Start designing Serialize trait
This commit is contained in:
parent
974cfd8ad9
commit
5a86c41d07
212
src/abi.rs
212
src/abi.rs
|
@ -1,5 +1,21 @@
|
|||
extern crate alloc;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use uefi::proto::console::gop::{GraphicsOutput, PixelFormat};
|
||||
|
||||
/// Serialize object into a buffer for FreeBSD
|
||||
pub trait Serialize {
|
||||
/// Output buffer must be aligned to this size
|
||||
fn alignment() -> usize;
|
||||
|
||||
/// Calculate output size of object, from base address to final byte written
|
||||
fn size(&self) -> usize;
|
||||
|
||||
/// Serliaze data into a buffer. Buffer must be aligned at alignment.
|
||||
fn serialize(&self, out: &mut [u8]);
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct EFIFramebufferParams {
|
||||
pub addr: u64,
|
||||
|
@ -45,76 +61,142 @@ impl EFIFramebufferParams {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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),
|
||||
impl Serialize for EFIFramebufferParams {
|
||||
fn alignment() -> usize {
|
||||
4
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
core::mem::size_of::<Self>()
|
||||
}
|
||||
|
||||
fn serialize(&self, out: &mut [u8]) {
|
||||
// we're already repr(C) so just copy
|
||||
out.copy_from_slice(unsafe {
|
||||
core::slice::from_raw_parts(
|
||||
self as *const Self as *const u8,
|
||||
core::mem::size_of_val(self),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[repr(u32)]
|
||||
/// Tag in the module info TLV
|
||||
pub enum ModuleInfoType {
|
||||
/// Module name (MODINFO_NAME)
|
||||
Name = 0x1,
|
||||
/// Module type (MODINFO_TYPE)
|
||||
Type = 0x2,
|
||||
// TODO: figure out how to make this pointer safer
|
||||
/// Module address (MOD_ADDR)
|
||||
LoadAddress(*const u8),
|
||||
/// Module size (MOD_SIZE)
|
||||
/// Module address (MODINFO_ADDR)
|
||||
LoadAddress = 0x3,
|
||||
/// Module size (MODINFO_SIZE)
|
||||
Size = 0x4,
|
||||
/// Module parameters (MODINFO_ARGS)
|
||||
Args = 0x6,
|
||||
|
||||
/// a.out header (MODINFOMD_AOUTEXEC)
|
||||
AoutExecHeader = 0x8001,
|
||||
/// ELF header (MODINFOMD_ELFHDR)
|
||||
ElfHeader = 0x8002,
|
||||
/// Start virtual address of symtab/strtab (MODINFOMD_SSYM)
|
||||
StartSymbols = 0x8003,
|
||||
/// End virtual address of symtab/strtab (MODINFOMD_SSYM)
|
||||
EndSymbols = 0x8004,
|
||||
/// Base virtual address of `PT_DYNAMIC` segment (MODINFOMD_DYNAMIC)
|
||||
Dynamic = 0x8005,
|
||||
/// Section header table (MODINFOMD_SHDR)
|
||||
SectionHeader = 0x8009,
|
||||
/// Base virtual address of constructors (MODINFOMD_CTORS_ADDR)
|
||||
CtorsAddress = 0x800a,
|
||||
/// Size of constructors (MODINFOMD_CTORS_SIZE)
|
||||
CtorsSize = 0x800b,
|
||||
/// Pointer to firmware object, on EFI this means Runtime SystemTable (MODINFOMD_FW_HANDLE)
|
||||
FirmwareHandle = 0x800c,
|
||||
/// Crypto key buffer, used for geli (MODINFOMD_KEYBUF)
|
||||
KeyBuffer = 0x800d,
|
||||
/// Console font (MODINFOMD_FONT)
|
||||
Font = 0x800e,
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
/// Base virtual address of device tree (MODINFOMD_DTBP)
|
||||
DeviceTreePointer = 0x9003,
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
/// EFI memory map (MODINFOMD_EFI_MAP)
|
||||
EFIMemoryMap = 0x9004,
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
/// EFI framebuffer metadata (MODINFOMD_EFI_FB)
|
||||
EFIFrameBuffer = 0x9005,
|
||||
}
|
||||
|
||||
/// Value in the module info TLV
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ModuleInfoValue {
|
||||
StaticString(&'static str),
|
||||
String(String),
|
||||
// TODO: figure out how to make this pointer safer
|
||||
Pointer(*const u8),
|
||||
Size(usize),
|
||||
/// Type-speicfic metadata (MOD_METADATA)
|
||||
Metadata(FileMetadataType, &'a [u8]),
|
||||
End,
|
||||
Buffer(Vec<u8>),
|
||||
}
|
||||
|
||||
impl<'a> PreloadDirectoryElem<'a> {
|
||||
fn copy_str(data: &str, output: &mut [u8]) -> Option<u32> {
|
||||
output[..data.len()].copy_from_slice(data.as_bytes());
|
||||
output[data.len()] = 0;
|
||||
data.len().checked_add(1)?.try_into().ok()
|
||||
}
|
||||
|
||||
pub fn copy_to_output<'b>(&'a self, output: &'b mut [u8]) -> Option<&'b mut [u8]> {
|
||||
let usize_size = core::mem::size_of::<usize>();
|
||||
|
||||
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)..])
|
||||
impl ModuleInfoValue {
|
||||
fn serialize_str(s: &str, out: &mut [u8]) {
|
||||
out[..s.len()].copy_from_slice(s.as_bytes());
|
||||
out[s.len()] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[repr(u16)]
|
||||
pub enum FileMetadataType {
|
||||
AoutExecHeader = 1,
|
||||
ElfHeader = 2,
|
||||
StartSymbols = 3,
|
||||
EndSymbols = 4,
|
||||
Dynamic = 5,
|
||||
MB2Header = 6,
|
||||
SectionHeader = 9,
|
||||
CtorsAddress = 10,
|
||||
CtorsSize = 11,
|
||||
FirmwareHandle = 12,
|
||||
KeyBuffer = 13,
|
||||
Font = 14,
|
||||
impl Serialize for ModuleInfoValue {
|
||||
fn alignment() -> usize {
|
||||
4
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
match self {
|
||||
ModuleInfoValue::StaticString(s) => s.len() + 1,
|
||||
ModuleInfoValue::String(s) => s.len() + 1,
|
||||
ModuleInfoValue::Pointer(obj) => core::mem::size_of_val(obj),
|
||||
ModuleInfoValue::Size(obj) => core::mem::size_of_val(obj),
|
||||
ModuleInfoValue::Buffer(buf) => buf.len(),
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize(&self, out: &mut [u8]) {
|
||||
match self {
|
||||
ModuleInfoValue::StaticString(s) => Self::serialize_str(s, out),
|
||||
ModuleInfoValue::String(s) => Self::serialize_str(s, out),
|
||||
ModuleInfoValue::Pointer(p) => out.copy_from_slice(&usize::to_ne_bytes(*p as usize)),
|
||||
ModuleInfoValue::Size(p) => out.copy_from_slice(&usize::to_ne_bytes(*p)),
|
||||
ModuleInfoValue::Buffer(buf) => out.copy_from_slice(buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Key and value in the module info TLV
|
||||
/// TODO: figure out how to make this properly typesafe
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ModuleInfoItem {
|
||||
tag: ModuleInfoType,
|
||||
value: ModuleInfoValue,
|
||||
}
|
||||
|
||||
impl Serialize for ModuleInfoItem {
|
||||
fn alignment() -> usize {
|
||||
core::mem::size_of::<usize>()
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
8 + self.value.size()
|
||||
}
|
||||
|
||||
fn serialize(&self, out: &mut [u8]) {
|
||||
out[..4].copy_from_slice(&u32::to_ne_bytes(self.tag as u32));
|
||||
out[4..8].copy_from_slice(&u32::to_ne_bytes(self.value.size().try_into().unwrap()));
|
||||
self.value.serialize(&mut out[8..]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ fn main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
|
|||
staging_buf[..kernel.len()].copy_from_slice(&kernel);
|
||||
|
||||
let header =
|
||||
elf::ElfBytes::<NativeEndian>::minimal_parse(&staging_buf).expect("Failed to parse kernel");
|
||||
elf::ElfBytes::<NativeEndian>::minimal_parse(staging_buf).expect("Failed to parse kernel");
|
||||
|
||||
info!("Kernel is {:?}", header.ehdr.class);
|
||||
|
||||
|
|
Loading…
Reference in a new issue