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};
|
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)]
|
#[repr(C)]
|
||||||
pub struct EFIFramebufferParams {
|
pub struct EFIFramebufferParams {
|
||||||
pub addr: u64,
|
pub addr: u64,
|
||||||
|
@ -45,76 +61,142 @@ impl EFIFramebufferParams {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Single TLV in the metadata buffer.
|
impl Serialize for EFIFramebufferParams {
|
||||||
/// In the FreeBSD kernel would be placed in `preload_metadata`
|
fn alignment() -> usize {
|
||||||
pub enum PreloadDirectoryElem<'a> {
|
4
|
||||||
/// Module name (MOD_NAME)
|
}
|
||||||
Name(&'a str),
|
|
||||||
/// Module type (MOD_TYPE)
|
fn size(&self) -> usize {
|
||||||
Type(&'a str),
|
core::mem::size_of::<Self>()
|
||||||
/// Module parameters (MOD_ARGS)
|
}
|
||||||
Args(&'a str),
|
|
||||||
|
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
|
// TODO: figure out how to make this pointer safer
|
||||||
/// Module address (MOD_ADDR)
|
/// Module address (MODINFO_ADDR)
|
||||||
LoadAddress(*const u8),
|
LoadAddress = 0x3,
|
||||||
/// Module size (MOD_SIZE)
|
/// 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),
|
Size(usize),
|
||||||
/// Type-speicfic metadata (MOD_METADATA)
|
Buffer(Vec<u8>),
|
||||||
Metadata(FileMetadataType, &'a [u8]),
|
|
||||||
End,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PreloadDirectoryElem<'a> {
|
impl ModuleInfoValue {
|
||||||
fn copy_str(data: &str, output: &mut [u8]) -> Option<u32> {
|
fn serialize_str(s: &str, out: &mut [u8]) {
|
||||||
output[..data.len()].copy_from_slice(data.as_bytes());
|
out[..s.len()].copy_from_slice(s.as_bytes());
|
||||||
output[data.len()] = 0;
|
out[s.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)..])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
impl Serialize for ModuleInfoValue {
|
||||||
#[repr(u16)]
|
fn alignment() -> usize {
|
||||||
pub enum FileMetadataType {
|
4
|
||||||
AoutExecHeader = 1,
|
}
|
||||||
ElfHeader = 2,
|
|
||||||
StartSymbols = 3,
|
fn size(&self) -> usize {
|
||||||
EndSymbols = 4,
|
match self {
|
||||||
Dynamic = 5,
|
ModuleInfoValue::StaticString(s) => s.len() + 1,
|
||||||
MB2Header = 6,
|
ModuleInfoValue::String(s) => s.len() + 1,
|
||||||
SectionHeader = 9,
|
ModuleInfoValue::Pointer(obj) => core::mem::size_of_val(obj),
|
||||||
CtorsAddress = 10,
|
ModuleInfoValue::Size(obj) => core::mem::size_of_val(obj),
|
||||||
CtorsSize = 11,
|
ModuleInfoValue::Buffer(buf) => buf.len(),
|
||||||
FirmwareHandle = 12,
|
}
|
||||||
KeyBuffer = 13,
|
}
|
||||||
Font = 14,
|
|
||||||
|
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);
|
staging_buf[..kernel.len()].copy_from_slice(&kernel);
|
||||||
|
|
||||||
let header =
|
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);
|
info!("Kernel is {:?}", header.ehdr.class);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue