22
33use std:: prelude:: v1:: * ;
44
5- #[ cfg( not( feature = "uefi" ) ) ]
5+ #[ cfg( all ( not( feature = "uefi" ) , not ( target_os = "freebsd" ) ) ) ]
66use std:: io:: ErrorKind ;
77
88use crate :: util:: { Config , Platform } ;
@@ -13,6 +13,9 @@ use spin::Mutex;
1313#[ cfg( not( feature = "uefi" ) ) ]
1414use std:: sync:: Mutex ;
1515
16+ #[ cfg( target_os = "freebsd" ) ]
17+ use std:: io:: { Read , Seek , SeekFrom } ;
18+
1619/// Current platform. Won't ever change during the program's runtime
1720static CACHED_PLATFORM : Mutex < Option < Option < Platform > > > = Mutex :: new ( None ) ;
1821
@@ -82,6 +85,103 @@ pub fn dmidecode_string_val(s: &SMBiosString) -> Option<String> {
8285 }
8386}
8487
88+ #[ cfg( target_os = "freebsd" ) ]
89+ #[ repr( C ) ]
90+ pub struct Smbios3 {
91+ pub anchor : [ u8 ; 5 ] ,
92+ pub checksum : u8 ,
93+ pub length : u8 ,
94+ pub major_version : u8 ,
95+ pub minor_version : u8 ,
96+ pub docrev : u8 ,
97+ pub revision : u8 ,
98+ _reserved : u8 ,
99+ pub table_length : u32 ,
100+ pub table_address : u64 ,
101+ }
102+
103+ #[ cfg( target_os = "freebsd" ) ]
104+ #[ repr( packed) ]
105+ pub struct Smbios {
106+ pub anchor : [ u8 ; 4 ] ,
107+ pub checksum : u8 ,
108+ pub length : u8 ,
109+ pub major_version : u8 ,
110+ pub minor_version : u8 ,
111+ pub max_structure_size : u16 ,
112+ pub revision : u8 ,
113+ pub formatted : [ u8 ; 5 ] ,
114+ pub inter_anchor : [ u8 ; 5 ] ,
115+ pub inter_checksum : u8 ,
116+ pub table_length : u16 ,
117+ pub table_address : u32 ,
118+ pub structure_count : u16 ,
119+ pub bcd_revision : u8 ,
120+ }
121+
122+ #[ cfg( target_os = "freebsd" ) ]
123+ pub fn get_smbios ( ) -> Option < SMBiosData > {
124+ // Get the SMBIOS entrypoint address from the kernel environment
125+ let addr_hex = kenv_get ( "hint.smbios.0.mem" ) . ok ( ) ?;
126+ let addr_hex = addr_hex. trim_start_matches ( "0x" ) ;
127+ let addr = u64:: from_str_radix ( & addr_hex, 16 ) . unwrap ( ) ;
128+ trace ! ( "SMBIOS Entrypoint Addr: {} 0x{:x}" , addr_hex, addr) ;
129+
130+ let mut dev_mem = std:: fs:: File :: open ( "/dev/mem" ) . ok ( ) ?;
131+ // Smbios struct is larger than Smbios3 struct
132+ let mut header_buf = [ 0 ; std:: mem:: size_of :: < Smbios > ( ) ] ;
133+ dev_mem. seek ( SeekFrom :: Start ( addr) ) . ok ( ) ?;
134+ dev_mem. read_exact ( & mut header_buf) . ok ( ) ?;
135+
136+ let entrypoint = unsafe { & * ( header_buf. as_ptr ( ) as * const Smbios3 ) } ;
137+
138+ trace ! ( "SMBIOS Anchor {:?} = " , entrypoint. anchor) ;
139+ let ( addr, len, version) = match entrypoint. anchor {
140+ [ b'_' , b'S' , b'M' , b'3' , b'_' ] => {
141+ trace ! ( "_SM3_" ) ;
142+ let entrypoint = unsafe { & * ( header_buf. as_ptr ( ) as * const Smbios3 ) } ;
143+ let ver = Some ( SMBiosVersion {
144+ major : entrypoint. major_version ,
145+ minor : entrypoint. minor_version ,
146+ revision : 0 ,
147+ } ) ;
148+
149+ ( entrypoint. table_address , entrypoint. table_length , ver)
150+ }
151+ [ b'_' , b'S' , b'M' , b'_' , _] => {
152+ trace ! ( "_SM_" ) ;
153+ let entrypoint = unsafe { & * ( header_buf. as_ptr ( ) as * const Smbios ) } ;
154+ let ver = Some ( SMBiosVersion {
155+ major : entrypoint. major_version ,
156+ minor : entrypoint. minor_version ,
157+ revision : 0 ,
158+ } ) ;
159+
160+ (
161+ entrypoint. table_address as u64 ,
162+ entrypoint. table_length as u32 ,
163+ ver,
164+ )
165+ }
166+ [ b'_' , b'D' , b'M' , b'I' , b'_' ] => {
167+ error ! ( "_DMI_ - UNSUPPORTED" ) ;
168+ return None ;
169+ }
170+ _ => {
171+ error ! ( " Unknown - UNSUPPORTED" ) ;
172+ return None ;
173+ }
174+ } ;
175+
176+ // Get actual SMBIOS table data
177+ let mut smbios_buf = vec ! [ 0 ; len as usize ] ;
178+ dev_mem. seek ( SeekFrom :: Start ( addr) ) . ok ( ) ?;
179+ dev_mem. read_exact ( & mut smbios_buf) . ok ( ) ?;
180+
181+ let smbios = SMBiosData :: from_vec_and_version ( smbios_buf, version) ;
182+ Some ( smbios)
183+ }
184+
85185#[ cfg( feature = "uefi" ) ]
86186pub fn get_smbios ( ) -> Option < SMBiosData > {
87187 let data = crate :: uefi:: smbios_data ( ) . unwrap ( ) ;
@@ -90,9 +190,8 @@ pub fn get_smbios() -> Option<SMBiosData> {
90190 Some ( smbios)
91191}
92192// On Linux this reads either from /dev/mem or sysfs
93- // On FreeBSD from /dev/mem
94193// On Windows from the kernel API
95- #[ cfg( not( feature = "uefi" ) ) ]
194+ #[ cfg( all ( not( feature = "uefi" ) , not ( target_os = "freebsd" ) ) ) ]
96195pub fn get_smbios ( ) -> Option < SMBiosData > {
97196 match smbioslib:: table_load_from_device ( ) {
98197 Ok ( data) => Some ( data) ,
@@ -104,6 +203,8 @@ pub fn get_smbios() -> Option<SMBiosData> {
104203 println ! ( "Failed to get SMBIOS: {:?}" , err) ;
105204 None
106205 }
206+ }
207+ }
107208
108209fn get_product_name ( ) -> Option < String > {
109210 // On FreeBSD we can short-circuit and avoid parsing SMBIOS
0 commit comments