29ff1ea8fc
- P19-init-startup-hardening: Replace panic-grade expect/unwrap in init startup paths (getns, register_scheme_to_ns, setrens, filename parsing) with graceful error handling and logging - P19-acpid-startup-hardening: Replace panic-grade calls in acpid with graceful degradation (rxsdt read failure → warn + exit 0, SDT parse → error + exit 1, I/O privilege → fatal, scheme registration → fatal, setrens → warn + continue, event loop errors → log + continue) - P18-9-msi-allocation-resilience: Regenerate with git diff -U0 -w format for maximum context resilience - fetch.rs: Change --fuzz=0 to --fuzz=3 for resilient patch application - AGENTS.md: Document robust patch generation technique as mandatory - Add P4/P5/P6/P7 patches (estale, dmi, i2c, ps2d hardening) - Add P21 kernel x2apic SMP fix patch - Multiple local recipe source improvements (redox-drm, driver-manager, driver-acpi, thermald) - Config updates for redbear-mini and redbear-device-services - Subsystem assessment document
682 lines
23 KiB
Diff
682 lines
23 KiB
Diff
diff --git a/drivers/acpid/src/dmi.rs b/drivers/acpid/src/dmi.rs
|
||
new file mode 100644
|
||
--- /dev/null
|
||
+++ b/drivers/acpid/src/dmi.rs
|
||
@@ -0,0 +1,350 @@
|
||
+use std::fmt;
|
||
+use syscall::PAGE_SIZE;
|
||
+
|
||
+use crate::acpi::PhysmapGuard;
|
||
+
|
||
+#[derive(Clone, Debug, Default)]
|
||
+pub struct DmiStrings {
|
||
+ pub sys_vendor: Option<String>,
|
||
+ pub board_vendor: Option<String>,
|
||
+ pub board_name: Option<String>,
|
||
+ pub board_version: Option<String>,
|
||
+ pub product_name: Option<String>,
|
||
+ pub product_version: Option<String>,
|
||
+ pub bios_version: Option<String>,
|
||
+}
|
||
+
|
||
+impl DmiStrings {
|
||
+ pub fn to_text(&self) -> String {
|
||
+ let mut text = String::new();
|
||
+ if let Some(ref v) = self.sys_vendor {
|
||
+ text.push_str("sys_vendor=");
|
||
+ text.push_str(v);
|
||
+ text.push('\n');
|
||
+ }
|
||
+ if let Some(ref v) = self.board_vendor {
|
||
+ text.push_str("board_vendor=");
|
||
+ text.push_str(v);
|
||
+ text.push('\n');
|
||
+ }
|
||
+ if let Some(ref v) = self.board_name {
|
||
+ text.push_str("board_name=");
|
||
+ text.push_str(v);
|
||
+ text.push('\n');
|
||
+ }
|
||
+ if let Some(ref v) = self.board_version {
|
||
+ text.push_str("board_version=");
|
||
+ text.push_str(v);
|
||
+ text.push('\n');
|
||
+ }
|
||
+ if let Some(ref v) = self.product_name {
|
||
+ text.push_str("product_name=");
|
||
+ text.push_str(v);
|
||
+ text.push('\n');
|
||
+ }
|
||
+ if let Some(ref v) = self.product_version {
|
||
+ text.push_str("product_version=");
|
||
+ text.push_str(v);
|
||
+ text.push('\n');
|
||
+ }
|
||
+ if let Some(ref v) = self.bios_version {
|
||
+ text.push_str("bios_version=");
|
||
+ text.push_str(v);
|
||
+ text.push('\n');
|
||
+ }
|
||
+ text
|
||
+ }
|
||
+}
|
||
+
|
||
+#[derive(Debug)]
|
||
+pub enum DmiError {
|
||
+ InvalidData,
|
||
+ Io(std::io::Error),
|
||
+}
|
||
+
|
||
+impl fmt::Display for DmiError {
|
||
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||
+ match self {
|
||
+ Self::InvalidData => write!(f, "invalid SMBIOS data"),
|
||
+ Self::Io(e) => write!(f, "I/O error: {}", e),
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+impl From<std::io::Error> for DmiError {
|
||
+ fn from(e: std::io::Error) -> Self {
|
||
+ DmiError::Io(e)
|
||
+ }
|
||
+}
|
||
+
|
||
+/// Scan physical memory for SMBIOS entry point and parse DMI strings.
|
||
+pub fn read_smbios_dmi() -> Result<DmiStrings, DmiError> {
|
||
+ // SMBIOS entry point is in the BIOS ROM area 0xF0000-0xFFFFF
|
||
+ let scan_start = 0xF_0000usize;
|
||
+ let scan_size = 0x10_0000usize - scan_start;
|
||
+ let start_page = scan_start / PAGE_SIZE * PAGE_SIZE;
|
||
+ let start_offset = scan_start % PAGE_SIZE;
|
||
+ let page_count = (start_offset + scan_size).div_ceil(PAGE_SIZE);
|
||
+
|
||
+ let pages = PhysmapGuard::map(start_page, page_count)?;
|
||
+ let bios_region = &pages[start_offset..start_offset + scan_size];
|
||
+
|
||
+ // Search for 64-bit entry point first (_SM3_), then 32-bit (_SM_)
|
||
+ // Entry points must be 16-byte aligned
|
||
+ let mut entry_point_addr = None;
|
||
+ let mut is_64bit = false;
|
||
+
|
||
+ for offset in (0..bios_region.len().saturating_sub(5)).step_by(16) {
|
||
+ if bios_region[offset..].starts_with(b"_SM3_") {
|
||
+ entry_point_addr = Some(scan_start + offset);
|
||
+ is_64bit = true;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if entry_point_addr.is_none() {
|
||
+ for offset in (0..bios_region.len().saturating_sub(4)).step_by(16) {
|
||
+ if bios_region[offset..].starts_with(b"_SM_") {
|
||
+ // Verify intermediate anchor "_DMI_" at offset 0x10 from anchor start
|
||
+ let dmi_offset = offset + 0x10;
|
||
+ if dmi_offset + 5 <= bios_region.len()
|
||
+ && bios_region[dmi_offset..dmi_offset + 5].starts_with(b"_DMI_")
|
||
+ {
|
||
+ entry_point_addr = Some(scan_start + offset);
|
||
+ is_64bit = false;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ let entry_addr = match entry_point_addr {
|
||
+ Some(addr) => addr,
|
||
+ None => {
|
||
+ log::warn!("SMBIOS entry point not found in 0xF0000-0xFFFFF");
|
||
+ return Ok(DmiStrings::default());
|
||
+ }
|
||
+ };
|
||
+
|
||
+ log::info!(
|
||
+ "Found SMBIOS {} entry point at {:#x}",
|
||
+ if is_64bit { "3.0" } else { "2.x" },
|
||
+ entry_addr
|
||
+ );
|
||
+
|
||
+ if is_64bit {
|
||
+ parse_smbios_64(entry_addr)
|
||
+ } else {
|
||
+ parse_smbios_32(entry_addr)
|
||
+ }
|
||
+}
|
||
+
|
||
+fn parse_smbios_32(entry_addr: usize) -> Result<DmiStrings, DmiError> {
|
||
+ // 32-bit entry point is at least 0x1F bytes
|
||
+ let page = entry_addr / PAGE_SIZE * PAGE_SIZE;
|
||
+ let offset = entry_addr % PAGE_SIZE;
|
||
+ let pages = PhysmapGuard::map(page, 1)?;
|
||
+
|
||
+ if pages.len() < offset + 0x1F {
|
||
+ log::warn!("SMBIOS 32-bit entry point truncated");
|
||
+ return Err(DmiError::InvalidData);
|
||
+ }
|
||
+
|
||
+ let ep = &pages[offset..];
|
||
+ let ep_len = ep[0x05] as usize;
|
||
+ if ep_len < 0x1F || pages.len() < offset + ep_len {
|
||
+ log::warn!("SMBIOS 32-bit entry point length invalid: {}", ep_len);
|
||
+ return Err(DmiError::InvalidData);
|
||
+ }
|
||
+
|
||
+ let checksum = ep[..ep_len].iter().fold(0u8, |sum, &b| sum.wrapping_add(b));
|
||
+ if checksum != 0 {
|
||
+ log::warn!("SMBIOS 32-bit entry point checksum failed");
|
||
+ return Err(DmiError::InvalidData);
|
||
+ }
|
||
+
|
||
+ let table_len = u16::from_le_bytes([ep[0x16], ep[0x17]]) as usize;
|
||
+ let table_addr = u32::from_le_bytes([ep[0x18], ep[0x19], ep[0x1A], ep[0x1B]]) as usize;
|
||
+
|
||
+ log::info!("SMBIOS 32-bit: table at {:#x}, len {}", table_addr, table_len);
|
||
+
|
||
+ parse_smbios_structures(table_addr, table_len)
|
||
+}
|
||
+
|
||
+fn parse_smbios_64(entry_addr: usize) -> Result<DmiStrings, DmiError> {
|
||
+ // 64-bit entry point is at least 0x18 bytes
|
||
+ let page = entry_addr / PAGE_SIZE * PAGE_SIZE;
|
||
+ let offset = entry_addr % PAGE_SIZE;
|
||
+ let pages = PhysmapGuard::map(page, 1)?;
|
||
+
|
||
+ if pages.len() < offset + 0x18 {
|
||
+ log::warn!("SMBIOS 64-bit entry point truncated");
|
||
+ return Err(DmiError::InvalidData);
|
||
+ }
|
||
+
|
||
+ let ep = &pages[offset..];
|
||
+ let ep_len = ep[0x06] as usize;
|
||
+ if ep_len < 0x18 || pages.len() < offset + ep_len {
|
||
+ log::warn!("SMBIOS 64-bit entry point length invalid: {}", ep_len);
|
||
+ return Err(DmiError::InvalidData);
|
||
+ }
|
||
+
|
||
+ let checksum = ep[..ep_len].iter().fold(0u8, |sum, &b| sum.wrapping_add(b));
|
||
+ if checksum != 0 {
|
||
+ log::warn!("SMBIOS 64-bit entry point checksum failed");
|
||
+ return Err(DmiError::InvalidData);
|
||
+ }
|
||
+
|
||
+ let table_max_size =
|
||
+ u32::from_le_bytes([ep[0x0C], ep[0x0D], ep[0x0E], ep[0x0F]]) as usize;
|
||
+ let table_addr = u64::from_le_bytes([
|
||
+ ep[0x10], ep[0x11], ep[0x12], ep[0x13], ep[0x14], ep[0x15], ep[0x16], ep[0x17],
|
||
+ ]) as usize;
|
||
+
|
||
+ log::info!(
|
||
+ "SMBIOS 64-bit: table at {:#x}, max size {}",
|
||
+ table_addr,
|
||
+ table_max_size
|
||
+ );
|
||
+
|
||
+ parse_smbios_structures(table_addr, table_max_size)
|
||
+}
|
||
+
|
||
+fn parse_smbios_structures(table_addr: usize, table_len: usize) -> Result<DmiStrings, DmiError> {
|
||
+ if table_addr == 0 || table_len == 0 {
|
||
+ log::warn!("SMBIOS structure table address or length is zero");
|
||
+ return Ok(DmiStrings::default());
|
||
+ }
|
||
+
|
||
+ // Map the structure table. It may span multiple pages.
|
||
+ let start_page = table_addr / PAGE_SIZE * PAGE_SIZE;
|
||
+ let start_offset = table_addr % PAGE_SIZE;
|
||
+ let total_needed = start_offset + table_len;
|
||
+ let page_count = total_needed.div_ceil(PAGE_SIZE);
|
||
+
|
||
+ let pages = PhysmapGuard::map(start_page, page_count)?;
|
||
+ if pages.len() < total_needed {
|
||
+ log::warn!("SMBIOS structure table mapping truncated");
|
||
+ return Err(DmiError::InvalidData);
|
||
+ }
|
||
+
|
||
+ let table = &pages[start_offset..start_offset + table_len];
|
||
+
|
||
+ let mut dmi = DmiStrings::default();
|
||
+ let mut pos = 0;
|
||
+
|
||
+ while pos + 4 <= table.len() {
|
||
+ let stype = table[pos];
|
||
+ let slen = table[pos + 1] as usize;
|
||
+ let _handle = u16::from_le_bytes([table[pos + 2], table[pos + 3]]);
|
||
+
|
||
+ if slen < 4 {
|
||
+ log::warn!(
|
||
+ "Malformed SMBIOS structure at offset {}, type {}, len {}",
|
||
+ pos,
|
||
+ stype,
|
||
+ slen
|
||
+ );
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ if pos + slen > table.len() {
|
||
+ log::warn!(
|
||
+ "SMBIOS structure at offset {} extends past table end", pos
|
||
+ );
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ // Parse strings after the formatted section
|
||
+ let strings_start = pos + slen;
|
||
+ let mut strings = Vec::new();
|
||
+ let mut s = strings_start;
|
||
+
|
||
+ while s < table.len() {
|
||
+ // Find null terminator
|
||
+ let mut end = s;
|
||
+ while end < table.len() && table[end] != 0 {
|
||
+ end += 1;
|
||
+ }
|
||
+
|
||
+ if end >= table.len() {
|
||
+ log::warn!("Unterminated SMBIOS strings at offset {}", s);
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ let string = std::str::from_utf8(&table[s..end]).unwrap_or("").to_string();
|
||
+ strings.push(string);
|
||
+
|
||
+ s = end + 1;
|
||
+
|
||
+ // Double null terminates the string set
|
||
+ if s < table.len() && table[s] == 0 {
|
||
+ s += 1;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ match stype {
|
||
+ 0 => {
|
||
+ // BIOS Information
|
||
+ if slen > 5 {
|
||
+ let idx = table[pos + 5] as usize;
|
||
+ if idx > 0 && idx <= strings.len() {
|
||
+ dmi.bios_version = Some(strings[idx - 1].clone());
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ 1 => {
|
||
+ // System Information
|
||
+ if slen > 4 {
|
||
+ let idx = table[pos + 4] as usize;
|
||
+ if idx > 0 && idx <= strings.len() {
|
||
+ dmi.sys_vendor = Some(strings[idx - 1].clone());
|
||
+ }
|
||
+ }
|
||
+ if slen > 5 {
|
||
+ let idx = table[pos + 5] as usize;
|
||
+ if idx > 0 && idx <= strings.len() {
|
||
+ dmi.product_name = Some(strings[idx - 1].clone());
|
||
+ }
|
||
+ }
|
||
+ if slen > 6 {
|
||
+ let idx = table[pos + 6] as usize;
|
||
+ if idx > 0 && idx <= strings.len() {
|
||
+ dmi.product_version = Some(strings[idx - 1].clone());
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ 2 => {
|
||
+ // Base Board Information
|
||
+ if slen > 4 {
|
||
+ let idx = table[pos + 4] as usize;
|
||
+ if idx > 0 && idx <= strings.len() {
|
||
+ dmi.board_vendor = Some(strings[idx - 1].clone());
|
||
+ }
|
||
+ }
|
||
+ if slen > 5 {
|
||
+ let idx = table[pos + 5] as usize;
|
||
+ if idx > 0 && idx <= strings.len() {
|
||
+ dmi.board_name = Some(strings[idx - 1].clone());
|
||
+ }
|
||
+ }
|
||
+ if slen > 6 {
|
||
+ let idx = table[pos + 6] as usize;
|
||
+ if idx > 0 && idx <= strings.len() {
|
||
+ dmi.board_version = Some(strings[idx - 1].clone());
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ 127 => {
|
||
+ // End-of-table marker
|
||
+ break;
|
||
+ }
|
||
+ _ => {}
|
||
+ }
|
||
+
|
||
+ pos = s;
|
||
+ }
|
||
+
|
||
+ Ok(dmi)
|
||
+}
|
||
|
||
diff --git a/drivers/acpid/src/acpi.rs b/drivers/acpid/src/acpi.rs
|
||
--- a/drivers/acpid/src/acpi.rs
|
||
+++ b/drivers/acpid/src/acpi.rs
|
||
@@ -95,12 +95,12 @@
|
||
BadChecksum,
|
||
}
|
||
|
||
-struct PhysmapGuard {
|
||
+pub struct PhysmapGuard {
|
||
virt: *const u8,
|
||
size: usize,
|
||
}
|
||
impl PhysmapGuard {
|
||
- fn map(page: usize, page_count: usize) -> std::io::Result<Self> {
|
||
+ pub fn map(page: usize, page_count: usize) -> std::io::Result<Self> {
|
||
let size = page_count * PAGE_SIZE;
|
||
let virt = unsafe {
|
||
common::physmap(page, size, common::Prot::RO, common::MemoryType::default())
|
||
@@ -245,26 +245,55 @@
|
||
symbol_cache: FxHashMap<String, String>,
|
||
page_cache: Arc<Mutex<AmlPageCache>>,
|
||
aml_region_handlers: Vec<(RegionSpace, Box<dyn RegionHandler>)>,
|
||
+ pci_fd: Arc<parking_lot::RwLock<Option<libredox::Fd>>>,
|
||
}
|
||
|
||
impl AmlSymbols {
|
||
- pub fn new(aml_region_handlers: Vec<(RegionSpace, Box<dyn RegionHandler>)>) -> Self {
|
||
+ pub fn new(aml_region_handlers: Vec<(RegionSpace, Box<dyn RegionHandler>)>, pci_fd: Arc<parking_lot::RwLock<Option<libredox::Fd>>>) -> Self {
|
||
Self {
|
||
aml_context: None,
|
||
symbol_cache: FxHashMap::default(),
|
||
page_cache: Arc::new(Mutex::new(AmlPageCache::default())),
|
||
aml_region_handlers,
|
||
+ pci_fd,
|
||
}
|
||
}
|
||
|
||
- pub fn init(&mut self, pci_fd: Option<&libredox::Fd>) -> Result<(), Box<dyn Error>> {
|
||
+ pub fn init(&mut self) -> Result<(), Box<dyn Error>> {
|
||
if self.aml_context.is_some() {
|
||
return Err("AML interpreter already initialized".into());
|
||
}
|
||
let format_err = |err| format!("{:?}", err);
|
||
- let handler = AmlPhysMemHandler::new(pci_fd, Arc::clone(&self.page_cache));
|
||
+ let handler = AmlPhysMemHandler::new(Arc::clone(&self.pci_fd), Arc::clone(&self.page_cache));
|
||
//TODO: use these parsed tables for the rest of acpid
|
||
- let rsdp_address = usize::from_str_radix(&std::env::var("RSDP_ADDR")?, 16)?;
|
||
+ let rsdp_address = match std::env::var("RSDP_ADDR") {
|
||
+ Ok(addr) => usize::from_str_radix(&addr, 16)?,
|
||
+ Err(_) => {
|
||
+ // RSDP_ADDR not provided — probe BIOS area (0xE0000–0xFFFFF) for RSDP signature
|
||
+ log::info!("RSDP_ADDR not set, probing BIOS area for RSDP...");
|
||
+ let mut found = None;
|
||
+ for page_base in (0xE_0000..0x10_0000).step_by(16) {
|
||
+ let mapped = unsafe {
|
||
+ common::physmap(
|
||
+ page_base,
|
||
+ 16,
|
||
+ common::Prot::RW,
|
||
+ common::MemoryType::default(),
|
||
+ )
|
||
+ };
|
||
+ if let Ok(virt) = mapped {
|
||
+ let sig = unsafe { std::slice::from_raw_parts(virt as *const u8, 8) };
|
||
+ if sig == b"RSD PTR " {
|
||
+ log::info!("found RSDP at physical {:#x}", page_base);
|
||
+ found = Some(page_base);
|
||
+ break;
|
||
+ }
|
||
+ let _ = unsafe { libredox::call::munmap(virt as *mut (), 16) };
|
||
+ }
|
||
+ }
|
||
+ found.ok_or("RSDP not found in BIOS area (0xE0000-0xFFFFF)")?
|
||
+ }
|
||
+ };
|
||
let tables =
|
||
unsafe { AcpiTables::from_rsdp(handler.clone(), rsdp_address).map_err(format_err)? };
|
||
let platform = AcpiPlatform::new(tables, handler).map_err(format_err)?;
|
||
@@ -278,10 +307,9 @@
|
||
|
||
pub fn aml_context_mut(
|
||
&mut self,
|
||
- pci_fd: Option<&libredox::Fd>,
|
||
) -> Result<&mut Interpreter<AmlPhysMemHandler>, AmlEvalError> {
|
||
if self.aml_context.is_none() {
|
||
- match self.init(pci_fd) {
|
||
+ match self.init() {
|
||
Ok(()) => (),
|
||
Err(err) => {
|
||
log::error!("failed to initialize AML context: {}", err);
|
||
@@ -305,8 +333,8 @@
|
||
None
|
||
}
|
||
|
||
- pub fn build_cache(&mut self, pci_fd: Option<&libredox::Fd>) {
|
||
- let Ok(aml_context) = self.aml_context_mut(pci_fd) else {
|
||
+ pub fn build_cache(&mut self) {
|
||
+ let Ok(aml_context) = self.aml_context_mut() else {
|
||
return;
|
||
};
|
||
|
||
@@ -382,6 +410,8 @@
|
||
|
||
aml_symbols: RwLock<AmlSymbols>,
|
||
|
||
+ pub pci_fd: Arc<parking_lot::RwLock<Option<libredox::Fd>>>,
|
||
+
|
||
// TODO: The kernel ACPI code seemed to use load_table quite ubiquitously, however ACPI 5.1
|
||
// states that DDBHandles can only be obtained when loading XSDT-pointed tables. So, we'll
|
||
// generate an index only for those.
|
||
@@ -397,7 +427,7 @@
|
||
args: Vec<AmlSerdeValue>,
|
||
) -> Result<AmlSerdeValue, AmlEvalError> {
|
||
let mut symbols = self.aml_symbols.write();
|
||
- let interpreter = symbols.aml_context_mut(None)?;
|
||
+ let interpreter = symbols.aml_context_mut()?;
|
||
interpreter.acquire_global_lock(16)?;
|
||
|
||
let args = args
|
||
@@ -440,13 +470,17 @@
|
||
})
|
||
.collect::<Vec<Sdt>>();
|
||
|
||
+ let pci_fd = Arc::new(parking_lot::RwLock::new(None));
|
||
+
|
||
let mut this = Self {
|
||
tables,
|
||
dsdt: None,
|
||
fadt: None,
|
||
|
||
// Temporary values
|
||
- aml_symbols: RwLock::new(AmlSymbols::new(ec)),
|
||
+ aml_symbols: RwLock::new(AmlSymbols::new(ec, Arc::clone(&pci_fd))),
|
||
+
|
||
+ pci_fd,
|
||
|
||
next_ctx: RwLock::new(0),
|
||
|
||
@@ -526,7 +560,7 @@
|
||
}
|
||
|
||
pub fn aml_lookup(&self, symbol: &str) -> Option<String> {
|
||
- if let Ok(aml_symbols) = self.aml_symbols(None) {
|
||
+ if let Ok(aml_symbols) = self.aml_symbols() {
|
||
aml_symbols.lookup(symbol)
|
||
} else {
|
||
None
|
||
@@ -535,7 +569,6 @@
|
||
|
||
pub fn aml_symbols(
|
||
&self,
|
||
- pci_fd: Option<&libredox::Fd>,
|
||
) -> Result<RwLockReadGuard<'_, AmlSymbols>, AmlError> {
|
||
// return the cached value if it exists
|
||
let symbols = self.aml_symbols.read();
|
||
@@ -550,7 +583,7 @@
|
||
|
||
let mut aml_symbols = self.aml_symbols.write();
|
||
|
||
- aml_symbols.build_cache(pci_fd);
|
||
+ aml_symbols.build_cache();
|
||
|
||
// return the cached value
|
||
Ok(RwLockWriteGuard::downgrade(aml_symbols))
|
||
|
||
diff --git a/drivers/acpid/src/main.rs b/drivers/acpid/src/main.rs
|
||
--- a/drivers/acpid/src/main.rs
|
||
+++ b/drivers/acpid/src/main.rs
|
||
@@ -14,6 +14,7 @@
|
||
mod aml_physmem;
|
||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||
mod ec;
|
||
+mod dmi;
|
||
|
||
mod scheme;
|
||
|
||
@@ -73,6 +74,14 @@
|
||
];
|
||
let acpi_context = self::acpi::AcpiContext::init(physaddrs_iter, region_handlers);
|
||
|
||
+ let dmi_strings = match self::dmi::read_smbios_dmi() {
|
||
+ Ok(strings) => Some(strings),
|
||
+ Err(e) => {
|
||
+ log::warn!("Failed to read SMBIOS DMI: {}", e);
|
||
+ None
|
||
+ }
|
||
+ };
|
||
+
|
||
// TODO: I/O permission bitmap?
|
||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||
common::acquire_port_io_rights().expect("acpid: failed to set I/O privilege level to Ring 3");
|
||
@@ -83,7 +92,7 @@
|
||
let mut event_queue = RawEventQueue::new().expect("acpid: failed to create event queue");
|
||
let socket = Socket::nonblock().expect("acpid: failed to create disk scheme");
|
||
|
||
- let mut scheme = self::scheme::AcpiScheme::new(&acpi_context, &socket);
|
||
+ let mut scheme = self::scheme::AcpiScheme::new(&acpi_context, &socket, dmi_strings);
|
||
let mut handler = Blocking::new(&socket, 16);
|
||
|
||
event_queue
|
||
|
||
diff --git a/drivers/acpid/src/scheme.rs b/drivers/acpid/src/scheme.rs
|
||
--- a/drivers/acpid/src/scheme.rs
|
||
+++ b/drivers/acpid/src/scheme.rs
|
||
@@ -22,12 +22,13 @@
|
||
use syscall::{EOVERFLOW, EPERM};
|
||
|
||
use crate::acpi::{AcpiContext, AmlSymbols, SdtSignature};
|
||
+use crate::dmi::DmiStrings;
|
||
|
||
pub struct AcpiScheme<'acpi, 'sock> {
|
||
ctx: &'acpi AcpiContext,
|
||
handles: HandleMap<Handle<'acpi>>,
|
||
- pci_fd: Option<Fd>,
|
||
socket: &'sock Socket,
|
||
+ dmi_text: Option<String>,
|
||
}
|
||
|
||
struct Handle<'a> {
|
||
@@ -43,6 +44,7 @@
|
||
Symbol { name: String, description: String },
|
||
SchemeRoot,
|
||
RegisterPci,
|
||
+ Dmi(String),
|
||
}
|
||
|
||
impl HandleKind<'_> {
|
||
@@ -55,6 +57,7 @@
|
||
Self::Symbol { .. } => false,
|
||
Self::SchemeRoot => false,
|
||
Self::RegisterPci => false,
|
||
+ Self::Dmi(_) => false,
|
||
}
|
||
}
|
||
fn len(&self, acpi_ctx: &AcpiContext) -> Result<usize> {
|
||
@@ -65,6 +68,7 @@
|
||
.ok_or(Error::new(EBADFD))?
|
||
.length(),
|
||
Self::Symbol { description, .. } => description.len(),
|
||
+ Self::Dmi(text) => text.len(),
|
||
// Directories
|
||
Self::TopLevel | Self::Symbols(_) | Self::Tables => 0,
|
||
Self::SchemeRoot | Self::RegisterPci => return Err(Error::new(EBADF)),
|
||
@@ -73,12 +77,12 @@
|
||
}
|
||
|
||
impl<'acpi, 'sock> AcpiScheme<'acpi, 'sock> {
|
||
- pub fn new(ctx: &'acpi AcpiContext, socket: &'sock Socket) -> Self {
|
||
+ pub fn new(ctx: &'acpi AcpiContext, socket: &'sock Socket, dmi: Option<DmiStrings>) -> Self {
|
||
Self {
|
||
ctx,
|
||
handles: HandleMap::new(),
|
||
- pci_fd: None,
|
||
socket,
|
||
+ dmi_text: dmi.map(|d| d.to_text()),
|
||
}
|
||
}
|
||
}
|
||
@@ -196,6 +200,7 @@
|
||
match &*components {
|
||
[""] => HandleKind::TopLevel,
|
||
["register_pci"] => HandleKind::RegisterPci,
|
||
+ ["dmi"] => HandleKind::Dmi(self.dmi_text.clone().unwrap_or_default()),
|
||
["tables"] => HandleKind::Tables,
|
||
|
||
["tables", table] => {
|
||
@@ -204,7 +209,7 @@
|
||
}
|
||
|
||
["symbols"] => {
|
||
- if let Ok(aml_symbols) = self.ctx.aml_symbols(self.pci_fd.as_ref()) {
|
||
+ if let Ok(aml_symbols) = self.ctx.aml_symbols() {
|
||
HandleKind::Symbols(aml_symbols)
|
||
} else {
|
||
return Err(Error::new(EIO));
|
||
@@ -309,6 +314,7 @@
|
||
.ok_or(Error::new(EBADFD))?
|
||
.as_slice(),
|
||
HandleKind::Symbol { description, .. } => description.as_bytes(),
|
||
+ HandleKind::Dmi(ref text) => text.as_bytes(),
|
||
_ => return Err(Error::new(EINVAL)),
|
||
};
|
||
|
||
@@ -332,9 +338,13 @@
|
||
|
||
match &handle.kind {
|
||
HandleKind::TopLevel => {
|
||
- const TOPLEVEL_ENTRIES: &[&str] = &["tables", "symbols"];
|
||
+ const TOPLEVEL_ENTRIES: &[(DirentKind, &str)] = &[
|
||
+ (DirentKind::Regular, "dmi"),
|
||
+ (DirentKind::Directory, "tables"),
|
||
+ (DirentKind::Directory, "symbols"),
|
||
+ ];
|
||
|
||
- for (idx, name) in TOPLEVEL_ENTRIES
|
||
+ for (idx, (kind, name)) in TOPLEVEL_ENTRIES
|
||
.iter()
|
||
.enumerate()
|
||
.skip(opaque_offset as usize)
|
||
@@ -343,7 +353,7 @@
|
||
inode: 0,
|
||
next_opaque_id: idx as u64 + 1,
|
||
name,
|
||
- kind: DirentKind::Directory,
|
||
+ kind: *kind,
|
||
})?;
|
||
}
|
||
}
|
||
@@ -470,10 +480,12 @@
|
||
}
|
||
let new_fd = libredox::Fd::new(new_fd);
|
||
|
||
- if self.pci_fd.is_some() {
|
||
- return Err(Error::new(EINVAL));
|
||
- } else {
|
||
- self.pci_fd = Some(new_fd);
|
||
+ {
|
||
+ let mut pci_fd = self.ctx.pci_fd.write();
|
||
+ if pci_fd.is_some() {
|
||
+ return Err(Error::new(EINVAL));
|
||
+ }
|
||
+ *pci_fd = Some(new_fd);
|
||
}
|
||
|
||
Ok(num_fds)
|