diff options
author | Ard Biesheuvel <ardb@kernel.org> | 2023-10-10 12:39:40 +0200 |
---|---|---|
committer | Ard Biesheuvel <ardb@kernel.org> | 2023-10-10 12:39:40 +0200 |
commit | deec400c2814c46f42170f8ad2bcfa0c3f8dbe47 (patch) | |
tree | 4ec94a14efcfefd8916b388cec3a583f99b25bfa | |
parent | bc42e7aea20b1344893ab00a8ebf45e22337c240 (diff) | |
download | efilite-deec400c2814c46f42170f8ad2bcfa0c3f8dbe47.tar.gz |
WIP
-rw-r--r-- | src/console.rs | 4 | ||||
-rw-r--r-- | src/fwcfg.rs | 120 | ||||
-rw-r--r-- | src/main.rs | 11 |
3 files changed, 57 insertions, 78 deletions
diff --git a/src/console.rs b/src/console.rs index 0d251ac..9eea861 100644 --- a/src/console.rs +++ b/src/console.rs @@ -3,7 +3,7 @@ // Author: Ard Biesheuvel <ardb@google.com> use core::fmt::Write; -use log::{Level, Metadata, Record}; +use log::{Metadata, Record}; use mmio::{Allow, Deny, VolBox}; use once_cell::race::OnceBox; use spinning_top::Spinlock; @@ -64,7 +64,7 @@ impl Write for DumbSerialConsoleWriter<'_> { impl log::Log for DumbSerialConsole { fn enabled(&self, metadata: &Metadata) -> bool { - metadata.level() <= Level::Info + metadata.level() <= log::max_level() } fn log(&self, record: &Record) { diff --git a/src/fwcfg.rs b/src/fwcfg.rs index 57c4e1a..c028caf 100644 --- a/src/fwcfg.rs +++ b/src/fwcfg.rs @@ -4,7 +4,6 @@ use crate::{efi, MemoryType, Placement}; use alloc::collections::BTreeMap; -use alloc::vec; use alloc::vec::Vec; use core::{ fmt, @@ -62,10 +61,6 @@ struct FwCfgFile { filename: FwCfgFilename, } -trait Zeroed<T> { - fn zeroed() -> T; -} - impl FwCfgFile { pub fn size(&self) -> usize { u32::to_be(self._size) as usize @@ -76,18 +71,6 @@ impl FwCfgFile { } } -impl Zeroed<FwCfgFile> for FwCfgFile { - fn zeroed() -> FwCfgFile { - FwCfgFile { - _size: 0, - _select: 0, - reserved: 0, - filename: [0u8; 56], - } - } -} - -#[derive(Copy, Clone)] struct FwCfgFileIterator<'a, T> { count: u32, next: u32, @@ -97,19 +80,24 @@ struct FwCfgFileIterator<'a, T> { phantom: PhantomData<T>, } -impl<'a, T: Clone + Zeroed<T>> FwCfgFileIterator<'a, T> { - pub fn to_vec(&self) -> Vec<T> { - let slice = pin!(vec![T::zeroed(); self.count as usize].into_boxed_slice()); - let size = slice.len() * size_of::<T>(); +impl<'a, T> FwCfgFileIterator<'a, T> { + pub fn to_vec(&self) -> Option<Vec<T>> { + let len = self.count as usize; + let mut v = Vec::<T>::with_capacity(len); + let size = len * size_of::<T>(); let mut mmio = self.fwcfg.0.lock(); mmio.selector.write(u16::to_be(self.select)); fence(Ordering::Release); - mmio.dma_transfer(0, self.offset as u32).ok(); - mmio.dma_transfer(&**slice as *const [T] as *const () as u64, size as u32) - .ok(); - slice.clone().into_vec() + if self.offset > 0 { + mmio.dma_transfer(0, self.offset as u32).ok()?; + } + mmio.dma_transfer(v.as_mut_ptr() as u64, size as u32).ok()?; + unsafe { + v.set_len(len); + } + Some(v) } } @@ -162,6 +150,7 @@ impl FwCfgMmio { }); self.dmacontrol.write(u64::to_be(&*xfer as *const _ as u64)); + fence(Ordering::Release); let control = unsafe { VolBox::<u32, Allow, Deny>::new(&xfer.control as *const _ as *mut u32) }; @@ -178,7 +167,7 @@ impl FwCfgMmio { #[derive(Copy, Clone, Debug)] #[repr(C)] pub struct FwCfgLoaderAllocate { - pub filename: [u8; 56], + pub filename: FwCfgFilename, pub alignment: u32, pub zone: u8, } @@ -211,7 +200,6 @@ pub struct FwCfgLoaderWritePointer { pub size: u8, } -#[derive(Copy, Clone)] #[repr(C)] pub union FwCfgLoaderUnion { pub allocate: FwCfgLoaderAllocate, @@ -220,7 +208,7 @@ pub union FwCfgLoaderUnion { pub write_pointer: FwCfgLoaderWritePointer, } -#[derive(Copy, Clone, Debug)] +#[derive(Debug)] #[allow(dead_code)] #[repr(u32)] pub enum FwCfgLoaderCmdType { @@ -231,30 +219,12 @@ pub enum FwCfgLoaderCmdType { FwCfgLoaderCmdWritePointer, } -#[derive(Copy, Clone)] #[repr(C)] pub struct FwCfgLoaderEntry { pub _type: FwCfgLoaderCmdType, pub u: FwCfgLoaderUnion, } -impl Zeroed<FwCfgLoaderEntry> for FwCfgLoaderEntry { - fn zeroed() -> FwCfgLoaderEntry { - FwCfgLoaderEntry { - _type: FwCfgLoaderCmdType::FwCfgLoaderCmdUnused, - u: FwCfgLoaderUnion { - write_pointer: FwCfgLoaderWritePointer { - pointer: [0u8; 56], - pointee: [0u8; 56], - pointer_offset: 0, - pointee_offset: 0, - size: 0, - }, - }, - } - } -} - impl fmt::Debug for FwCfgLoaderEntry { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut out = f.debug_struct("FwCfgLoaderEntry"); @@ -299,17 +269,15 @@ impl FwCfg { let f = self.files().find(|f| { from_utf8(&f.filename).map_or(false, |s| s.trim_end_matches("\0") == "etc/table-loader") })?; - Some( - FwCfgFileIterator { - count: (f.size() / size_of::<FwCfgLoaderEntry>()) as u32, - next: 0, - select: f.select(), - offset: 0, - fwcfg: self, - phantom: PhantomData, - } - .to_vec() - ) + FwCfgFileIterator { + count: (f.size() / size_of::<FwCfgLoaderEntry>()) as u32, + next: 0, + select: f.select(), + offset: 0, + fwcfg: self, + phantom: PhantomData, + } + .to_vec() } pub fn from_fdt_node(node: fdt::node::FdtNode) -> Option<FwCfg> { @@ -360,9 +328,10 @@ impl FwCfg { loadbuffer: &'a mut [MaybeUninit<u8>], size: usize, data_cfg: u16, - ) -> Result<&'a mut [u8], ()> { + ) -> Result<&'a mut [u8], &'static str> { let size = size.min(loadbuffer.len()); - self.dma_read(loadbuffer, size, data_cfg)?; + self.dma_read(loadbuffer, size, data_cfg) + .or(Err("DMA read failed"))?; if size < loadbuffer.len() { loadbuffer.split_at_mut(size).1.fill(MaybeUninit::zeroed()); } @@ -394,7 +363,7 @@ impl FwCfg { self.get_loader(CFG_INITRD_SIZE, CFG_INITRD_DATA) } - pub fn load_firmware_tables(&self) -> Result<*const u8, ()> { + pub fn load_firmware_tables(&self) -> Result<*const u8, &'static str> { FwCfgTableLoader::new(self).load_firmware_tables() } } @@ -412,27 +381,32 @@ impl<'a> FwCfgTableLoader<'a> { } } - fn allocate(&mut self, allocate: &FwCfgLoaderAllocate) -> Result<(), ()> { + fn allocate(&mut self, allocate: &FwCfgLoaderAllocate) -> Result<(), &'static str> { let f = self .fwcfg .files() .find(|f| f.filename == allocate.filename) - .ok_or(())?; + .ok_or("Failed to locate blob file")?; let b = efi::memmap::allocate_pages( efi::memmap::size_to_pages(f.size()), MemoryType::EfiACPIReclaimMemory, Placement::Anywhere, ) - .ok_or(())?; + .ok_or("Failed to allocate blob memory")?; let b = self.fwcfg.load_file_mut(b, f.size(), f.select())?; self.loaded_tables.insert(f.filename, b); Ok(()) } - fn add_pointer(&mut self, add_pointer: &FwCfgLoaderAddPointer) -> Result<(), ()> { + fn add_pointer(&mut self, add_pointer: &FwCfgLoaderAddPointer) -> Result<(), &'static str> { let tables = &mut self.loaded_tables; - let addend = tables.get(&add_pointer.pointee).ok_or(())?.as_ptr(); - let pointer = tables.get_mut(&add_pointer.pointer).ok_or(())?; + let addend = tables + .get(&add_pointer.pointee) + .ok_or("Unknown pointee blob")? + .as_ptr(); + let pointer = tables + .get_mut(&add_pointer.pointer) + .ok_or("Unknown pointer blob")?; let offset = add_pointer.offset as usize; match add_pointer.size { @@ -445,12 +419,14 @@ impl<'a> FwCfgTableLoader<'a> { Ok(()) } - fn add_checksum(&mut self, add_checksum: &FwCfgLoaderAddChecksum) -> Result<(), ()> { + fn add_checksum(&mut self, add_checksum: &FwCfgLoaderAddChecksum) -> Result<(), &'static str> { let tables = &mut self.loaded_tables; let start = add_checksum.start as usize; let end = start + add_checksum.size as usize; let offset = add_checksum.result_offset as usize; - let table = tables.get_mut(&add_checksum.filename).ok_or(())?; + let table = tables + .get_mut(&add_checksum.filename) + .ok_or("Unknown blob for checksum")?; let mut checksum = 0u8; table[start..end] .iter() @@ -459,8 +435,8 @@ impl<'a> FwCfgTableLoader<'a> { Ok(()) } - pub fn load_firmware_tables(&mut self) -> Result<*const u8, ()> { - for entry in self.fwcfg.loader().ok_or(())? { + pub fn load_firmware_tables(&mut self) -> Result<*const u8, &'static str> { + for entry in self.fwcfg.loader().ok_or("Failed to access table loader")? { match entry._type { FwCfgLoaderCmdType::FwCfgLoaderCmdAllocate => unsafe { self.allocate(&entry.u.allocate) @@ -473,7 +449,7 @@ impl<'a> FwCfgTableLoader<'a> { }, //FwCfgLoaderCmdType::FwCfgLoaderCmdWritePointer => unsafe { //}, - _ => Err(()), + _ => Err("Unsupported table loader command"), }?; } let rsdp = self @@ -482,7 +458,7 @@ impl<'a> FwCfgTableLoader<'a> { .find(|(&k, &ref _v)| { from_utf8(&k).map_or(false, |s| s.trim_end_matches("\0") == "etc/acpi/rsdp") }) - .ok_or(())? + .ok_or("Failed to locate RSDP table")? .1; Ok(rsdp.as_ptr()) } diff --git a/src/main.rs b/src/main.rs index a30911c..58b5a07 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,7 +31,7 @@ mod rng; use core::{arch::global_asm, panic::PanicInfo, slice}; use linked_list_allocator::LockedHeap; -use log::{error, info}; +use log::{error, info, debug}; extern crate alloc; use alloc::vec::Vec; @@ -89,7 +89,7 @@ extern "C" fn efilite_main(base: *mut u8, mapped: usize, used: isize, avail: usi console::OUT.init(n.reg()?.nth(0)?.starting_address as usize)?; log::set_logger(&console::OUT).ok()?; #[cfg(debug_assertions)] - log::set_max_level(log::LevelFilter::Info); + log::set_max_level(log::LevelFilter::Debug); info!("Using {:?} for console output\n", n.name); Some(()) }); @@ -149,10 +149,13 @@ extern "C" fn efilite_main(base: *mut u8, mapped: usize, used: isize, avail: usi let fwcfg = fwcfg::FwCfg::from_fdt_node(fwcfg_node).expect("Failed to open fwcfg device"); - if let Ok(rsdp) = fwcfg.load_firmware_tables() { - info!("Installing ACPI tables from fwcfg\n"); + let tbl = fwcfg.load_firmware_tables(); + if let Ok(rsdp) = tbl { + info!("Booting in ACPI mode\n"); efi.install_configtable(&RSDP_GUID, rsdp as *const ()); } else { + debug!("ACPI tables unavailable: {}\n", tbl.err().unwrap()); + info!("Booting in DT mode\n"); efi.install_configtable(&DTB_GUID, dtb.as_ptr() as *const ()); } |