@@ -2,6 +2,7 @@ use core::convert::Infallible;
22use core:: { mem, ptr, slice, str} ;
33
44use align_address:: Align ;
5+ use hermit_sync:: OnceCell ;
56use x86:: io:: * ;
67use x86_64:: structures:: paging:: PhysFrame ;
78
@@ -41,11 +42,11 @@ const AML_BYTEPREFIX: u8 = 0x0A;
4142const SLP_EN : u16 = 1 << 13 ;
4243
4344/// The "Multiple APIC Description Table" (MADT) preserved for get_apic_table().
44- static mut MADT : Option < AcpiTable < ' _ > > = None ;
45+ static MADT : OnceCell < AcpiTable < ' _ > > = OnceCell :: new ( ) ;
4546/// The PM1A Control I/O Port for powering off the computer through ACPI.
46- static mut PM1A_CNT_BLK : Option < u16 > = None ;
47+ static PM1A_CNT_BLK : OnceCell < u16 > = OnceCell :: new ( ) ;
4748/// The Sleeping State Type code for powering off the computer through ACPI.
48- static mut SLP_TYPA : Option < u8 > = None ;
49+ static SLP_TYPA : OnceCell < u8 > = OnceCell :: new ( ) ;
4950
5051/// The "Root System Description Pointer" structure providing pointers to all other ACPI tables.
5152#[ repr( C , packed) ]
@@ -68,6 +69,7 @@ impl AcpiRsdp {
6869}
6970
7071/// The header of (almost) every ACPI table.
72+ #[ derive( Clone , Copy , Debug ) ]
7173#[ repr( C , packed) ]
7274struct AcpiSdtHeader {
7375 signature : [ u8 ; 4 ] ,
@@ -89,6 +91,7 @@ impl AcpiSdtHeader {
8991
9092/// A convenience structure to work with an ACPI table.
9193/// Maps a single table to memory and frees the memory when a variable of this structure goes out of scope.
94+ #[ derive( Debug ) ]
9295pub struct AcpiTable < ' a > {
9396 header : & ' a AcpiSdtHeader ,
9497 allocated_virtual_address : VirtAddr ,
@@ -376,9 +379,7 @@ fn search_s5_in_table(table: AcpiTable<'_>) {
376379 // Note that Power Off may also be controlled through PM1B_CNT_BLK / SLP_TYPB
377380 // according to the ACPI Specification. However, this has not yet been observed on real computers
378381 // and therefore not implemented.
379- unsafe {
380- SLP_TYPA = Some ( slp_typa) ;
381- }
382+ SLP_TYPA . set ( slp_typa) . unwrap ( ) ;
382383 }
383384 }
384385 }
@@ -402,9 +403,7 @@ fn parse_fadt(fadt: AcpiTable<'_>) {
402403 } else {
403404 fadt_table. pm1a_cnt_blk as u16
404405 } ;
405- unsafe {
406- PM1A_CNT_BLK = Some ( pm1a_cnt_blk) ;
407- }
406+ PM1A_CNT_BLK . set ( pm1a_cnt_blk) . unwrap ( ) ;
408407
409408 // Map the "Differentiated System Description Table" (DSDT).
410409 let x_dsdt_field_address = ptr:: addr_of!( fadt_table. x_dsdt) as usize ;
@@ -435,7 +434,7 @@ fn parse_fadt(fadt: AcpiTable<'_>) {
435434fn parse_ssdt ( ssdt : AcpiTable < ' _ > ) {
436435 // We don't need to parse the SSDT if we already have information about the "_S5_" object
437436 // (e.g. from the DSDT or a previous SSDT).
438- if unsafe { SLP_TYPA } . is_some ( ) {
437+ if SLP_TYPA . get ( ) . is_some ( ) {
439438 return ;
440439 }
441440
@@ -444,25 +443,25 @@ fn parse_ssdt(ssdt: AcpiTable<'_>) {
444443}
445444
446445pub fn get_madt ( ) -> Option < & ' static AcpiTable < ' static > > {
447- unsafe { MADT . as_ref ( ) }
446+ MADT . get ( )
448447}
449448
450449pub fn poweroff ( ) -> Result < Infallible , ( ) > {
451- unsafe {
452- if let ( Some ( pm1a_cnt_blk ) , Some ( slp_typa) ) = ( PM1A_CNT_BLK , SLP_TYPA ) {
453- let bits = ( u16 :: from ( slp_typa ) << 10 ) | SLP_EN ;
454- debug ! (
455- "Powering Off through ACPI (port {:#X}, bitmask {:#X})" ,
456- pm1a_cnt_blk , bits
457- ) ;
450+ if let ( Some ( & pm1a_cnt_blk ) , Some ( & slp_typa ) ) = ( PM1A_CNT_BLK . get ( ) , SLP_TYPA . get ( ) ) {
451+ let bits = ( u16 :: from ( slp_typa) << 10 ) | SLP_EN ;
452+ debug ! (
453+ "Powering Off through ACPI (port {:#X}, bitmask {:#X})" ,
454+ pm1a_cnt_blk , bits
455+ ) ;
456+ unsafe {
458457 outw ( pm1a_cnt_blk, bits) ;
459- loop {
460- processor:: halt ( ) ;
461- }
462- } else {
463- warn ! ( "ACPI Power Off is not available" ) ;
464- Err ( ( ) )
465458 }
459+ loop {
460+ processor:: halt ( ) ;
461+ }
462+ } else {
463+ warn ! ( "ACPI Power Off is not available" ) ;
464+ Err ( ( ) )
466465 }
467466}
468467
@@ -505,9 +504,7 @@ pub fn init() {
505504 verify_checksum( table. header_start_address( ) , table. header. length as usize ) . is_ok( ) ,
506505 "MADT at {table_physical_address:#X} has invalid checksum"
507506 ) ;
508- unsafe {
509- MADT = Some ( table) ;
510- }
507+ MADT . set ( table) . unwrap ( ) ;
511508 } else if table. header . signature ( ) == "FACP" {
512509 // The "Fixed ACPI Description Table" (FADT) aka "Fixed ACPI Control Pointer" (FACP)
513510 // Check and parse this table for the poweroff() call.
0 commit comments