mirror of
https://github.com/edera-dev/sprout.git
synced 2025-12-19 20:20:17 +00:00
document by hand much more of the sprout code
This commit is contained in:
@@ -19,20 +19,26 @@ pub struct DriverDeclaration {
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
/// Loads the driver specified by the [driver] declaration.
|
||||
fn load_driver(context: Rc<SproutContext>, driver: &DriverDeclaration) -> Result<()> {
|
||||
// Acquire the handle and device path of the loaded image.
|
||||
let sprout_image = uefi::boot::image_handle();
|
||||
let image_device_path_protocol =
|
||||
uefi::boot::open_protocol_exclusive::<LoadedImageDevicePath>(sprout_image)
|
||||
.context("unable to open loaded image device path protocol")?;
|
||||
|
||||
// Get the device path root of the sprout image.
|
||||
let mut full_path = utils::device_path_root(&image_device_path_protocol)?;
|
||||
|
||||
// Push the path of the driver from the root.
|
||||
full_path.push_str(&context.stamp(&driver.path));
|
||||
|
||||
info!("driver path: {}", full_path);
|
||||
|
||||
// Convert the path to a device path.
|
||||
let device_path = utils::text_to_device_path(&full_path)?;
|
||||
|
||||
// Load the driver image.
|
||||
let image = uefi::boot::load_image(
|
||||
sprout_image,
|
||||
uefi::boot::LoadImageSource::FromDevicePath {
|
||||
@@ -42,37 +48,55 @@ fn load_driver(context: Rc<SproutContext>, driver: &DriverDeclaration) -> Result
|
||||
)
|
||||
.context("unable to load image")?;
|
||||
|
||||
// Start the driver image, this is expected to return control to sprout.
|
||||
// There is no guarantee that the driver will actually return control as it is
|
||||
// just a standard EFI image.
|
||||
uefi::boot::start_image(image).context("unable to start driver image")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reconnects all handles to their controllers.
|
||||
/// This is effectively a UEFI stack reload in a sense.
|
||||
/// After we load all the drivers, we need to reconnect all of their handles
|
||||
/// so that filesystems are recognized again.
|
||||
fn reconnect() -> Result<()> {
|
||||
// Locate all of the handles in the UEFI stack.
|
||||
let handles = uefi::boot::locate_handle_buffer(SearchType::AllHandles)
|
||||
.context("unable to locate handles buffer")?;
|
||||
|
||||
for handle in handles.iter() {
|
||||
// ignore result as there is nothing we can do if it doesn't work.
|
||||
// Ignore the result as there is nothing we can do if reconnecting a controller fails.
|
||||
// This is also likely to fail in some cases but should fail safely.
|
||||
let _ = uefi::boot::connect_controller(*handle, None, None, true);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Load all the drivers specified in `drivers`.
|
||||
/// There is no driver order currently. This will reconnect all the controllers
|
||||
/// to all handles if at least one driver was loaded.
|
||||
pub fn load(
|
||||
context: Rc<SproutContext>,
|
||||
drivers: &BTreeMap<String, DriverDeclaration>,
|
||||
) -> Result<()> {
|
||||
// If there are no drivers, we don't need to do anything.
|
||||
if drivers.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
info!("loading drivers");
|
||||
|
||||
// Load all the drivers in no particular order.
|
||||
for (name, driver) in drivers {
|
||||
load_driver(context.clone(), driver).context(format!("unable to load driver: {}", name))?;
|
||||
}
|
||||
|
||||
// Reconnect all the controllers to all handles.
|
||||
reconnect().context("unable to reconnect drivers")?;
|
||||
info!("loaded drivers");
|
||||
|
||||
// We've now loaded all the drivers, so we can return.
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user