diff --git a/src/hardware.rs b/src/hardware.rs new file mode 100644 index 0000000..226cce6 --- /dev/null +++ b/src/hardware.rs @@ -0,0 +1,57 @@ +use alloc::{format, string::ToString}; +use uefi::table::{cfg::ACPI2_GUID, Boot, SystemTable}; + +use crate::abi::Environment; + +#[repr(C, packed)] +struct Rsdp { + pub signature: [u8; 8], + pub checksum: u8, + pub oem_id: [u8; 6], + pub revision: u8, + pub rsdt_addr: u32, + pub xsdt_length: u32, + pub xsdt_addr: u64, + pub extended_checksum: u8, +} + +pub fn add_acpi_environ(system_table: &SystemTable, environment: &mut Environment) { + let rsdp_ptr = system_table + .config_table() + .iter() + .find(|table| table.guid == ACPI2_GUID) + .expect("Unable to find ACPI tables") + .address; + + let rsdp = unsafe { (rsdp_ptr as *const Rsdp).as_ref().unwrap() }; + + environment.0.insert( + "acpi.rsdp".to_string(), + format!("{:#018x}", rsdp_ptr as usize), + ); + if let Ok(oem) = core::str::from_utf8(&rsdp.oem_id) { + environment + .0 + .insert("acpi.oem".to_string(), oem.to_string()); + } + environment.0.insert( + "acpi.revision".to_string(), + format!("{}", rsdp.revision as usize), + ); + let rsdt_addr = rsdp.rsdt_addr; + environment + .0 + .insert("acpi.rsdt".to_string(), format!("{:#018x}", rsdt_addr)); + + // Should always be true but check anyway + if rsdp.revision >= 2 { + let xsdt_addr = rsdp.xsdt_addr; + environment + .0 + .insert("acpi.xsdt".to_string(), format!("{:#018x}", xsdt_addr)); + let xsdt_length = rsdp.xsdt_length; + environment + .0 + .insert("acpi.xsdt_length".to_string(), format!("{}", xsdt_length)); + } +} diff --git a/src/main.rs b/src/main.rs index 8ef398d..0a5e4bb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ mod abi; mod boot; +mod hardware; mod object; mod staging; @@ -10,6 +11,7 @@ extern crate alloc; use abi::{Environment, Howto, ModuleInfoItem, ModuleInfoType, ModuleInfoValue, Serialize}; use alloc::{collections::btree_map::BTreeMap, string::ToString}; +use hardware::add_acpi_environ; use log::info; use object::{Kernel, Module}; use uefi::{fs::FileSystem, prelude::*, proto::loaded_image::LoadedImage, table::boot::PAGE_SIZE}; @@ -46,11 +48,15 @@ fn main(image_handle: Handle, mut system_table: SystemTable) -> Status { let kernel = Kernel::from_elf_bytes(&kernel_data); let mut kernel_metadata = kernel.metadata(); - let environment = Environment(BTreeMap::from([( + let mut environment = Environment(BTreeMap::from([( "kernel".to_string(), "kernel".to_string(), )])); + add_acpi_environ(&system_table, &mut environment); + + log::debug!("environment: {:?}", environment.0); + // Allocate an extra 1 MiB for items we have to add to metadata, like memory map let metadata_size: usize = kernel_metadata .iter() @@ -61,9 +67,9 @@ fn main(image_handle: Handle, mut system_table: SystemTable) -> Status { let alloc_size = kernel.alloc_size() + environment.alloc_size() + metadata_size; let staging = staging::allocate_code(system_table.boot_services(), alloc_size); - let (environ_base, next) = environment.serialize_unaligned_base(staging); + let (kernel_base, next) = kernel.serialize_unaligned_base(staging); - let (kernel_base, mut next) = kernel.serialize_unaligned_base(next); + let (environ_base, next) = environment.serialize_unaligned_base(next); kernel_metadata.push(abi::ModuleInfoItem { tag: ModuleInfoType::Environment, @@ -91,8 +97,8 @@ fn main(image_handle: Handle, mut system_table: SystemTable) -> Status { info!("Kernel metadata is {:x?}", kernel_metadata); - let modinfo_base = next.as_ptr(); - for item in kernel_metadata.iter() { + let (modinfo_base, mut next) = kernel_metadata[0].serialize_unaligned_base(next); + for item in kernel_metadata[1..].iter() { next = item.serialize_unaligned(next); }