@@ -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,57 @@ pub fn get_family() -> Option<PlatformFamily> {
174174 get_platform ( ) . and_then ( Platform :: which_family)
175175}
176176
177+ /// Minimum size of an Additional Information entry (SMBIOS Type 40)
178+ const DMI_A_INFO_ENT_MIN_SIZE : usize = 6 ;
179+
180+ /// Extract AGESA version string from an SMBIOS Type 40 (Additional Information) structure.
181+ ///
182+ /// On AMD Zen systems, the AGESA version is stored here.
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+ // raw.data layout (after the 4-byte header):
190+ // [0]: count — number of Additional Information entries
191+ // [1..]: entries, each starting with a length byte
192+ let count = * raw. data . first ( ) ? as usize ;
193+ let mut remaining = raw. data . get ( 1 ..) ?;
194+
195+ for _ in 0 ..count {
196+ if remaining. len ( ) < DMI_A_INFO_ENT_MIN_SIZE {
197+ break ;
198+ }
199+ let entry_len = remaining[ 0 ] as usize ;
200+ if entry_len == 0 || entry_len > remaining. len ( ) {
201+ break ;
202+ }
203+ // String number is at offset 4 within the entry
204+ let str_num = remaining[ 4 ] ;
205+ if let Ok ( s) = raw. find_string ( str_num) {
206+ if s. starts_with ( "AGESA" ) {
207+ return Some ( s. to_string ( ) ) ;
208+ }
209+ }
210+ remaining = & remaining[ entry_len..] ;
211+ }
212+
213+ None
214+ }
215+
216+ /// Get the AGESA version from SMBIOS Type 40 Additional Information entries
217+ pub fn get_agesa_version ( ) -> Option < String > {
218+ let smbios = get_smbios ( ) ?;
219+ smbios. structures ( ) . find_map ( |result| {
220+ if let Ok ( Structure :: Other ( ref raw) ) = result {
221+ find_agesa_in_type40 ( raw)
222+ } else {
223+ None
224+ }
225+ } )
226+ }
227+
177228pub fn get_platform ( ) -> Option < Platform > {
178229 #[ cfg( feature = "uefi" ) ]
179230 let mut cached_platform = CACHED_PLATFORM . lock ( ) ;
0 commit comments