blob: cc7791fbbab05a5cc0d9353e14aa31f4d05e30e4 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
#include <kernel/arch/amd64/acpi.h>
#include <kernel/panic.h>
#include <shared/mem.h>
#include <stdint.h>
typedef struct {
char sig[8];
uint8_t checksum;
char oemid[6];
uint8_t rev;
uint32_t rsdt;
} __attribute__((packed)) RDSP;
typedef struct {
char sig[4];
uint32_t len;
uint8_t rev;
uint8_t checksum;
char oemID[6];
char oemTID[8];
uint32_t oemRev;
uint32_t creatorId;
uint32_t creatorRev;
char data[0];
} __attribute__((packed)) SDT;
/* https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf */
typedef struct {
uint8_t where;
uint8_t bitwidth;
uint8_t bitoffset;
uint8_t _reserved;
uint64_t addr;
} __attribute__((packed)) GAS; /* Generic Address Structure */
typedef struct {
SDT hdr;
uint32_t _someid;
GAS addr;
/* ... */
} __attribute__((packed)) HPET;
void
acpi_parse(const void *rdsp_v)
{
const RDSP *rdsp = rdsp_v;
if (memcmp(rdsp->sig, "RSD PTR ", 8) != 0) {
panic_invalid_state();
}
SDT *rsdt = (void*)(uintptr_t)rdsp->rsdt;
if (memcmp(rsdt->sig, "RSDT ", 4) != 0) {
panic_invalid_state();
}
uint32_t *sub = (void*)rsdt->data;
int len = (rsdt->len - sizeof(SDT)) / 4;
for (int i = 0; i < len; i++) {
SDT *it = (void*)(uintptr_t)sub[i];
if (memcmp(it->sig, "HPET", 4) == 0) {
HPET *hpet = (void*)it;
GAS *gas = &hpet->addr;
if (gas->where == 0) { /* in memory */
hpet_init((void*)gas->addr);
}
}
}
}
|