Skip to content

Commit a86157e

Browse files
Improved ACPI Reboot.
1 parent de11901 commit a86157e

2 files changed

Lines changed: 48 additions & 15 deletions

File tree

source/includes/acpi.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @file acpi.h
3-
* @author Mintsuki (https://github.com/mintsuki)
3+
* @author Pradosh & Mintsuki (https://github.com/mintsuki)
44
* @brief The ACPI Header
55
* @version 0.1
66
* @date 2023-10-29
@@ -30,6 +30,15 @@ struct sdt {
3030
uint32_t creator_rev;
3131
} __attribute__((packed));
3232

33+
struct acpi_gas {
34+
uint8_t address_space;
35+
uint8_t bit_width;
36+
uint8_t bit_offset;
37+
uint8_t access_size;
38+
uint64_t address;
39+
};
40+
41+
3342
/**
3443
* @brief Initializes and iterates through all ACPI tables
3544
*

source/kernel/C/acpi.c

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @file acpi.c
3-
* @author Mintsuki (https://github.com/mintsuki)
3+
* @author Pradosh & Mintsuki (https://github.com/mintsuki)
44
* @brief The full ACPI Source
55
* @version 0.1
66
* @date 2023-10-29
@@ -39,11 +39,23 @@ struct rsdt {
3939
symbol ptrs_start;
4040
} __attribute__((packed));
4141

42-
struct fadt{
42+
struct fadt {
4343
char signature[4];
4444
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+
4759

4860
static bool use_xsdt;
4961
static struct rsdt *rsdt;
@@ -103,28 +115,40 @@ void *acpi_find_sdt(const char *signature, size_t index)
103115
return NULL;
104116
}
105117

106-
void acpi_reboot(){
118+
void acpi_reboot() {
107119
clear_interrupts();
108120

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+
}
111127

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);
115132
sleep(5);
116133
hard_reset();
117134
}
118135

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+
}
122144

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);
124147
sleep(5);
125148
hard_reset();
126149
}
127150

151+
128152
void hard_reset()
129153
{
130154
uint8_t foo = 0x02;

0 commit comments

Comments
 (0)