summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArd Biesheuvel <ardb@kernel.org>2023-10-10 12:39:40 +0200
committerArd Biesheuvel <ardb@kernel.org>2023-10-10 12:39:40 +0200
commitdeec400c2814c46f42170f8ad2bcfa0c3f8dbe47 (patch)
tree4ec94a14efcfefd8916b388cec3a583f99b25bfa
parentbc42e7aea20b1344893ab00a8ebf45e22337c240 (diff)
downloadefilite-deec400c2814c46f42170f8ad2bcfa0c3f8dbe47.tar.gz
WIP
-rw-r--r--src/console.rs4
-rw-r--r--src/fwcfg.rs120
-rw-r--r--src/main.rs11
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 ());
}