diff options
author | Ard Biesheuvel <ardb@kernel.org> | 2023-10-09 23:44:56 +0200 |
---|---|---|
committer | Ard Biesheuvel <ardb@kernel.org> | 2023-10-10 01:07:28 +0200 |
commit | 7a1be111dd09f596bd146e06dcd3c31fa080da5b (patch) | |
tree | e4b63a9312a35c5b19d370a2bc23d4f02db8324d | |
parent | e88d20e7c94aeb7444c4571995c491368ddea77c (diff) | |
download | efilite-7a1be111dd09f596bd146e06dcd3c31fa080da5b.tar.gz |
WIP ACPI stuff
-rw-r--r-- | src/efi/bootservices.rs | 8 | ||||
-rw-r--r-- | src/efi/memmap.rs | 15 | ||||
-rw-r--r-- | src/efi/mod.rs | 42 | ||||
-rw-r--r-- | src/fwcfg.rs | 436 | ||||
-rw-r--r-- | src/main.rs | 20 |
5 files changed, 449 insertions, 72 deletions
diff --git a/src/efi/bootservices.rs b/src/efi/bootservices.rs index b321afb..40ae88b 100644 --- a/src/efi/bootservices.rs +++ b/src/efi/bootservices.rs @@ -3,10 +3,10 @@ // Author: Ard Biesheuvel <ardb@google.com> use crate::efi::devicepath::DevicePath; +use crate::efi::efi_rtsdata_pool; use crate::efi::memmap; use crate::efi::memmap::Placement; use crate::efi::ProtocolPtr; -use crate::efi::efi_rtsdata_pool; use crate::efi::{memorytype::*, status::*, tableheader::*}; use crate::efi::{Bool, Char16, Event, EventNotify, Guid, Handle, PhysicalAddress, Tpl}; use crate::efi::{ProtocolDb, PROTOCOL_DB, TPL_APPLICATION, UEFI_REVISION}; @@ -16,8 +16,8 @@ use crate::efi::devicepath; use crate::efi::devicepath::EFI_DEVICE_PATH_PROTOCOL_GUID; use crate::efi::loadedimage::exit_image; use crate::efi::LoadedImage; -use crate::efi::EFI_LOADED_IMAGE_PROTOCOL_GUID; use crate::efi::EFI; +use crate::efi::EFI_LOADED_IMAGE_PROTOCOL_GUID; use core::sync::atomic::{AtomicUsize, Ordering}; use core::{ptr, slice}; @@ -524,7 +524,9 @@ extern "C" fn locate_device_path( } extern "C" fn install_configuration_table(guid: *const Guid, table: *const ()) -> Status { - EFI.get().unwrap().install_configtable(unsafe { &*guid }, table); + EFI.get() + .unwrap() + .install_configtable(unsafe { &*guid }, table); Status::EFI_SUCCESS } diff --git a/src/efi/memmap.rs b/src/efi/memmap.rs index cc2c902..7583252 100644 --- a/src/efi/memmap.rs +++ b/src/efi/memmap.rs @@ -209,20 +209,23 @@ fn convert_region( } pub fn allocate_region(region: &[u8], _type: MemoryType) -> Result<(), ()> { - let base = region.as_ptr() as PhysicalAddress; - let size = region.len() as usize; convert_region( &mut MEMMAP.lock(), - base, - size, + region.as_ptr() as PhysicalAddress, + region.len() as usize, Some(EfiConventionalMemory), _type, ) } pub fn free_pages(base: u64, pages: usize) -> Result<(), ()> { - let size = pages << EFI_PAGE_SHIFT; - convert_region(&mut MEMMAP.lock(), base, size, None, EfiConventionalMemory) + convert_region( + &mut MEMMAP.lock(), + base, + pages << EFI_PAGE_SHIFT, + None, + EfiConventionalMemory, + ) } pub enum Placement { diff --git a/src/efi/mod.rs b/src/efi/mod.rs index 800dd86..44e72ce 100644 --- a/src/efi/mod.rs +++ b/src/efi/mod.rs @@ -2,10 +2,10 @@ // Copyright 2022-2023 Google LLC // Author: Ard Biesheuvel <ardb@google.com> +use crate::efi::bootservices::BootServices; use crate::efi::configtable::ConfigurationTable; use crate::efi::loadedimage::EFI_LOADED_IMAGE_PROTOCOL_GUID; use crate::efi::memmap::*; -use crate::efi::bootservices::BootServices; use crate::efi::runtimeservices::RuntimeServices; use crate::efi::MemoryType::*; use crate::efi::{loadedimage::*, memorytype::*, systemtable::*}; @@ -207,17 +207,17 @@ pub fn efi_rtsdata_pool() -> &'static LockedHeap { &EFI.get().unwrap().rtsdata } -fn alloc_table<T>(h: &LockedHeap, tmpl: T) -> Result<Box<T>, ()> { - let layout = Layout::from_size_align(mem::size_of::<T>(), 8).map_err(|_| ())?; - let rtp = h.lock().allocate_first_fit(layout).map_err(|_| ())?; - let mut rt: Box<mem::MaybeUninit<T>> = unsafe { Box::from_raw(rtp.as_ptr() as *mut _) }; - rt.write(tmpl); - - unsafe { Ok(mem::transmute::<Box<mem::MaybeUninit<T>>, Box<T>>(rt)) } -} - pub fn init() -> Result<&'static EfiContext, ()> { let ctx = EFI.get_or_try_init(|| { + fn alloc_table<T>(h: &LockedHeap, tmpl: T) -> Result<Box<T>, ()> { + let layout = Layout::from_size_align(mem::size_of::<T>(), 8).map_err(|_| ())?; + let rtp = h.lock().allocate_first_fit(layout).map_err(|_| ())?; + let mut rt: Box<mem::MaybeUninit<T>> = unsafe { Box::from_raw(rtp.as_ptr() as *mut _) }; + rt.write(tmpl); + + unsafe { Ok(mem::transmute::<Box<mem::MaybeUninit<T>>, Box<T>>(rt)) } + } + let rtspool = memmap::allocate_pages( 16, MemoryType::EfiRuntimeServicesData, @@ -240,21 +240,21 @@ pub fn init() -> Result<&'static EfiContext, ()> { ctx.unwrap().install_configtable( &EFI_RT_PROPERTIES_TABLE_GUID, &RT_PROPERTIES_TABLE as *const _ as *const (), - ); -// efi.install_configtable( -// &EFI_MEMORY_ATTRIBUTES_TABLE_GUID, -// MemoryAttributesTable::new() as *const _ as *const (), -// ); - ctx + ); + ctx.unwrap().install_configtable( + &EFI_MEMORY_ATTRIBUTES_TABLE_GUID, + MemoryAttributesTable::new() as *const _ as *const (), + ); + ctx } -pub fn install_protocol<T>(handle: Handle, guid: &'static Guid, protocol: &T) { +pub fn install_protocol<T>(handle: Handle, guid: &Guid, protocol: &T) { PROTOCOL_DB .lock() .insert((handle, *guid), ProtocolPtr::from(protocol)); } -pub fn uninstall_protocol<T>(handle: Handle, guid: &'static Guid, _protocol: &T) { +pub fn uninstall_protocol<T>(handle: Handle, guid: &Guid, _protocol: &T) { PROTOCOL_DB.lock().remove(&(handle, *guid)); } @@ -267,7 +267,7 @@ impl EfiContext { }; db.insert(*guid, entry); - let array: Vec<ConfigurationTable> = db.values().cloned().collect(); + let array: Vec<_> = db.values().cloned().collect(); SystemTable::update_config_table_array(array.as_slice()); } @@ -276,7 +276,7 @@ impl EfiContext { pe_image: &'a Parser, cmdline: &'a Vec<u16>, randomized: bool, - ) -> LoadedImageData<'a> { + ) -> LoadedImageData<'a> { LoadedImageData::new( pe_image.get_image(), cmdline.as_slice(), @@ -284,6 +284,6 @@ impl EfiContext { EfiLoaderData, pe_image.get_entrypoint(), randomized, - ) + ) } } diff --git a/src/fwcfg.rs b/src/fwcfg.rs index 7d1668e..ab77785 100644 --- a/src/fwcfg.rs +++ b/src/fwcfg.rs @@ -2,11 +2,14 @@ // Copyright 2022-2023 Google LLC // Author: Ard Biesheuvel <ardb@google.com> -use crate::efi; +use crate::{efi, MemoryType, Placement}; use core::{ - mem::MaybeUninit, + fmt, + marker::PhantomData, + mem::{size_of, MaybeUninit}, pin::pin, slice, + str::from_utf8, sync::atomic::{fence, Ordering}, }; use mmio::{Allow, Deny, VolBox}; @@ -31,9 +34,12 @@ const CFG_KERNEL_DATA: u16 = 0x11; const CFG_INITRD_SIZE: u16 = 0x0b; const CFG_INITRD_DATA: u16 = 0x12; +const CFG_FILE_DIR: u16 = 0x19; + const CFG_DMACTL_DONE: u32 = 0; const CFG_DMACTL_ERROR: u32 = 1; const CFG_DMACTL_READ: u32 = 2; +const CFG_DMACTL_SKIP: u32 = 4; #[repr(C)] struct DmaTransfer { @@ -42,34 +48,84 @@ struct DmaTransfer { address: u64, } -impl FwCfg { - pub fn from_fdt_node(node: fdt::node::FdtNode) -> Option<FwCfg> { - let addr = node.reg()?.nth(0)?.starting_address; +#[derive(Copy, Clone)] +#[repr(C)] +struct FwCfgFile { + _size: u32, + _select: u16, + reserved: u16, + filename: [u8; 56], +} + +impl FwCfgFile { + pub fn size(&self) -> usize { + u32::to_be(self._size) as usize + } + + pub fn select(&self) -> u16 { + u16::to_be(self._select) + } +} + +#[derive(Copy, Clone)] +struct FwCfgFileIterator<'a, T> { + count: u32, + next: u32, + select: u16, + offset: u32, + fwcfg: &'a FwCfg, + phantom: PhantomData<T>, +} + +impl<T: Copy> Iterator for FwCfgFileIterator<'_, T> { + type Item = T; + + fn next(&mut self) -> Option<Self::Item> { + if self.next == self.count { + return None; + } + + let itemsz = size_of::<Self::Item>() as u32; + let offset = self.offset + self.next * itemsz; + let out = pin!(MaybeUninit::<T>::uninit()); + let mut mmio = self.fwcfg.0.lock(); + + mmio.selector.write(u16::to_be(self.select)); + fence(Ordering::Release); + + mmio.dma_transfer(0, offset as u32).ok()?; + mmio.dma_transfer(&*out as *const _ as u64, itemsz as u32) + .ok()?; + self.next += 1; + + unsafe { Some(out.assume_init()) } + } +} + +impl FwCfgMmio { + fn new(addr: *const u8) -> FwCfgMmio { unsafe { - Some(FwCfg(Spinlock::new(FwCfgMmio { + FwCfgMmio { data: VolBox::<u64, Allow, Deny>::new(addr as *mut u64), selector: VolBox::<u16, Deny, Allow>::new(addr.offset(8) as *mut u16), dmacontrol: VolBox::<u64, Deny, Allow>::new(addr.offset(16) as *mut u64), - }))) + } } } - fn dma_transfer( - &self, - loadbuffer: &mut [MaybeUninit<u8>], - size: usize, - config_item: u16, - ) -> Result<(), ()> { + fn dma_transfer(&mut self, addr: u64, size: u32) -> Result<(), ()> { + let control = match addr { + 0 => CFG_DMACTL_SKIP, + _ => CFG_DMACTL_READ, + }; + let xfer = pin!(DmaTransfer { - control: u32::to_be(CFG_DMACTL_READ), - length: u32::to_be(size as u32), - address: u64::to_be(loadbuffer.as_ptr() as u64), + control: u32::to_be(control), + length: u32::to_be(size), + address: u64::to_be(addr), }); - let mut mmio = self.0.lock(); - mmio.selector.write(u16::to_be(config_item)); - fence(Ordering::Release); - mmio.dmacontrol.write(u64::to_be(&*xfer as *const _ as u64)); + self.dmacontrol.write(u64::to_be(&*xfer as *const _ as u64)); let control = unsafe { VolBox::<u32, Allow, Deny>::new(&xfer.control as *const _ as *mut u32) }; @@ -81,6 +137,141 @@ impl FwCfg { } } } +} + +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub struct FwCfgLoaderAllocate { + pub filename: [u8; 56], + pub alignment: u32, + pub zone: u8, +} + +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub struct FwCfgLoaderAddPointer { + pub pointer: [u8; 56], + pub pointee: [u8; 56], + pub offset: u32, + pub size: u8, +} + +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub struct FwCfgLoaderAddChecksum { + pub filename: [u8; 56], + pub result_offset: u32, + pub start: u32, + pub size: u32, +} + +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub struct FwCfgLoaderWritePointer { + pub pointer: [u8; 56], + pub pointee: [u8; 56], + pub pointer_offset: u32, + pub pointee_offset: u32, + pub size: u8, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub union FwCfgLoaderUnion { + pub allocate: FwCfgLoaderAllocate, + pub add_pointer: FwCfgLoaderAddPointer, + pub add_checksum: FwCfgLoaderAddChecksum, + pub write_pointer: FwCfgLoaderWritePointer, +} + +#[derive(Copy, Clone, Debug)] +#[repr(u32)] +#[allow(dead_code)] +pub enum FwCfgLoaderCmdType { + FwCfgLoaderCmdUnused, + FwCfgLoaderCmdAllocate, + FwCfgLoaderCmdAddPointer, + FwCfgLoaderCmdAddChecksum, + FwCfgLoaderCmdWritePointer, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct FwCfgLoaderEntry { + pub _type: FwCfgLoaderCmdType, + pub u: FwCfgLoaderUnion, +} + +impl fmt::Debug for FwCfgLoaderEntry { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut out = f.debug_struct("FwCfgLoaderEntry"); + + match self._type { + FwCfgLoaderCmdType::FwCfgLoaderCmdAllocate => unsafe { + out.field("u", &self.u.allocate); + }, + FwCfgLoaderCmdType::FwCfgLoaderCmdAddPointer => unsafe { + out.field("u", &self.u.add_pointer); + }, + FwCfgLoaderCmdType::FwCfgLoaderCmdAddChecksum => unsafe { + out.field("u", &self.u.add_checksum); + }, + FwCfgLoaderCmdType::FwCfgLoaderCmdWritePointer => unsafe { + out.field("u", &self.u.write_pointer); + }, + _ => (), + }; + out.finish() + } +} + +impl FwCfg { + fn new(addr: *const u8) -> FwCfg { + FwCfg(Spinlock::new(FwCfgMmio::new(addr))) + } + + fn files(&self) -> FwCfgFileIterator<FwCfgFile> { + let size = u32::to_be(self.get_file_size(CFG_FILE_DIR) as u32); + FwCfgFileIterator { + count: size, + next: 0, + select: CFG_FILE_DIR, + offset: size_of::<u32>() as u32, + fwcfg: self, + phantom: PhantomData, + } + } + + fn loader(&self) -> Option<FwCfgFileIterator<FwCfgLoaderEntry>> { + 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, + }) + } + + pub fn from_fdt_node(node: fdt::node::FdtNode) -> Option<FwCfg> { + let addr = node.reg()?.nth(0)?.starting_address; + Some(Self::new(addr)) + } + + fn dma_read( + &self, + loadbuffer: &mut [MaybeUninit<u8>], + size: usize, + config_item: u16, + ) -> Result<(), ()> { + let mut mmio = self.0.lock(); + mmio.selector.write(u16::to_be(config_item)); + fence(Ordering::Release); + mmio.dma_transfer(loadbuffer.as_ptr() as u64, size as u32) + } pub fn get_file_size(&self, size_cfg: u16) -> usize { let mut mmio = self.0.lock(); @@ -92,15 +283,11 @@ impl FwCfg { pub fn load_file<'a>( &self, loadbuffer: &'a mut [MaybeUninit<u8>], - size_cfg: u16, + size: usize, data_cfg: u16, ) -> Result<&'a [u8], ()> { - let size = self.get_file_size(size_cfg); - if size == 0 { - return Err(()); - } let size = size.min(loadbuffer.len()); - self.dma_transfer(loadbuffer, size, data_cfg)?; + self.dma_read(loadbuffer, size, data_cfg)?; if size < loadbuffer.len() { loadbuffer.split_at_mut(size).1.fill(MaybeUninit::zeroed()); } @@ -112,37 +299,210 @@ impl FwCfg { } } - pub fn get_kernel_loader(&self) -> FwCfgFileLoader { - FwCfgFileLoader { - size_cfg: CFG_KERNEL_SIZE, - data_cfg: CFG_KERNEL_DATA, - fwcfg: self, + pub fn load_file_mut<'a>( + &self, + loadbuffer: &'a mut [MaybeUninit<u8>], + size: usize, + data_cfg: u16, + ) -> Result<&'a mut [u8], ()> { + let size = size.min(loadbuffer.len()); + self.dma_read(loadbuffer, size, data_cfg)?; + if size < loadbuffer.len() { + loadbuffer.split_at_mut(size).1.fill(MaybeUninit::zeroed()); + } + unsafe { + Ok(slice::from_raw_parts_mut( + loadbuffer.as_ptr() as *mut _, + loadbuffer.len(), + )) } } - pub fn get_initrd_loader(&self) -> FwCfgFileLoader { - FwCfgFileLoader { - size_cfg: CFG_INITRD_SIZE, - data_cfg: CFG_INITRD_DATA, + fn get_loader(&self, size_cfg: u16, data_cfg: u16) -> Option<FwCfgFileLoader> { + let size = self.get_file_size(size_cfg); + if size == 0 { + return None; + } + Some(FwCfgFileLoader { + size: size, + data_cfg: data_cfg, fwcfg: self, + }) + } + + pub fn get_kernel_loader(&self) -> Option<FwCfgFileLoader> { + self.get_loader(CFG_KERNEL_SIZE, CFG_KERNEL_DATA) + } + + pub fn get_initrd_loader(&self) -> Option<FwCfgFileLoader> { + self.get_loader(CFG_INITRD_SIZE, CFG_INITRD_DATA) + } + + pub fn load_firmware_tables(&self) -> Result<*const u8, ()> { + FwCfgTableLoader::new(self).load_firmware_tables() + } +} + +use alloc::collections::BTreeMap; + +struct FwCfgTableLoader<'a> { + loaded_tables: BTreeMap<[u8; 56], &'a mut [u8]>, + fwcfg: &'a FwCfg, +} + +impl<'a> FwCfgTableLoader<'a> { + pub fn new(fwcfg: &'a FwCfg) -> Self { + FwCfgTableLoader { + loaded_tables: BTreeMap::new(), + fwcfg: fwcfg, + } + } + + fn allocate(&mut self, allocate: &FwCfgLoaderAllocate) -> Result<(), ()> { + let f = self + .fwcfg + .files() + .find(|f| f.filename == allocate.filename) + .ok_or(())?; + let b = efi::memmap::allocate_pages( + efi::memmap::size_to_pages(f.size()), + MemoryType::EfiACPIReclaimMemory, + Placement::Anywhere, + ) + .ok_or(())?; + 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<(), ()> { + let tables = &mut self.loaded_tables; + let addend = tables.get(&add_pointer.pointee).ok_or(())?.as_ptr() as u64; + let pointer = tables.get_mut(&add_pointer.pointer).ok_or(())?; + let offset = add_pointer.offset as usize; + + match add_pointer.size { + 1 => add_value_at_offset(addend as u8, offset, pointer), + 2 => add_value_at_offset(addend as u16, offset, pointer), + 4 => add_value_at_offset(addend as u32, offset, pointer), + 8 => add_value_at_offset(addend as u64, offset, pointer), + _ => (), } + Ok(()) + } + + fn add_checksum(&mut self, add_checksum: &FwCfgLoaderAddChecksum) -> Result<(), ()> { + 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 mut checksum = 0u8; + table[start..end] + .iter() + .for_each(|&c| checksum = checksum.wrapping_sub(c)); + add_value_at_offset(checksum, offset, table); + Ok(()) } + + pub fn load_firmware_tables(&mut self) -> Result<*const u8, ()> { + for entry in self.fwcfg.loader().ok_or(())? { + match entry._type { + FwCfgLoaderCmdType::FwCfgLoaderCmdAllocate => unsafe { + self.allocate(&entry.u.allocate) + }, + FwCfgLoaderCmdType::FwCfgLoaderCmdAddPointer => unsafe { + self.add_pointer(&entry.u.add_pointer) + }, + FwCfgLoaderCmdType::FwCfgLoaderCmdAddChecksum => unsafe { + self.add_checksum(&entry.u.add_checksum) + }, + //FwCfgLoaderCmdType::FwCfgLoaderCmdWritePointer => unsafe { + //}, + _ => Err(()), + }?; + } + let rsdp = self + .loaded_tables + .iter() + .find(|(&k, &ref _v)| { + from_utf8(&k).map_or(false, |s| s.trim_end_matches("\0") == "etc/acpi/rsdp") + }) + .ok_or(())? + .1; + Ok(rsdp.as_ptr()) + } +} + +trait LeBytes<T, const N: usize> { + fn from_le_bytes(val: &[u8; N]) -> T; + fn to_le_bytes(val: T) -> [u8; N]; +} + +impl LeBytes<u8, 1> for u8 { + fn from_le_bytes(val: &[u8; 1]) -> u8 { + val[0] + } + + fn to_le_bytes(val: u8) -> [u8; 1] { + [val] + } +} + +impl LeBytes<u16, 2> for u16 { + fn from_le_bytes(val: &[u8; 2]) -> u16 { + u16::from_le_bytes(*val) + } + + fn to_le_bytes(val: u16) -> [u8; 2] { + u16::to_le_bytes(val) + } +} + +impl LeBytes<u32, 4> for u32 { + fn from_le_bytes(val: &[u8; 4]) -> u32 { + u32::from_le_bytes(*val) + } + + fn to_le_bytes(val: u32) -> [u8; 4] { + u32::to_le_bytes(val) + } +} + +impl LeBytes<u64, 8> for u64 { + fn from_le_bytes(val: &[u8; 8]) -> u64 { + u64::from_le_bytes(*val) + } + + fn to_le_bytes(val: u64) -> [u8; 8] { + u64::to_le_bytes(val) + } +} + +fn add_value_at_offset<T: LeBytes<T, N> + core::ops::Add<Output = T>, const N: usize>( + addend: T, + offset: usize, + buf: &mut &mut [u8], +) { + let end = offset + N; + let val: T = T::from_le_bytes(buf[offset..end].try_into().unwrap()) + addend; + buf[offset..end].copy_from_slice(&T::to_le_bytes(val)); } pub struct FwCfgFileLoader<'a> { - size_cfg: u16, + size: usize, data_cfg: u16, fwcfg: &'a FwCfg, } impl efi::FileLoader for FwCfgFileLoader<'_> { fn get_size(&self) -> usize { - self.fwcfg.get_file_size(self.size_cfg) + self.size } fn load_file<'a>(&self, loadbuffer: &'a mut [MaybeUninit<u8>]) -> Result<&'a [u8], &str> { self.fwcfg - .load_file(loadbuffer, self.size_cfg, self.data_cfg) + .load_file(loadbuffer, self.size, self.data_cfg) .or(Err("Failed to load file from fwcfg")) } } diff --git a/src/main.rs b/src/main.rs index 333206c..a30911c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,6 +57,13 @@ pub const DTB_GUID: Guid = guid!( [0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0] ); +pub const RSDP_GUID: Guid = guid!( + 0x8868e871, + 0xe4f1, + 0x11d3, + [0xbc, 0x22, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81] +); + #[global_allocator] pub static ALLOCATOR: LockedHeap = LockedHeap::empty(); @@ -133,8 +140,6 @@ extern "C" fn efilite_main(base: *mut u8, mapped: usize, used: isize, avail: usi let efi = efi::init().expect("Failed to init EFI runtime"); - efi.install_configtable(&DTB_GUID, dtb.as_ptr() as *const ()); - let compat = ["qemu,fw-cfg-mmio"]; let fwcfg_node = fdt .find_compatible(&compat) @@ -144,6 +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"); + efi.install_configtable(&RSDP_GUID, rsdp as *const ()); + } else { + efi.install_configtable(&DTB_GUID, dtb.as_ptr() as *const ()); + } + let (placement, randomized) = if let Some(seed) = rng::get_random::<u32>() { (Placement::Random(seed, 0x20000), true) } else { @@ -151,7 +163,7 @@ extern "C" fn efilite_main(base: *mut u8, mapped: usize, used: isize, avail: usi }; let pe_image = { - let ldr = fwcfg.get_kernel_loader(); + let ldr = fwcfg.get_kernel_loader().unwrap(); let buf = efi::memmap::allocate_pages( efi::memmap::size_to_pages(ldr.get_size()), MemoryType::EfiLoaderData, @@ -195,7 +207,7 @@ extern "C" fn efilite_main(base: *mut u8, mapped: usize, used: isize, avail: usi idmap.map_range(code, ro_flags.non_global()); idmap.activate(); - let initrdloader = fwcfg.get_initrd_loader(); + let initrdloader = fwcfg.get_initrd_loader().unwrap(); let _initrd = efi::initrdloadfile2::new(&initrdloader); let _rng = efi::rng::new(); let _memattr = efi::memattr::new(&mut idmap); |