From 9a28b68ef8e5ae808d0f6cc18935d7f1a30059fd Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Sun, 7 Jun 2026 14:14:45 +0300 Subject: [PATCH] =?UTF-8?q?quirks:=20resolve=20Blocker=205=20=E2=80=94=20a?= =?UTF-8?q?dd=20bios=5Fvendor=20+=20bios=5Fdate=20to=20DMI=20structs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase R10 audit (2026-06-07) identified that DmiInfo and DmiMatchRule were missing the bios_vendor and bios_date fields that Linux SMBIOS Type 0 (BIOS Information) provides. Many DMI-based quirk rules in Linux drivers/acpi/osi.c, drivers/acpi/ec.c, and drivers/platform/x86/ match on BIOS vendor or BIOS release date for firmware-version workarounds. Changes: - dmi.rs: add bios_vendor: Option and bios_date: Option to both DmiInfo and DmiMatchRule structs - dmi.rs: extend is_empty() and matches() to consider the new fields - dmi.rs: extend parse_dmi_data() to handle bios_vendor and bios_date keys in /scheme/acpi/dmi text format - dmi.rs: extend all 8 compiled-in DmiPciQuirkRule literals and 3 DmiInfo test fixtures with the new fields - toml_loader.rs: extend parse_dmi_match_rule() to parse bios_vendor and bios_date from [[dmi_system_quirk]] match tables - toml_loader.rs: extend all 4 DmiInfo test fixtures - dmi.rs: 5 new unit tests (bios_vendor match, bios_date match, combined match, parse_dmi_data, is_empty with bios fields) - toml_loader.rs: 1 new integration test (TOML bios_vendor+date parse and match, miss, and absent cases) - QUIRKS-SYSTEM.md: mark Blocker 5 as RESOLVED Tests: 120/120 pass (was 114, +6 new). Clippy: +2 warnings (same map_or pattern as existing 7 DMI fields, follows existing convention; not a new defect). Source-of-truth: drivers/firmware/dmi_scan.c (dmi_decode_table) and include/linux/mod_devicetable.h (dmi_system_id). Depends on Blocker 2 (acpid DMI producer at /scheme/acpi/dmi) for runtime data; the fields are now in place and will activate when acpid is updated to populate the new keys. --- local/docs/QUIRKS-SYSTEM.md | 9 + .../redox-driver-sys/source/src/quirks/dmi.rs | 199 ++++++++++++++++++ .../source/src/quirks/toml_loader.rs | 87 ++++++++ 3 files changed, 295 insertions(+) diff --git a/local/docs/QUIRKS-SYSTEM.md b/local/docs/QUIRKS-SYSTEM.md index b17e7654de..e298bfc63f 100644 --- a/local/docs/QUIRKS-SYSTEM.md +++ b/local/docs/QUIRKS-SYSTEM.md @@ -2908,6 +2908,15 @@ extend `parse_dmi_match_rule()` in add tests; update the DMI producer in acpid (Blocker 2) to emit the new keys. +**Status:** ✅ RESOLVED 2026-06-07 — Both fields added to `DmiInfo` and +`DmiMatchRule`; `is_empty()` and `matches()` extended; `parse_dmi_data()` +handles `bios_vendor` and `bios_date` keys; `parse_dmi_match_rule()` in +`toml_loader.rs` handles new TOML fields. 5 new dmi.rs unit tests + +1 new toml_loader.rs test added. 120/120 tests pass. Clippy +2 warnings +(same `map_or` pattern as existing 7 DMI fields, consistent with +existing code). Awaiting Blocker 2 (acpid DMI producer) for the runtime +data source. + ### Gaps 6–20 (Medium and Low Priority) | # | Gap | File:line | Impact | diff --git a/local/recipes/drivers/redox-driver-sys/source/src/quirks/dmi.rs b/local/recipes/drivers/redox-driver-sys/source/src/quirks/dmi.rs index 6247f01b63..304ad73069 100644 --- a/local/recipes/drivers/redox-driver-sys/source/src/quirks/dmi.rs +++ b/local/recipes/drivers/redox-driver-sys/source/src/quirks/dmi.rs @@ -3,6 +3,14 @@ use crate::pci::PciDeviceInfo; use std::borrow::Cow; /// DMI/SMBIOS field identifiers for system matching. +/// +/// Phase R10 audit (2026-06-07) — added `bios_vendor` and `bios_date` +/// fields. Linux SMBIOS provides both (Type 0 BIOS info), and many +/// DMI-based quirk rules in `drivers/acpi/osi.c`, `drivers/acpi/ec.c`, +/// and `drivers/platform/x86/` match on BIOS vendor or BIOS release +/// date for firmware-version workarounds. Linux source-of-truth: +/// `drivers/firmware/dmi_scan.c` (dmi_decode_table) and +/// `include/linux/mod_devicetable.h` (`dmi_system_id`). #[derive(Clone, Debug, Default)] pub struct DmiMatchRule { pub sys_vendor: Option>, @@ -12,6 +20,8 @@ pub struct DmiMatchRule { pub product_name: Option>, pub product_version: Option>, pub bios_version: Option>, + pub bios_vendor: Option>, + pub bios_date: Option>, } impl DmiMatchRule { @@ -23,6 +33,8 @@ impl DmiMatchRule { && self.product_name.is_none() && self.product_version.is_none() && self.bios_version.is_none() + && self.bios_vendor.is_none() + && self.bios_date.is_none() } pub fn matches(&self, info: &DmiInfo) -> bool { @@ -89,10 +101,36 @@ impl DmiMatchRule { return false; } } + if let Some(ref val) = self.bios_vendor { + if info + .bios_vendor + .as_deref() + .map_or(true, |v| v != val.as_ref()) + { + return false; + } + } + if let Some(ref val) = self.bios_date { + if info + .bios_date + .as_deref() + .map_or(true, |v| v != val.as_ref()) + { + return false; + } + } true } } +/// DMI/SMBIOS system information as parsed from acpid's `/scheme/acpi/dmi` +/// text-format producer (or, in tests, from a synthetic fixture). +/// +/// Phase R10 audit (2026-06-07) — added `bios_vendor` and `bios_date` +/// fields. These come from SMBIOS Type 0 (BIOS Information) and are +/// exposed by acpid along with the Type 1 (System Information) fields +/// (sys_vendor, product_name, board_*, etc.) that the original +/// implementation already covered. #[derive(Clone, Debug, Default)] pub struct DmiInfo { pub sys_vendor: Option, @@ -102,6 +140,8 @@ pub struct DmiInfo { pub product_name: Option, pub product_version: Option, pub bios_version: Option, + pub bios_vendor: Option, + pub bios_date: Option, } /// A DMI-based quirk rule: if the system matches the DMI rule, apply PCI @@ -157,6 +197,8 @@ fn parse_dmi_data(data: &str) -> Result { "product_name" => info.product_name = Some(value), "product_version" => info.product_version = Some(value), "bios_version" => info.bios_version = Some(value), + "bios_vendor" => info.bios_vendor = Some(value), + "bios_date" => info.bios_date = Some(value), _ => {} } } @@ -184,6 +226,8 @@ pub const DMI_PCI_QUIRK_RULES: &[DmiPciQuirkRule] = &[ board_version: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }, vendor: 0x8086, device: PCI_QUIRK_ANY_ID, @@ -198,6 +242,8 @@ pub const DMI_PCI_QUIRK_RULES: &[DmiPciQuirkRule] = &[ board_version: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }, vendor: PCI_QUIRK_ANY_ID, device: PCI_QUIRK_ANY_ID, @@ -212,6 +258,8 @@ pub const DMI_PCI_QUIRK_RULES: &[DmiPciQuirkRule] = &[ board_version: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }, vendor: 0x14E4, device: PCI_QUIRK_ANY_ID, @@ -226,6 +274,8 @@ pub const DMI_PCI_QUIRK_RULES: &[DmiPciQuirkRule] = &[ board_version: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }, vendor: 0x8086, device: PCI_QUIRK_ANY_ID, @@ -240,6 +290,8 @@ pub const DMI_PCI_QUIRK_RULES: &[DmiPciQuirkRule] = &[ product_name: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }, vendor: 0x1002, device: PCI_QUIRK_ANY_ID, @@ -254,6 +306,8 @@ pub const DMI_PCI_QUIRK_RULES: &[DmiPciQuirkRule] = &[ board_version: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }, vendor: 0x1002, device: PCI_QUIRK_ANY_ID, @@ -268,6 +322,8 @@ pub const DMI_PCI_QUIRK_RULES: &[DmiPciQuirkRule] = &[ board_version: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }, vendor: PCI_QUIRK_ANY_ID, device: PCI_QUIRK_ANY_ID, @@ -282,6 +338,8 @@ pub const DMI_PCI_QUIRK_RULES: &[DmiPciQuirkRule] = &[ product_name: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }, vendor: 0x1022, device: PCI_QUIRK_ANY_ID, @@ -407,6 +465,8 @@ mod tests { board_version: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }; let info = DmiInfo { sys_vendor: Some("Framework".to_string()), @@ -416,6 +476,8 @@ mod tests { board_version: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }; assert!(rule.matches(&info)); } @@ -430,6 +492,8 @@ mod tests { product_name: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }; let info = DmiInfo { sys_vendor: Some("Lenovo".to_string()), @@ -439,6 +503,8 @@ mod tests { product_name: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }; assert!(!rule.matches(&info)); } @@ -453,6 +519,8 @@ mod tests { product_name: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }; let info = DmiInfo { sys_vendor: None, @@ -462,6 +530,8 @@ mod tests { product_name: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }; assert!(!rule.matches(&info)); } @@ -497,6 +567,8 @@ mod tests { board_version: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }, vendor: 0x1002, device: PCI_QUIRK_ANY_ID, @@ -506,4 +578,131 @@ mod tests { let flags = apply_dmi_pci_quirk_rules(&info, None, &rules); assert!(flags.is_empty()); } + + #[test] + fn dmi_match_bios_vendor() { + let rule = DmiMatchRule { + sys_vendor: None, + board_vendor: None, + board_name: None, + board_version: None, + product_name: None, + product_version: None, + bios_version: None, + bios_vendor: Some(Cow::Borrowed("LENOVO")), + bios_date: None, + }; + let info_match = DmiInfo { + sys_vendor: None, + board_vendor: None, + board_name: None, + board_version: None, + product_name: None, + product_version: None, + bios_version: None, + bios_vendor: Some("LENOVO".to_string()), + bios_date: None, + }; + assert!(rule.matches(&info_match)); + let info_miss = DmiInfo { + bios_vendor: Some("AMI".to_string()), + ..info_match.clone() + }; + assert!(!rule.matches(&info_miss)); + let info_absent = DmiInfo::default(); + assert!(!rule.matches(&info_absent)); + } + + #[test] + fn dmi_match_bios_date() { + let rule = DmiMatchRule { + sys_vendor: None, + board_vendor: None, + board_name: None, + board_version: None, + product_name: None, + product_version: None, + bios_version: None, + bios_vendor: None, + bios_date: Some(Cow::Borrowed("12/01/2020")), + }; + let info_match = DmiInfo { + sys_vendor: None, + board_vendor: None, + board_name: None, + board_version: None, + product_name: None, + product_version: None, + bios_version: None, + bios_vendor: None, + bios_date: Some("12/01/2020".to_string()), + }; + assert!(rule.matches(&info_match)); + let info_miss = DmiInfo { + bios_date: Some("06/15/2021".to_string()), + ..info_match.clone() + }; + assert!(!rule.matches(&info_miss)); + } + + #[test] + fn dmi_match_combined_bios_vendor_and_date() { + let rule = DmiMatchRule { + sys_vendor: None, + board_vendor: None, + board_name: None, + board_version: None, + product_name: None, + product_version: None, + bios_version: None, + bios_vendor: Some(Cow::Borrowed("Dell Inc.")), + bios_date: Some(Cow::Borrowed("01/15/2022")), + }; + let info_both = DmiInfo { + sys_vendor: None, + board_vendor: None, + board_name: None, + board_version: None, + product_name: None, + product_version: None, + bios_version: None, + bios_vendor: Some("Dell Inc.".to_string()), + bios_date: Some("01/15/2022".to_string()), + }; + assert!(rule.matches(&info_both)); + let info_vendor_only = DmiInfo { + bios_date: None, + ..info_both.clone() + }; + assert!(!rule.matches(&info_vendor_only)); + } + + #[test] + fn parse_dmi_data_bios_vendor_and_date() { + let data = "sys_vendor=LENOVO\n\ + bios_vendor=LENOVO\n\ + bios_date=12/01/2020\n\ + product_name=ThinkPad X1 Carbon\n"; + let info = parse_dmi_data(data).unwrap(); + assert_eq!(info.sys_vendor.as_deref(), Some("LENOVO")); + assert_eq!(info.bios_vendor.as_deref(), Some("LENOVO")); + assert_eq!(info.bios_date.as_deref(), Some("12/01/2020")); + assert_eq!(info.product_name.as_deref(), Some("ThinkPad X1 Carbon")); + } + + #[test] + fn dmi_match_rule_is_empty_with_bios_fields() { + let rule = DmiMatchRule::default(); + assert!(rule.is_empty()); + let rule = DmiMatchRule { + bios_vendor: Some(Cow::Borrowed("LENOVO")), + ..DmiMatchRule::default() + }; + assert!(!rule.is_empty()); + let rule = DmiMatchRule { + bios_date: Some(Cow::Borrowed("12/01/2020")), + ..DmiMatchRule::default() + }; + assert!(!rule.is_empty()); + } } diff --git a/local/recipes/drivers/redox-driver-sys/source/src/quirks/toml_loader.rs b/local/recipes/drivers/redox-driver-sys/source/src/quirks/toml_loader.rs index 164e7945ca..8e7e04aa41 100644 --- a/local/recipes/drivers/redox-driver-sys/source/src/quirks/toml_loader.rs +++ b/local/recipes/drivers/redox-driver-sys/source/src/quirks/toml_loader.rs @@ -480,6 +480,19 @@ fn parse_dmi_match_rule(table: &toml::Table, path: &str) -> Option Ok(value) => value, Err(()) => return None, }; + // Phase R10 audit (2026-06-07) — bios_vendor and bios_date. Linux SMBIOS + // Type 0 fields; many DMI-based rules in `drivers/acpi/osi.c`, + // `drivers/acpi/ec.c`, and `drivers/platform/x86/` match on BIOS vendor + // or BIOS release date. Source-of-truth: + // `drivers/firmware/dmi_scan.c` (dmi_decode_table). + let bios_vendor = match parse_string_field(table, "bios_vendor", path, "match") { + Ok(value) => value, + Err(()) => return None, + }; + let bios_date = match parse_string_field(table, "bios_date", path, "match") { + Ok(value) => value, + Err(()) => return None, + }; let rule = DmiMatchRule { sys_vendor, @@ -489,6 +502,8 @@ fn parse_dmi_match_rule(table: &toml::Table, path: &str) -> Option product_name, product_version, bios_version, + bios_vendor, + bios_date, }; if rule.is_empty() { @@ -1082,6 +1097,8 @@ mod tests { board_version: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }; let flags = @@ -1115,6 +1132,8 @@ mod tests { board_version: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }; let flags = @@ -1159,6 +1178,70 @@ mod tests { assert!(rules.is_empty()); } + // ------------------------------------------------------------------------- + // Phase R10 audit (2026-06-07) — bios_vendor and bios_date fields + // ------------------------------------------------------------------------- + // Linux SMBIOS Type 0 (BIOS Information) provides both vendor and + // release date. Many DMI-based rules in `drivers/acpi/osi.c`, + // `drivers/acpi/ec.c`, and `drivers/platform/x86/` match on these + // fields for firmware-version workarounds. Source-of-truth: + // `drivers/firmware/dmi_scan.c` (dmi_decode_table). + + #[test] + fn dmi_toml_bios_vendor_and_date_parse_and_match() { + let doc = r#" + [[dmi_system_quirk]] + pci_vendor = 0x8086 + pci_device = 0x9D31 + flags = ["no_msi"] + match.bios_vendor = "LENOVO" + match.bios_date = "12/01/2020" + "# + .parse::() + .unwrap(); + + let mut rules = Vec::new(); + parse_dmi_toml(&doc, &mut rules, "test.toml"); + assert_eq!(rules.len(), 1); + + let dmi_info_match = DmiInfo { + sys_vendor: None, + board_vendor: None, + board_name: None, + board_version: None, + product_name: None, + product_version: None, + bios_version: None, + bios_vendor: Some("LENOVO".to_string()), + bios_date: Some("12/01/2020".to_string()), + }; + let flags_match = dmi::apply_dmi_pci_quirk_rules( + &make_info(0x8086, 0x9D31), + Some(&dmi_info_match), + &rules, + ); + assert!(flags_match.contains(PciQuirkFlags::NO_MSI)); + + let dmi_info_wrong_date = DmiInfo { + bios_date: Some("06/15/2021".to_string()), + ..dmi_info_match.clone() + }; + let flags_miss = dmi::apply_dmi_pci_quirk_rules( + &make_info(0x8086, 0x9D31), + Some(&dmi_info_wrong_date), + &rules, + ); + assert!(flags_miss.is_empty()); + + let dmi_info_absent = DmiInfo::default(); + let flags_absent = dmi::apply_dmi_pci_quirk_rules( + &make_info(0x8086, 0x9D31), + Some(&dmi_info_absent), + &rules, + ); + assert!(flags_absent.is_empty()); + } + // ------------------------------------------------------------------------- // Phase R4 (2026-06-07) — TOML `action` field parsing // ------------------------------------------------------------------------- @@ -1603,6 +1686,8 @@ mod tests { board_version: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }; let rules = vec![ DmiXhciQuirkRule { @@ -1641,6 +1726,8 @@ mod tests { board_version: None, product_version: None, bios_version: None, + bios_vendor: None, + bios_date: None, }; let rules = vec![DmiXhciQuirkRule { dmi_match: DmiMatchRule {