@@ -4,7 +4,7 @@ use std::prelude::v1::*;
44
55use crate :: util:: Config ;
66pub use crate :: util:: { Platform , PlatformFamily } ;
7- use dmidecode:: { EntryPoint , Structure } ;
7+ use dmidecode:: { EntryPoint , InfoType , RawStructure , Structure } ;
88use num_derive:: FromPrimitive ;
99use num_traits:: FromPrimitive ;
1010#[ cfg( feature = "uefi" ) ]
@@ -174,6 +174,64 @@ pub fn get_family() -> Option<PlatformFamily> {
174174 get_platform ( ) . and_then ( Platform :: which_family)
175175}
176176
177+ /// SMBIOS Type 40 Additional Information entry minimum size
178+ const DMI_A_INFO_ENT_MIN_SIZE : usize = 6 ;
179+
180+ /// Extract AGESA version string from SMBIOS Type 40 (Additional Information) entries.
181+ ///
182+ /// On AMD Zen systems, the AGESA version is stored in a Type 40 entry.
183+ /// Sample string: "AGESA!V9 StrixKrackanPI-FP8 1.1.0.0c"
184+ fn find_agesa_in_type40 ( raw : & RawStructure ) -> Option < String > {
185+ if raw. info != InfoType :: Oem ( 40 ) {
186+ return None ;
187+ }
188+
189+ // Type 40 formatted area (after 4-byte header):
190+ // offset 0x04: count (u8) — number of Additional Information entries
191+ // offset 0x05+: entries
192+ // raw.data starts after the header, so count is at data[0], entries at data[1..]
193+ let count = * raw. data . first ( ) ?;
194+ if count < 1 {
195+ return None ;
196+ }
197+
198+ let mut pos = 1 ; // start of entries in raw.data
199+ let data = raw. data ;
200+
201+ for _ in 0 ..count {
202+ if pos + DMI_A_INFO_ENT_MIN_SIZE > data. len ( ) {
203+ break ;
204+ }
205+ let entry_len = data[ pos] as usize ;
206+ if entry_len == 0 {
207+ break ;
208+ }
209+ // str_num is at offset 4 within the entry (pos+4)
210+ let str_num = data[ pos + 4 ] ;
211+ if let Ok ( s) = raw. find_string ( str_num) {
212+ if s. starts_with ( "AGESA" ) {
213+ return Some ( s. to_string ( ) ) ;
214+ }
215+ }
216+ pos += entry_len;
217+ }
218+
219+ None
220+ }
221+
222+ /// Get the AGESA version from SMBIOS Type 40 Additional Information entries
223+ pub fn get_agesa_version ( ) -> Option < String > {
224+ let smbios = get_smbios ( ) ?;
225+ for result in smbios. structures ( ) {
226+ if let Ok ( Structure :: Other ( ref raw) ) = result {
227+ if let Some ( agesa) = find_agesa_in_type40 ( raw) {
228+ return Some ( agesa) ;
229+ }
230+ }
231+ }
232+ None
233+ }
234+
177235pub fn get_platform ( ) -> Option < Platform > {
178236 #[ cfg( feature = "uefi" ) ]
179237 let mut cached_platform = CACHED_PLATFORM . lock ( ) ;
0 commit comments