@@ -2,6 +2,7 @@ use core::convert::Infallible;
2
2
use core:: { mem, ptr, slice, str} ;
3
3
4
4
use align_address:: Align ;
5
+ use hermit_sync:: OnceCell ;
5
6
use x86:: io:: * ;
6
7
use x86_64:: structures:: paging:: PhysFrame ;
7
8
@@ -41,11 +42,11 @@ const AML_BYTEPREFIX: u8 = 0x0A;
41
42
const SLP_EN : u16 = 1 << 13 ;
42
43
43
44
/// 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 ( ) ;
45
46
/// 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 ( ) ;
47
48
/// 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 ( ) ;
49
50
50
51
/// The "Root System Description Pointer" structure providing pointers to all other ACPI tables.
51
52
#[ repr( C , packed) ]
@@ -68,6 +69,7 @@ impl AcpiRsdp {
68
69
}
69
70
70
71
/// The header of (almost) every ACPI table.
72
+ #[ derive( Clone , Copy , Debug ) ]
71
73
#[ repr( C , packed) ]
72
74
struct AcpiSdtHeader {
73
75
signature : [ u8 ; 4 ] ,
@@ -89,6 +91,7 @@ impl AcpiSdtHeader {
89
91
90
92
/// A convenience structure to work with an ACPI table.
91
93
/// Maps a single table to memory and frees the memory when a variable of this structure goes out of scope.
94
+ #[ derive( Debug ) ]
92
95
pub struct AcpiTable < ' a > {
93
96
header : & ' a AcpiSdtHeader ,
94
97
allocated_virtual_address : VirtAddr ,
@@ -376,9 +379,7 @@ fn search_s5_in_table(table: AcpiTable<'_>) {
376
379
// Note that Power Off may also be controlled through PM1B_CNT_BLK / SLP_TYPB
377
380
// according to the ACPI Specification. However, this has not yet been observed on real computers
378
381
// and therefore not implemented.
379
- unsafe {
380
- SLP_TYPA = Some ( slp_typa) ;
381
- }
382
+ SLP_TYPA . set ( slp_typa) . unwrap ( ) ;
382
383
}
383
384
}
384
385
}
@@ -402,9 +403,7 @@ fn parse_fadt(fadt: AcpiTable<'_>) {
402
403
} else {
403
404
fadt_table. pm1a_cnt_blk as u16
404
405
} ;
405
- unsafe {
406
- PM1A_CNT_BLK = Some ( pm1a_cnt_blk) ;
407
- }
406
+ PM1A_CNT_BLK . set ( pm1a_cnt_blk) . unwrap ( ) ;
408
407
409
408
// Map the "Differentiated System Description Table" (DSDT).
410
409
let x_dsdt_field_address = ptr:: addr_of!( fadt_table. x_dsdt) as usize ;
@@ -435,7 +434,7 @@ fn parse_fadt(fadt: AcpiTable<'_>) {
435
434
fn parse_ssdt ( ssdt : AcpiTable < ' _ > ) {
436
435
// We don't need to parse the SSDT if we already have information about the "_S5_" object
437
436
// (e.g. from the DSDT or a previous SSDT).
438
- if unsafe { SLP_TYPA } . is_some ( ) {
437
+ if SLP_TYPA . get ( ) . is_some ( ) {
439
438
return ;
440
439
}
441
440
@@ -444,25 +443,25 @@ fn parse_ssdt(ssdt: AcpiTable<'_>) {
444
443
}
445
444
446
445
pub fn get_madt ( ) -> Option < & ' static AcpiTable < ' static > > {
447
- unsafe { MADT . as_ref ( ) }
446
+ MADT . get ( )
448
447
}
449
448
450
449
pub 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 {
458
457
outw ( pm1a_cnt_blk, bits) ;
459
- loop {
460
- processor:: halt ( ) ;
461
- }
462
- } else {
463
- warn ! ( "ACPI Power Off is not available" ) ;
464
- Err ( ( ) )
465
458
}
459
+ loop {
460
+ processor:: halt ( ) ;
461
+ }
462
+ } else {
463
+ warn ! ( "ACPI Power Off is not available" ) ;
464
+ Err ( ( ) )
466
465
}
467
466
}
468
467
@@ -505,9 +504,7 @@ pub fn init() {
505
504
verify_checksum( table. header_start_address( ) , table. header. length as usize ) . is_ok( ) ,
506
505
"MADT at {table_physical_address:#X} has invalid checksum"
507
506
) ;
508
- unsafe {
509
- MADT = Some ( table) ;
510
- }
507
+ MADT . set ( table) . unwrap ( ) ;
511
508
} else if table. header . signature ( ) == "FACP" {
512
509
// The "Fixed ACPI Description Table" (FADT) aka "Fixed ACPI Control Pointer" (FACP)
513
510
// Check and parse this table for the poweroff() call.
0 commit comments