diff --git a/src/abi.rs b/src/abi.rs index a370d43..d1904fd 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -17,8 +17,8 @@ impl EFIFramebufferParams { pub fn from_graphics_output(graphics_output: &mut GraphicsOutput) -> Option { let mode = graphics_output.current_mode_info(); let (mask_red, mask_green, mask_blue, mask_reserved) = match mode.pixel_format() { - PixelFormat::Rgb => (0x0000_00ff, 0x0000_ff00, 0x00ff_0000, 0xff00_000), - PixelFormat::Bgr => (0x00ff_0000, 0x0000_ff00, 0x0000_00ff, 0xff00_000), + PixelFormat::Rgb => (0x0000_00ff, 0x0000_ff00, 0x00ff_0000, 0xff00_0000), + PixelFormat::Bgr => (0x00ff_0000, 0x0000_ff00, 0x0000_00ff, 0xff00_0000), PixelFormat::Bitmask => { let bitmask = mode.pixel_bitmask()?; (bitmask.red, bitmask.green, bitmask.blue, bitmask.reserved) @@ -45,34 +45,64 @@ impl EFIFramebufferParams { } } -#[cfg_attr(target_pointer_width = "64", repr(C, align(8)))] -#[cfg_attr(target_pointer_width = "32", repr(C, align(4)))] -pub struct ModuleDirectoryElem { - ident: ModInfo, - size: u32, - data: T, +/// Single TLV in the metadata buffer. +/// In the FreeBSD kernel would be placed in `preload_metadata` +pub enum PreloadDirectoryElem<'a> { + /// Module name (MOD_NAME) + Name(&'a str), + /// Module type (MOD_TYPE) + Type(&'a str), + /// Module parameters (MOD_ARGS) + Args(&'a str), + // TODO: figure out how to make this pointer safer + /// Module address (MOD_ADDR) + LoadAddress(*const u8), + /// Module size (MOD_SIZE) + Size(usize), + /// Type-speicfic metadata (MOD_METADATA) + Metadata(FileMetadataType, &'a [u8]), + End, } +impl<'a> PreloadDirectoryElem<'a> { + fn copy_str(data: &str, output: &mut [u8]) -> Option { + output[..data.len()].copy_from_slice(data.as_bytes()); + output[data.len()] = 0; + data.len().checked_add(1)?.try_into().ok() + } -#[repr(C)] -pub struct FileMetadataElem { - size: usize, - typ: FileMetadataType, - addr: *const T, - next: Option<*const FileMetadataElem>, - data: T, -} - -#[repr(u32)] -pub enum ModInfo { - End = 0, - Name = 1, - Type = 2, - Addr = 3, - Size = 4, - Args = 6, + pub fn copy_to_output<'b>(&'a self, output: &'b mut [u8]) -> Option<&'b mut [u8]> { + let usize_size = core::mem::size_of::(); + + let (tag, length) = match self { + Self::Name(name) => (1u32, Self::copy_str(name, &mut output[8..])?), + Self::Type(typ) => (2u32, Self::copy_str(typ, &mut output[8..])?), + Self::Args(args) => (6u32, Self::copy_str(args, &mut output[8..])?), + Self::LoadAddress(addr) => { + output[8..(8 + usize_size)].copy_from_slice(&(*addr as usize).to_ne_bytes()); + (3u32, usize_size as u32) + } + Self::Size(size) => { + output[8..(8 + usize_size)].copy_from_slice(&size.to_ne_bytes()); + (4u32, usize_size as u32) + } + Self::Metadata(typ, metadata) => { + output[8..(8 + metadata.len())].copy_from_slice(metadata); + (0x8000 | (*typ as u32), metadata.len() as u32) + } + Self::End => (0u32, 0u32), + }; + + output[..4].copy_from_slice(&tag.to_ne_bytes()); + output[4..8].copy_from_slice(&length.to_ne_bytes()); + + let aligned_length = ((length as usize + usize_size - 1) / usize_size) * usize_size; + + Some(&mut output[(aligned_length + 8)..]) + } } +#[derive(Debug, Copy, Clone)] #[repr(u16)] pub enum FileMetadataType { AoutExecHeader = 1,