@@ -40,20 +40,31 @@ struct rsdt {
4040} __attribute__((packed ));
4141
4242struct fadt {
43- char signature [4 ];
44- uint32_t length ;
45- uint8_t revision ;
46- uint8_t checksum ;
47- char oem_id [6 ];
48- char oem_table_id [8 ];
49- uint32_t oem_revision ;
50- uint32_t creator_id ;
51- uint32_t creator_revision ;
52-
53- // ...
54- uint16_t reset_register_io_port ; // 0x64 in ACPI spec, but can vary
55- uint8_t reset_value ; // value to write to reset
56- // ...
43+ struct sdt header ;
44+
45+ uint32_t firmware_ctrl ;
46+ uint32_t dsdt ;
47+
48+ uint8_t reserved1 ;
49+ uint8_t preferred_pm_profile ;
50+ uint16_t sci_int ;
51+ uint32_t smi_cmd ;
52+ uint8_t acpi_enable ;
53+ uint8_t acpi_disable ;
54+ uint8_t s4bios_req ;
55+ uint8_t pstate_cnt ;
56+
57+ uint32_t pm1a_evt_blk ;
58+ uint32_t pm1b_evt_blk ;
59+ uint32_t pm1a_cnt_blk ;
60+ uint32_t pm1b_cnt_blk ;
61+
62+ /* skip tons of fields */
63+
64+ uint8_t reserved2 [76 ];
65+
66+ struct acpi_gas reset_reg ; // ✅ correct
67+ uint8_t reset_value ;
5768} __attribute__((packed ));
5869
5970
@@ -98,68 +109,56 @@ void acpi_init()
98109 }
99110}
100111
101- void * acpi_find_sdt (const char * signature , size_t index )
102- {
103- size_t cnt = 0 ;
112+ void * acpi_find_sdt (const char * signature , size_t index ) {
113+ size_t entries = ( rsdt -> sdt . length - sizeof ( struct sdt )) /
114+ ( use_xsdt ? 8 : 4 ) ;
104115
105- for (size_t i = 0 ; i < rsdt -> sdt .length - sizeof (struct sdt ); i ++ ) {
106- struct sdt * ptr ;
107- if (use_xsdt )
108- ptr = (struct sdt * )(uintptr_t )((int64 * )rsdt -> ptrs_start )[i ];
109- else
110- ptr = (struct sdt * )(uintptr_t )((int32 * )rsdt -> ptrs_start )[i ];
116+ size_t found = 0 ;
111117
112- if (!strncmp (ptr -> signature , signature , 4 ) && cnt ++ == index )
113- return (void * )ptr ;
114- }
118+ for (size_t i = 0 ; i < entries ; i ++ ) {
119+ struct sdt * ptr =
120+ use_xsdt ?
121+ (struct sdt * )(uintptr_t )((uint64_t * )rsdt -> ptrs_start )[i ] :
122+ (struct sdt * )(uintptr_t )((uint32_t * )rsdt -> ptrs_start )[i ];
115123
124+ if (!strncmp (ptr -> signature , signature , 4 )) {
125+ if (found ++ == index )
126+ return ptr ;
127+ }
128+ }
116129 return NULL ;
117130}
118131
119- void acpi_reboot () {
132+ void acpi_reboot (uintptr_t hhdm_offset ) {
120133 clear_interrupts ();
121134
122- struct fadt * fadt_ptr = (struct fadt * )acpi_find_sdt ("FACP" , 0 );
123- if (!fadt_ptr ) {
124- meltdown_screen ("FADT not found! Falling back to hard reset." , __FILE__ , __LINE__ , 0xdeadbeef );
125- sleep (5 );
126- hard_reset ();
127- }
135+ struct fadt * fadt = (struct fadt * )((uintptr_t )acpi_find_sdt ("FACP" , 0 ) + hhdm_offset );
136+ if (!fadt ) goto fallback ;
128137
129- // ACPI reset uses the reset register GAS
130- struct acpi_gas * reg = (struct acpi_gas * )((uintptr_t )fadt_ptr + 0x64 ); // offset for reset reg in FADT
131- if (!reg -> address ) {
132- meltdown_screen ("ACPI Reset register not present! Hard reset in 5 sec." , __FILE__ , __LINE__ , 0xdeadbeef );
133- sleep (5 );
134- hard_reset ();
135- }
138+ struct acpi_gas * reg = & fadt -> reset_reg ;
136139
137- // Only IO space is widely supported
138- if (reg -> address_space == 1 ) { // IO port
139- outb ((uint16_t )reg -> address , fadt_ptr -> reset_value );
140- } else {
141- meltdown_screen ("ACPI Reset register not IO space! Hard reset." , __FILE__ , __LINE__ , 0xdeadbeef );
142- hard_reset ();
143- }
144-
145- // If that fails
146- meltdown_screen ("ACPI Reset failed! Falling back to hard reset." , __FILE__ , __LINE__ , 0xfaded );
147- hard_reset ();
148- }
140+ if (reg -> address && reg -> address_space == 1 ) {
141+ printf ("ACPI reset: space=%d addr=0x%x value=0x%x" , reg -> address_space , reg -> address , fadt -> reset_value );
142+ if (reg -> address > 0xFFFF )
143+ printf ("Invalid I/O port! Will not work." );
149144
150-
151- void hard_reset (void ) {
152- // Wait until input buffer is clear (bit 1 of 0x64)
153- for (int i = 0 ; i < 100000 ; i ++ ) {
154- if (!(inb (0x64 ) & 0x02 )) break ;
145+ outb ((uint16_t )reg -> address , fadt -> reset_value );
155146 }
156147
157- // Request CPU reset via keyboard controller
148+ fallback :
149+ outb (0xCF9 , 0x02 );
150+ outb (0xCF9 , 0x06 );
151+
152+ // Keyboard controller reset
153+ for (int i = 0 ; i < 100000 ; i ++ )
154+ if (!(inb (0x64 ) & 0x02 )) break ;
158155 outb (0x64 , 0xFE );
159156
160- // If we reach here, reset failed
161- meltdown_screen ("Hard reset failed! (unsupported hardware?)" , __FILE__ , __LINE__ , 0xBADBED );
157+ // Triple fault fallback (works everywhere)
158+ asm volatile (
159+ "lidt (0)\n"
160+ "int $3\n"
161+ );
162162
163- // Halt forever
164163 hcf2 ();
165- }
164+ }
0 commit comments