mirror of
https://github.com/edera-dev/sprout.git
synced 2025-12-20 01:00:17 +00:00
add efi shell so that chainloading multiple items can be tested
This commit is contained in:
@@ -1,10 +1,8 @@
|
||||
use crate::config::ChainloaderConfiguration;
|
||||
use crate::utils::text_to_device_path;
|
||||
use crate::utils;
|
||||
use log::info;
|
||||
use uefi::proto::device_path::{
|
||||
DevicePath, LoadedImageDevicePath,
|
||||
text::{AllowShortcuts, DisplayOnly},
|
||||
};
|
||||
use uefi::CString16;
|
||||
use uefi::proto::device_path::LoadedImageDevicePath;
|
||||
use uefi::proto::loaded_image::LoadedImage;
|
||||
|
||||
pub fn chainloader(configuration: ChainloaderConfiguration) {
|
||||
@@ -13,28 +11,12 @@ pub fn chainloader(configuration: ChainloaderConfiguration) {
|
||||
uefi::boot::open_protocol_exclusive::<LoadedImageDevicePath>(sprout_image)
|
||||
.expect("unable to open loaded image device path protocol");
|
||||
|
||||
let image_device_path: &DevicePath = &image_device_path_protocol;
|
||||
let mut full_path = image_device_path
|
||||
.node_iter()
|
||||
.filter_map(|item| {
|
||||
let item = item
|
||||
.to_string(DisplayOnly(false), AllowShortcuts(false))
|
||||
.expect("unable to convert device path to string");
|
||||
if item.to_string().contains("(") {
|
||||
Some(item)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(|item| item.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("/");
|
||||
full_path.push('/');
|
||||
let mut full_path = utils::device_path_root(&image_device_path_protocol);
|
||||
full_path.push_str(&configuration.path);
|
||||
|
||||
info!("path={}", full_path);
|
||||
|
||||
let device_path = text_to_device_path(&full_path);
|
||||
let device_path = utils::text_to_device_path(&full_path);
|
||||
|
||||
let image = uefi::boot::load_image(
|
||||
sprout_image,
|
||||
@@ -45,10 +27,31 @@ pub fn chainloader(configuration: ChainloaderConfiguration) {
|
||||
)
|
||||
.expect("failed to load image");
|
||||
|
||||
let image_device_path_protocol = uefi::boot::open_protocol_exclusive::<LoadedImage>(image)
|
||||
let mut loaded_image_protocol = uefi::boot::open_protocol_exclusive::<LoadedImage>(image)
|
||||
.expect("unable to open loaded image protocol");
|
||||
|
||||
let (base, size) = image_device_path_protocol.info();
|
||||
let options = configuration.options.join(" ");
|
||||
if !options.is_empty() {
|
||||
let options = Box::new(
|
||||
CString16::try_from(&options[..])
|
||||
.expect("unable to convert chainloader options to CString16"),
|
||||
);
|
||||
info!("options={}", options);
|
||||
|
||||
if options.num_bytes() > u32::MAX as usize {
|
||||
panic!("chainloader options too large");
|
||||
}
|
||||
|
||||
// SAFETY: options size is checked to validate it is safe to pass.
|
||||
// Additionally, the pointer is allocated and retained on the heap which makes
|
||||
// passing the options pointer safe to the next image.
|
||||
unsafe {
|
||||
loaded_image_protocol
|
||||
.set_load_options(options.as_ptr() as *const u8, options.num_bytes() as u32);
|
||||
}
|
||||
}
|
||||
|
||||
let (base, size) = loaded_image_protocol.info();
|
||||
info!("loaded image base={:#x} size={:#x}", base.addr(), size);
|
||||
uefi::boot::start_image(image).expect("failed to start image");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user