Skip to content

Commit b813fa1

Browse files
Fixed ACPI reboot not working, (use shutdown -r now) Implemented the cat command. (i dont think it works)
1 parent a2e5f05 commit b813fa1

7 files changed

Lines changed: 76 additions & 68 deletions

File tree

disk.img

0 Bytes
Binary file not shown.

source/includes/acpi-shutdown.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@
88
* @copyright Copyright (C) 2019-2023 mintsuki and contributors.
99
*
1010
*/
11-
#ifndef _ACPI_SHUTDOWN_HACK_H
12-
#define _ACPI_SHUTDOWN_HACK_H
11+
#ifndef ACPI_SHUTDOWN_H
12+
#define ACPI_SHUTDOWN_H
1313

14-
#include <stddef.h>
15-
#include <stdint.h>
1614
#include <basics.h>
1715

1816
int acpi_shutdown_hack(uintptr_t direct_map_base, void *(*find_sdt)(cstring signature, size_t index));

source/includes/acpi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,11 @@ void acpi_init();
5454
*/
5555
void *acpi_find_sdt(const char *signature, size_t index);
5656

57+
/**
58+
* @brief Reboots using ACPI, if ACPI is unresponsive it tires hard reset and then triple fault.
59+
*
60+
* @param hhdm_offset The HHDM Offset offered by Limine bootloader.
61+
*/
62+
void acpi_reboot(uintptr_t hhdm_offset);
63+
5764
#endif

source/kernel/C/acpi.c

Lines changed: 61 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,31 @@ struct rsdt {
4040
} __attribute__((packed));
4141

4242
struct 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+
}

source/kernel/C/kernel.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,4 +267,8 @@ void putc(char c){
267267
*/
268268
void shutdown(){
269269
acpi_shutdown_hack(hhdm_request.response->offset, acpi_find_sdt);
270+
}
271+
272+
void reboot(){
273+
acpi_reboot(hhdm_request.response->offset);
270274
}

source/kernel/C/shell/commands/cat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ int cmd_cat(int argc, char** argv)
2929

3030
/* Open file */
3131
if (vfs_open(argv[i], &file) != 0) {
32-
printf("cat: %s: No such file or directory\n", argv[i]);
32+
printf("cat: %s: No such file or directory", argv[i]);
3333
continue;
3434
}
3535

source/kernel/C/shell/commands/shutdown.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ int cmd_shutdown(int argc, char** argv)
3535
}
3636

3737
if (do_reboot)
38-
acpi_reboot();
38+
reboot();
3939
else if (do_halt)
4040
shutdown();
4141
else

0 commit comments

Comments
 (0)