Pass initrd to Linux
This commit is contained in:
parent
ee861e2fc0
commit
5e7bdfd5b5
|
@ -1,17 +1,17 @@
|
||||||
//! This module implements the protocols to hand an initrd to the
|
//! This module implements the protocols to hand an initrd to the
|
||||||
//! Linux kernel.
|
//! Linux kernel.
|
||||||
|
|
||||||
use core::{ffi::c_void, pin::Pin};
|
use core::{ffi::c_void, pin::Pin, ptr::slice_from_raw_parts_mut};
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::{boxed::Box, vec};
|
||||||
use uefi::{
|
use uefi::{
|
||||||
prelude::BootServices,
|
prelude::BootServices,
|
||||||
proto::{
|
proto::{
|
||||||
device_path::{DevicePath, FfiDevicePath},
|
device_path::{DevicePath, FfiDevicePath},
|
||||||
media::file::RegularFile,
|
media::file::{File, FileInfo, RegularFile},
|
||||||
Protocol,
|
Protocol,
|
||||||
},
|
},
|
||||||
unsafe_guid, Handle, Identify, Result, Status,
|
unsafe_guid, Handle, Identify, Result, ResultExt, Status,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The Linux kernel's initrd loading device path.
|
/// The Linux kernel's initrd loading device path.
|
||||||
|
@ -58,15 +58,47 @@ struct LoadFile2Protocol {
|
||||||
file: RegularFile,
|
file: RegularFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "efiapi" fn linux_initrd_load_file(
|
impl LoadFile2Protocol {
|
||||||
_this: &mut LoadFile2Protocol,
|
fn load_file(
|
||||||
|
&mut self,
|
||||||
_file_path: *const FfiDevicePath,
|
_file_path: *const FfiDevicePath,
|
||||||
_boot_policy: bool,
|
_boot_policy: bool,
|
||||||
_buffer_size: *mut usize,
|
buffer_size: *mut usize,
|
||||||
_buffer: *mut c_void,
|
buffer: *mut c_void,
|
||||||
|
) -> Result<()> {
|
||||||
|
let mut fs_info_buf = vec![0; 128];
|
||||||
|
let fs_info = self
|
||||||
|
.file
|
||||||
|
.get_info::<FileInfo>(&mut fs_info_buf)
|
||||||
|
.map_err(|_| Status::INVALID_PARAMETER)?;
|
||||||
|
let fs_size = usize::try_from(fs_info.file_size()).unwrap();
|
||||||
|
|
||||||
|
if buffer.is_null() || unsafe { *buffer_size } < fs_size {
|
||||||
|
unsafe {
|
||||||
|
*buffer_size = fs_size;
|
||||||
|
}
|
||||||
|
return Err(Status::BUFFER_TOO_SMALL.into());
|
||||||
|
};
|
||||||
|
|
||||||
|
let output_slice: &mut [u8] =
|
||||||
|
unsafe { &mut *slice_from_raw_parts_mut(buffer as *mut u8, *buffer_size) };
|
||||||
|
|
||||||
|
let read_bytes = self.file.read(output_slice).map_err(|e| e.status())?;
|
||||||
|
assert_eq!(read_bytes, unsafe { *buffer_size });
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "efiapi" fn raw_load_file(
|
||||||
|
this: &mut LoadFile2Protocol,
|
||||||
|
file_path: *const FfiDevicePath,
|
||||||
|
boot_policy: bool,
|
||||||
|
buffer_size: *mut usize,
|
||||||
|
buffer: *mut c_void,
|
||||||
) -> Status {
|
) -> Status {
|
||||||
// Linux doesn't like that.
|
this.load_file(file_path, boot_policy, buffer_size, buffer)
|
||||||
Status::NOT_FOUND
|
.status()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InitrdLoader {
|
pub struct InitrdLoader {
|
||||||
|
@ -78,7 +110,7 @@ pub struct InitrdLoader {
|
||||||
impl InitrdLoader {
|
impl InitrdLoader {
|
||||||
pub fn new(boot_services: &BootServices, handle: Handle, file: RegularFile) -> Result<Self> {
|
pub fn new(boot_services: &BootServices, handle: Handle, file: RegularFile) -> Result<Self> {
|
||||||
let mut proto = Box::pin(LoadFile2Protocol {
|
let mut proto = Box::pin(LoadFile2Protocol {
|
||||||
load_file: linux_initrd_load_file,
|
load_file: raw_load_file,
|
||||||
file,
|
file,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue