-
Notifications
You must be signed in to change notification settings - Fork 1
--versions: Get AGESA version from SMBIOS Type 40 #310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,7 +4,7 @@ use std::prelude::v1::*; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use crate::util::Config; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub use crate::util::{Platform, PlatformFamily}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use dmidecode::{EntryPoint, Structure}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use dmidecode::{EntryPoint, InfoType, RawStructure, Structure}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use num_derive::FromPrimitive; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use num_traits::FromPrimitive; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[cfg(feature = "uefi")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -174,6 +174,57 @@ pub fn get_family() -> Option<PlatformFamily> { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| get_platform().and_then(Platform::which_family) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Minimum size of an Additional Information entry (SMBIOS Type 40) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const DMI_A_INFO_ENT_MIN_SIZE: usize = 6; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Extract AGESA version string from an SMBIOS Type 40 (Additional Information) structure. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// On AMD Zen systems, the AGESA version is stored here. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Sample string: "AGESA!V9 StrixKrackanPI-FP8 1.1.0.0c" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn find_agesa_in_type40(raw: &RawStructure) -> Option<String> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if raw.info != InfoType::Oem(40) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return None; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // raw.data layout (after the 4-byte header): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // [0]: count — number of Additional Information entries | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // [1..]: entries, each starting with a length byte | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let count = *raw.data.first()? as usize; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut remaining = raw.data.get(1..)?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for _ in 0..count { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if remaining.len() < DMI_A_INFO_ENT_MIN_SIZE { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let entry_len = remaining[0] as usize; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if entry_len == 0 || entry_len > remaining.len() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // String number is at offset 4 within the entry | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let str_num = remaining[4]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if let Ok(s) = raw.find_string(str_num) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if s.starts_with("AGESA") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Some(s.to_string()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| remaining = &remaining[entry_len..]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+189
to
+210
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // raw.data layout (after the 4-byte header): | |
| // [0]: count — number of Additional Information entries | |
| // [1..]: entries, each starting with a length byte | |
| let count = *raw.data.first()? as usize; | |
| let mut remaining = raw.data.get(1..)?; | |
| for _ in 0..count { | |
| if remaining.len() < DMI_A_INFO_ENT_MIN_SIZE { | |
| break; | |
| } | |
| let entry_len = remaining[0] as usize; | |
| if entry_len == 0 || entry_len > remaining.len() { | |
| break; | |
| } | |
| // String number is at offset 4 within the entry | |
| let str_num = remaining[4]; | |
| if let Ok(s) = raw.find_string(str_num) { | |
| if s.starts_with("AGESA") { | |
| return Some(s.to_string()); | |
| } | |
| } | |
| remaining = &remaining[entry_len..]; | |
| // SMBIOS Type 40 formatted section: | |
| // offset 0x04: count — number of Additional Information entries | |
| // offset 0x05: entries, each starting with a length byte | |
| let count = usize::from(*raw.get::<u8>(4).ok()?); | |
| let mut offset = 5usize; | |
| let structure_len = usize::from(raw.length); | |
| for _ in 0..count { | |
| if offset + DMI_A_INFO_ENT_MIN_SIZE > structure_len { | |
| break; | |
| } | |
| let entry_len = match raw.get::<u8>(offset) { | |
| Ok(len) => usize::from(*len), | |
| Err(_) => break, | |
| }; | |
| if entry_len == 0 || offset + entry_len > structure_len { | |
| break; | |
| } | |
| // String number is at offset 4 within the entry | |
| let str_num = match raw.get::<u8>(offset + 4) { | |
| Ok(num) => *num, | |
| Err(_) => break, | |
| }; | |
| if let Ok(s) = raw.find_string(str_num) { | |
| if s.starts_with("AGESA") { | |
| return Some(s.to_string()); | |
| } | |
| } | |
| offset += entry_len; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type 40 entry parsing uses
entry_lento delimit each Additional Information entry, but it doesn’t validate thatentry_lenis at least the minimum size needed to read the string number at offset 4. Ifentry_lenis < 5/6,remaining[4]is read from outside the current entry, which can mis-associate strings and return an incorrect AGESA value on malformed tables. Add a check likeif entry_len < DMI_A_INFO_ENT_MIN_SIZE { break/continue; }before readingremaining[4](and consider skipping to the next entry if you can safely advance).