Handle alignment and size in Serialize

This commit is contained in:
Artemis Tosini 2024-08-04 03:37:32 +00:00
parent aa44e84ffc
commit a0a26b745f
Signed by: artemist
GPG key ID: EE5227935FE3FF18
3 changed files with 27 additions and 18 deletions

View file

@ -3,6 +3,12 @@ use alloc::string::String;
use alloc::vec::Vec; use alloc::vec::Vec;
use uefi::proto::console::gop::{GraphicsOutput, PixelFormat}; use uefi::proto::console::gop::{GraphicsOutput, PixelFormat};
fn align_slice(unaligned: &mut [u8], alignment: usize) -> &mut [u8] {
let base_addr = &unaligned[0] as *const u8 as usize;
let offset = base_addr.next_multiple_of(alignment) - base_addr;
&mut unaligned[offset..]
}
/// Serialize object into a buffer for FreeBSD /// Serialize object into a buffer for FreeBSD
pub trait Serialize { pub trait Serialize {
/// Output buffer must be aligned to this size /// Output buffer must be aligned to this size
@ -11,8 +17,18 @@ pub trait Serialize {
/// Calculate output size of object, from base address to final byte written /// Calculate output size of object, from base address to final byte written
fn size(&self) -> usize; fn size(&self) -> usize;
/// Serliaze data into a buffer. Buffer must be aligned at alignment. /// Serliaze data into a buffer. Buffer must be aligned at alignment and size of size().
fn serialize(&self, out: &mut [u8]); fn serialize_raw(&self, out: &mut [u8]);
/// Serialize to an unaligned buffer, returning the end address
#[must_use]
fn serialize_unaligned<'a>(&self, out: &'a mut [u8]) -> &'a mut [u8] {
let aligned = align_slice(out, Self::alignment());
let size = self.size();
self.serialize_raw(&mut aligned[..size]);
&mut aligned[size..]
}
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -70,7 +86,7 @@ impl Serialize for EFIFramebufferParams {
core::mem::size_of::<Self>() core::mem::size_of::<Self>()
} }
fn serialize(&self, out: &mut [u8]) { fn serialize_raw(&self, out: &mut [u8]) {
// we're already repr(C) so just copy // we're already repr(C) so just copy
out.copy_from_slice(unsafe { out.copy_from_slice(unsafe {
core::slice::from_raw_parts( core::slice::from_raw_parts(
@ -166,7 +182,7 @@ impl Serialize for ModuleInfoValue {
} }
} }
fn serialize(&self, out: &mut [u8]) { fn serialize_raw(&self, out: &mut [u8]) {
match self { match self {
ModuleInfoValue::StaticString(s) => Self::serialize_str(s, out), ModuleInfoValue::StaticString(s) => Self::serialize_str(s, out),
ModuleInfoValue::String(s) => Self::serialize_str(s, out), ModuleInfoValue::String(s) => Self::serialize_str(s, out),
@ -206,9 +222,9 @@ impl Serialize for ModuleInfoItem {
8 + self.value.size() 8 + self.value.size()
} }
fn serialize(&self, out: &mut [u8]) { fn serialize_raw(&self, out: &mut [u8]) {
out[..4].copy_from_slice(&u32::to_ne_bytes(self.tag as u32)); 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())); out[4..8].copy_from_slice(&u32::to_ne_bytes(self.value.size().try_into().unwrap()));
self.value.serialize(&mut out[8..]); self.value.serialize_raw(&mut out[8..]);
} }
} }

View file

@ -6,7 +6,7 @@ mod object;
mod staging; mod staging;
use abi::{ModuleInfoItem, Serialize}; use abi::{ModuleInfoItem, Serialize};
use log::{info}; use log::info;
use object::{Kernel, Module}; use object::{Kernel, Module};
use uefi::{fs::FileSystem, prelude::*}; use uefi::{fs::FileSystem, prelude::*};
@ -44,11 +44,10 @@ fn main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
let staging = staging::allocate_staging(system_table.boot_services(), alloc_size); let staging = staging::allocate_staging(system_table.boot_services(), alloc_size);
{ {
let mut aligned = align_slice(staging, Kernel::alignment()); let mut next = staging;
kernel.serialize(aligned); next = kernel.serialize_unaligned(next);
for item in kernel_metadata.iter() { for item in kernel_metadata.iter() {
aligned = align_slice(aligned, ModuleInfoItem::alignment()); next = item.serialize_unaligned(next);
item.serialize(aligned);
} }
} }
@ -56,9 +55,3 @@ fn main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
system_table.boot_services().stall(10_000_000); system_table.boot_services().stall(10_000_000);
} }
} }
fn align_slice(unaligned: &mut [u8], alignment: usize) -> &mut [u8] {
let base_addr = &unaligned[0] as *const u8 as usize;
let offset = base_addr.next_multiple_of(alignment) - base_addr;
&mut unaligned[offset..]
}

View file

@ -146,7 +146,7 @@ impl<'a> Serialize for Kernel<'a> {
self.size_load_segments() + self.size_symbols() self.size_load_segments() + self.size_symbols()
} }
fn serialize(&self, out: &mut [u8]) { fn serialize_raw(&self, out: &mut [u8]) {
// Each section is rounded to sizeof(long) // Each section is rounded to sizeof(long)
let end_load = self.size_load_segments(); let end_load = self.size_load_segments();
self.serialize_load_segments(&mut out[..end_load]); self.serialize_load_segments(&mut out[..end_load]);