@@ -20,8 +20,6 @@ use core::prelude::v1::derive;
2020#[ cfg( not( feature = "uefi" ) ) ]
2121use guid_macros:: guid;
2222#[ cfg( feature = "uefi" ) ]
23- use std:: slice;
24- #[ cfg( feature = "uefi" ) ]
2523use uefi:: { guid, Guid } ;
2624
2725#[ cfg( feature = "linux" ) ]
@@ -31,6 +29,15 @@ use std::io;
3129#[ cfg( feature = "linux" ) ]
3230use std:: path:: Path ;
3331
32+ #[ cfg( target_os = "freebsd" ) ]
33+ use nix:: ioctl_readwrite;
34+ #[ cfg( target_os = "freebsd" ) ]
35+ use std:: fs:: OpenOptions ;
36+ #[ cfg( target_os = "freebsd" ) ]
37+ use std:: os:: fd:: AsRawFd ;
38+ #[ cfg( target_os = "freebsd" ) ]
39+ use std:: os:: unix:: fs:: OpenOptionsExt ;
40+
3441/// Decode from GUID string version
3542///
3643/// # Examples
@@ -316,7 +323,7 @@ fn esrt_from_sysfs(dir: &Path) -> io::Result<Esrt> {
316323 Ok ( esrt_table)
317324}
318325
319- #[ cfg( all( not( feature = "uefi" ) , feature = "linux" ) ) ]
326+ #[ cfg( all( not( feature = "uefi" ) , feature = "linux" , target_os = "linux" ) ) ]
320327pub fn get_esrt ( ) -> Option < Esrt > {
321328 let res = esrt_from_sysfs ( Path :: new ( "/sys/firmware/efi/esrt/entries" ) ) . ok ( ) ;
322329 if res. is_none ( ) {
@@ -332,11 +339,43 @@ pub fn get_esrt() -> Option<Esrt> {
332339 None
333340}
334341
342+ #[ cfg( target_os = "freebsd" ) ]
343+ #[ repr( C ) ]
344+ struct EfiGetTableIoc {
345+ buf : * mut u8 ,
346+ uuid : [ u8 ; 16 ] ,
347+ table_len : usize ,
348+ buf_len : usize ,
349+ }
350+ #[ cfg( target_os = "freebsd" ) ]
351+ ioctl_readwrite ! ( efi_get_table, b'E' , 1 , EfiGetTableIoc ) ;
352+
335353#[ cfg( all( not( feature = "uefi" ) , target_os = "freebsd" ) ) ]
336354pub fn get_esrt ( ) -> Option < Esrt > {
337- // TODO: Implement
338- println ! ( "Reading ESRT is not implemented on FreeBSD yet." ) ;
339- None
355+ let file = OpenOptions :: new ( )
356+ . read ( true )
357+ . write ( true )
358+ . custom_flags ( libc:: O_NONBLOCK )
359+ . open ( "/dev/efi" )
360+ . unwrap ( ) ;
361+
362+ let mut buf: Vec < u8 > = Vec :: new ( ) ;
363+ let mut table = EfiGetTableIoc {
364+ buf : std:: ptr:: null_mut ( ) ,
365+ uuid : SYSTEM_RESOURCE_TABLE_GUID . to_bytes ( ) ,
366+ buf_len : 0 ,
367+ table_len : 0 ,
368+ } ;
369+ unsafe {
370+ let fd = file. as_raw_fd ( ) ;
371+ let _res = efi_get_table ( fd, & mut table) . unwrap ( ) ;
372+ buf. resize ( table. table_len , 0 ) ;
373+ table. buf_len = table. table_len ;
374+ table. buf = buf. as_mut_ptr ( ) ;
375+
376+ let _res = efi_get_table ( fd, & mut table) . unwrap ( ) ;
377+ esrt_from_buf ( table. buf )
378+ }
340379}
341380
342381/// gEfiSystemResourceTableGuid from MdePkg/MdePkg.dec
@@ -353,26 +392,32 @@ pub fn get_esrt() -> Option<Esrt> {
353392 let table_guid: Guid = unsafe { std:: mem:: transmute ( table. guid ) } ;
354393 match table_guid {
355394 SYSTEM_RESOURCE_TABLE_GUID => unsafe {
356- let raw_esrt = & * ( table. address as * const _Esrt ) ;
357- let mut esrt = Esrt {
358- resource_count : raw_esrt. resource_count ,
359- resource_count_max : raw_esrt. resource_count_max ,
360- resource_version : raw_esrt. resource_version ,
361- entries : vec ! [ ] ,
362- } ;
363-
364- // Make sure it's the version we expect
365- debug_assert ! ( esrt. resource_version == ESRT_FIRMWARE_RESOURCE_VERSION ) ;
366-
367- let src_ptr = std:: ptr:: addr_of!( raw_esrt. entries) as * const EsrtResourceEntry ;
368- let slice_entries = slice:: from_raw_parts ( src_ptr, esrt. resource_count as usize ) ;
369-
370- esrt. entries = slice_entries. to_vec ( ) ;
371-
372- return Some ( esrt) ;
395+ return esrt_from_buf ( table. address as * const u8 ) ;
373396 } ,
374397 _ => { }
375398 }
376399 }
377400 None
378401}
402+
403+ /// Parse the ESRT table buffer
404+ #[ cfg( any( feature = "uefi" , target_os = "freebsd" ) ) ]
405+ unsafe fn esrt_from_buf ( ptr : * const u8 ) -> Option < Esrt > {
406+ let raw_esrt = & * ( ptr as * const _Esrt ) ;
407+ let mut esrt = Esrt {
408+ resource_count : raw_esrt. resource_count ,
409+ resource_count_max : raw_esrt. resource_count_max ,
410+ resource_version : raw_esrt. resource_version ,
411+ entries : vec ! [ ] ,
412+ } ;
413+
414+ // Make sure it's the version we expect
415+ debug_assert ! ( esrt. resource_version == ESRT_FIRMWARE_RESOURCE_VERSION ) ;
416+
417+ let src_ptr = core:: ptr:: addr_of!( raw_esrt. entries) as * const EsrtResourceEntry ;
418+ let slice_entries = core:: slice:: from_raw_parts ( src_ptr, esrt. resource_count as usize ) ;
419+
420+ esrt. entries = slice_entries. to_vec ( ) ;
421+
422+ Some ( esrt)
423+ }
0 commit comments