--versions: Get AGESA version from SMBIOS Type 40#310
--versions: Get AGESA version from SMBIOS Type 40#310JohnAZoidberg wants to merge 1 commit intomainfrom
Conversation
Signed-off-by: Daniel Schaefer <dhs@frame.work>
There was a problem hiding this comment.
Pull request overview
Adds support for displaying the AMD AGESA version in --versions output by parsing SMBIOS Type 40 (“Additional Information”) entries and extracting the first string that starts with AGESA.
Changes:
- Parse SMBIOS Type 40 raw structures to locate an
AGESA…string and expose it via a newsmbios::get_agesa_version()helper. - Print the AGESA string in
framework_tool --versionsoutput when present. - Update
EXAMPLES.mdto show the new AGESA line in sample--versionsoutput.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
framework_lib/src/smbios.rs |
Adds Type 40 parsing helper and a public accessor to retrieve AGESA from SMBIOS. |
framework_lib/src/commandline/mod.rs |
Prints AGESA in --versions output when available. |
EXAMPLES.md |
Documents the new --versions output line including AGESA. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| 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) { |
There was a problem hiding this comment.
Type 40 entry parsing uses entry_len to delimit each Additional Information entry, but it doesn’t validate that entry_len is at least the minimum size needed to read the string number at offset 4. If entry_len is < 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 like if entry_len < DMI_A_INFO_ENT_MIN_SIZE { break/continue; } before reading remaining[4] (and consider skipping to the next entry if you can safely advance).
| // 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..]; |
There was a problem hiding this comment.
This parsing relies on raw.data and a comment that it is laid out “after the 4-byte header”. Elsewhere in this repo (e.g., framework_lib/src/csme.rs), RawStructure parsing consistently uses raw.get::<T>(offset) with SMBIOS offsets that include the 4-byte header, which avoids ambiguity about what raw.data contains and keeps bounds checks tied to raw.length. Consider switching Type 40 parsing to use raw.get(4) for count and then index subsequent bytes via raw.get()/raw.length (or clearly document/verify raw.data’s semantics) to prevent future off-by-4 mistakes if dmidecode’s representation differs from the assumption here.
| // 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; |
No description provided.