|
1 | 1 | /** |
2 | 2 | * @file acpi.c |
3 | | - * @author Mintsuki (https://github.com/mintsuki) |
| 3 | + * @author Pradosh & Mintsuki (https://github.com/mintsuki) |
4 | 4 | * @brief The full ACPI Source |
5 | 5 | * @version 0.1 |
6 | 6 | * @date 2023-10-29 |
@@ -39,11 +39,23 @@ struct rsdt { |
39 | 39 | symbol ptrs_start; |
40 | 40 | } __attribute__((packed)); |
41 | 41 |
|
42 | | -struct fadt{ |
| 42 | +struct fadt { |
43 | 43 | char signature[4]; |
44 | 44 | uint32_t length; |
45 | | - // other fields are not necessary now |
46 | | -}; |
| 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 | + // ... |
| 57 | +} __attribute__((packed)); |
| 58 | + |
47 | 59 |
|
48 | 60 | static bool use_xsdt; |
49 | 61 | static struct rsdt *rsdt; |
@@ -103,28 +115,40 @@ void *acpi_find_sdt(const char *signature, size_t index) |
103 | 115 | return NULL; |
104 | 116 | } |
105 | 117 |
|
106 | | -void acpi_reboot(){ |
| 118 | +void acpi_reboot() { |
107 | 119 | clear_interrupts(); |
108 | 120 |
|
109 | | - struct fadt* fadt_ptr = null; |
110 | | - fadt_ptr = (struct fadt*)acpi_find_sdt("FACP", 0); |
| 121 | + struct fadt* fadt_ptr = (struct fadt*)acpi_find_sdt("FACP", 0); |
| 122 | + if (!fadt_ptr) { |
| 123 | + meltdown_screen("FADT not found! Falling back to hard reset.", __FILE__, __LINE__, 0xdeadbeef); |
| 124 | + sleep(5); |
| 125 | + hard_reset(); |
| 126 | + } |
111 | 127 |
|
112 | | - // Check if FADT is found |
113 | | - if (fadt_ptr == NULL) { |
114 | | - meltdown_screen("FADT not present but tried to call ACPI reboot. Not possible! Hard reseting in 5 seconds.", __FILE__, __LINE__, 0xdeadbeef); |
| 128 | + // ACPI reset uses the reset register GAS |
| 129 | + struct acpi_gas* reg = (struct acpi_gas*)((uintptr_t)fadt_ptr + 0x64); // offset for reset reg in FADT |
| 130 | + if (!reg->address) { |
| 131 | + meltdown_screen("ACPI Reset register not present! Hard reset in 5 sec.", __FILE__, __LINE__, 0xdeadbeef); |
115 | 132 | sleep(5); |
116 | 133 | hard_reset(); |
117 | 134 | } |
118 | 135 |
|
119 | | - // 3. Write the reset value to the reset register |
120 | | - int16* reset_register = (int16*)((int_pointer)fadt_ptr + 0x30); |
121 | | - *reset_register = 0x6; |
| 136 | + // Only IO space is widely supported |
| 137 | + if (reg->address_space == 1) { // IO port |
| 138 | + outb((uint16_t)reg->address, fadt_ptr->reset_value); |
| 139 | + } else { |
| 140 | + meltdown_screen("ACPI Reset register not IO space! Hard reset in 5 sec.", __FILE__, __LINE__, 0xdeadbeef); |
| 141 | + sleep(5); |
| 142 | + hard_reset(); |
| 143 | + } |
122 | 144 |
|
123 | | - meltdown_screen("ACPI Reboot failed! Hard reset will occur in 5 seconds.", __FILE__, __LINE__, 0xfaded); |
| 145 | + // If that fails |
| 146 | + meltdown_screen("ACPI Reset failed! Falling back to hard reset.", __FILE__, __LINE__, 0xfaded); |
124 | 147 | sleep(5); |
125 | 148 | hard_reset(); |
126 | 149 | } |
127 | 150 |
|
| 151 | + |
128 | 152 | void hard_reset() |
129 | 153 | { |
130 | 154 | uint8_t foo = 0x02; |
|
0 commit comments