mirror of
https://github.com/edera-dev/sprout.git
synced 2025-12-19 17:30:17 +00:00
fix unregistering of media loader
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use crate::context::SproutContext;
|
||||
use crate::utils;
|
||||
use crate::utils::media_loader::MediaLoaderHandle;
|
||||
use crate::utils::media_loader::constants::LINUX_EFI_INITRD_MEDIA_GUID;
|
||||
use crate::utils::media_loader::constants::linux::LINUX_EFI_INITRD_MEDIA_GUID;
|
||||
use anyhow::{Context, Result, bail};
|
||||
use log::{error, info};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -74,10 +74,10 @@ pub fn chainload(context: Rc<SproutContext>, configuration: &ChainloadConfigurat
|
||||
let initrd_path = context.stamp(linux_initrd);
|
||||
let content = utils::read_file_contents(context.root().loaded_image_path()?, &initrd_path)
|
||||
.context("unable to read linux initrd")?;
|
||||
initrd_handle = Some(
|
||||
let handle =
|
||||
MediaLoaderHandle::register(LINUX_EFI_INITRD_MEDIA_GUID, content.into_boxed_slice())
|
||||
.context("unable to register linux initrd")?,
|
||||
);
|
||||
.context("unable to register linux initrd")?;
|
||||
initrd_handle = Some(handle);
|
||||
}
|
||||
|
||||
let (base, size) = loaded_image_protocol.info();
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::{
|
||||
self,
|
||||
media_loader::{
|
||||
MediaLoaderHandle,
|
||||
constants::{
|
||||
constants::xen::{
|
||||
XEN_EFI_CONFIG_MEDIA_GUID, XEN_EFI_KERNEL_MEDIA_GUID, XEN_EFI_RAMDISK_MEDIA_GUID,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -13,7 +13,7 @@ pub mod constants;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct MediaLoaderProtocol {
|
||||
struct MediaLoaderProtocol {
|
||||
pub load_file: unsafe extern "efiapi" fn(
|
||||
this: *mut MediaLoaderProtocol,
|
||||
file_path: *const DevicePathProtocol,
|
||||
@@ -25,14 +25,24 @@ pub struct MediaLoaderProtocol {
|
||||
pub length: usize,
|
||||
}
|
||||
|
||||
/// Represents a media loader which has been registered in the UEFI stack.
|
||||
/// You MUST call [MediaLoaderHandle::unregister] when ready to unregister.
|
||||
/// [Drop] is not implemented for this type.
|
||||
pub struct MediaLoaderHandle {
|
||||
pub guid: Guid,
|
||||
pub handle: Handle,
|
||||
pub protocol: *mut MediaLoaderProtocol,
|
||||
pub path: *mut DevicePath,
|
||||
guid: Guid,
|
||||
handle: Handle,
|
||||
protocol: *mut MediaLoaderProtocol,
|
||||
path: *mut DevicePath,
|
||||
}
|
||||
|
||||
impl MediaLoaderHandle {
|
||||
/// The behavior of this function is derived from how Linux calls it.
|
||||
///
|
||||
/// Linux calls this function by first passing a NULL [buffer].
|
||||
/// We must set the size of the buffer it should allocate in [buffer_size].
|
||||
/// The next call will pass a buffer of the right size, and we should copy
|
||||
/// data into that buffer, checking whether it is safe to copy based on
|
||||
/// the buffer size.
|
||||
unsafe extern "efiapi" fn load_file(
|
||||
this: *mut MediaLoaderProtocol,
|
||||
file_path: *const DevicePathProtocol,
|
||||
@@ -44,10 +54,14 @@ impl MediaLoaderHandle {
|
||||
return Status::INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Boot policy must not be true, as that's special behavior that is irrelevant
|
||||
// for the media loader concept.
|
||||
if boot_policy == Boolean::TRUE {
|
||||
return Status::UNSUPPORTED;
|
||||
}
|
||||
|
||||
// SAFETY: Validated as safe because this is checked to be non-null. It is the caller's
|
||||
// responsibility to ensure that the right pointer is passed for [this].
|
||||
unsafe {
|
||||
if (*this).length == 0 || (*this).address.is_null() {
|
||||
return Status::NOT_FOUND;
|
||||
@@ -65,7 +79,7 @@ impl MediaLoaderHandle {
|
||||
Status::SUCCESS
|
||||
}
|
||||
|
||||
pub fn device_path(guid: Guid) -> Box<DevicePath> {
|
||||
fn device_path(guid: Guid) -> Box<DevicePath> {
|
||||
let mut path = Vec::new();
|
||||
let path = DevicePathBuilder::with_vec(&mut path)
|
||||
.push(&Vendor {
|
||||
@@ -167,8 +181,15 @@ impl MediaLoaderHandle {
|
||||
)
|
||||
.context("unable to uninstall media loader load file handle")?;
|
||||
|
||||
let _path = Box::from_raw(self.path);
|
||||
let _protocol = Box::from_raw(self.protocol);
|
||||
let path = Box::from_raw(self.path);
|
||||
let protocol = Box::from_raw(self.protocol);
|
||||
let slice =
|
||||
std::ptr::slice_from_raw_parts_mut(protocol.address as *mut u8, protocol.length);
|
||||
let data = Box::from_raw(slice);
|
||||
|
||||
drop(path);
|
||||
drop(protocol);
|
||||
drop(data);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
use uefi::{Guid, guid};
|
||||
/// These GUIDs are specific to Linux itself.
|
||||
pub mod linux {
|
||||
use uefi::{Guid, guid};
|
||||
|
||||
pub const LINUX_EFI_INITRD_MEDIA_GUID: Guid = guid!("5568e427-68fc-4f3d-ac74-ca555231cc68");
|
||||
/// The device path GUID for the Linux EFI initrd.
|
||||
pub const LINUX_EFI_INITRD_MEDIA_GUID: Guid = guid!("5568e427-68fc-4f3d-ac74-ca555231cc68");
|
||||
}
|
||||
|
||||
pub const XEN_EFI_CONFIG_MEDIA_GUID: Guid = guid!("bf61f458-a28e-46cd-93d7-07dac5e8cd66");
|
||||
pub const XEN_EFI_KERNEL_MEDIA_GUID: Guid = guid!("4010c8bf-6ced-40f5-a53f-e820aee8f34b");
|
||||
pub const XEN_EFI_RAMDISK_MEDIA_GUID: Guid = guid!("5db1fd01-c3cb-4812-b2ba-8791e52d4a89");
|
||||
/// These GUIDs were created by Edera to support Xen loading data
|
||||
/// from Sprout and other EFI bootloaders.
|
||||
pub mod xen {
|
||||
use uefi::{Guid, guid};
|
||||
|
||||
/// The device path GUID for the Xen EFI config.
|
||||
pub const XEN_EFI_CONFIG_MEDIA_GUID: Guid = guid!("bf61f458-a28e-46cd-93d7-07dac5e8cd66");
|
||||
/// The device path GUID for the Xen EFI config.
|
||||
pub const XEN_EFI_KERNEL_MEDIA_GUID: Guid = guid!("4010c8bf-6ced-40f5-a53f-e820aee8f34b");
|
||||
pub const XEN_EFI_RAMDISK_MEDIA_GUID: Guid = guid!("5db1fd01-c3cb-4812-b2ba-8791e52d4a89");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user