summaryrefslogtreecommitdiff
path: root/src/kernel/arch/amd64/acpi.c
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);
			}
		}
	}
}