Pass initrd to Linux

This commit is contained in:
Julian Stecklina 2022-11-23 00:52:38 +01:00
parent ee861e2fc0
commit 5e7bdfd5b5
1 changed files with 45 additions and 13 deletions

View File

@ -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,
}); });