summaryrefslogtreecommitdiff
path: root/src/acpi.c
blob: b4bb05e6e97078864a09bad38d2e19493bd835f7 (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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <acpi.h>
#include <vga.h>
#include <mem.h>
#include <stdbool.h>

static bool checksum_rsdp(const struct rsdp *rsdp) {
	size_t chksm = 0;
	for (uint8_t *byte = (uint8_t*) rsdp; byte < (uint8_t*)rsdp + sizeof(*rsdp); byte++)
		chksm += *byte;
	return (chksm & 0xFF) == 0;
}

static bool checksum_xsdp(const struct xsdp *rsdp) {
	return true;
	size_t chksm = 0;
	for (uint8_t *byte = (uint8_t*) rsdp; byte < (uint8_t*)rsdp + sizeof(*rsdp); byte++)
		chksm += *byte;
	return (chksm & 0xFF) == 0;
}

static bool checksum_sdt(const struct acpi_sdt_header *header) {
	uint8_t chksm = 0;
	for (size_t i = 0; i < header->len; i++) {
		chksm += ((int8_t *) header)[i];
	}
	return chksm == 0;
}

void print_rsdp(const struct rsdp *rsdp) {
	vga_puts("sig: ");
	vga_putsn(rsdp->signature, 8);
	vga_putc('\n');

	vga_puts("checksum: ");
	vga_putn(rsdp->checksum);
	vga_putc(' ');
	vga_puts(checksum_rsdp(rsdp) ? "PASS" : "FAIL");
	vga_putc('\n');

	vga_puts("oem id: ");
	vga_putsn(rsdp->oemid, 6);
	vga_putc('\n');

	vga_puts("revision: ");
	vga_putn(rsdp->revision);
	vga_putc('\n');

	vga_puts("addr: ");
	vga_putx(rsdp->rsdt_address);
	vga_putc('\n');
}

struct fadt *find_facp(struct xsdt *root_sdt) {
	if (root_sdt == NULL)
		return NULL;
	size_t entries = (root_sdt->header.len - sizeof(root_sdt->header)) / 4;
	for (size_t i = 0; i < entries; i++) {
		struct acpi_sdt_header *header = (struct acpi_sdt_header *) root_sdt->sdt_pointers[i];
		if (memcmp(header->signature, "FACP", 4) == 0 && checksum_sdt(header)) {
			return (struct fadt *) header;
		}
	}
	return NULL;
}

struct xsdp *find_rsdp() {
	struct xsdp *rsdp = NULL;

	char *ebda = (char*)((uintptr_t) *(uint16_t *)0x40e << 4);
	for (char *ptr = ebda; ptr < ebda + 128; ptr += 16) {
		if (memcmp(ptr, "RSD PTR ", 8) == 0 && checksum_xsdp((struct xsdp*) ptr)) {
			rsdp = (struct xsdp *) ptr;
		}
	}

	for (char *ptr = (char*)0x000E0000; ptr < (char*)0x000FFFFF; ptr += 16) {
		if (memcmp(ptr, "RSD PTR ", 8) == 0 && checksum_xsdp((struct xsdp*) ptr)) {
			if (rsdp == NULL)
				rsdp = (struct xsdp *) ptr;
		}
	}
	//print_rsdp(rsdp);
	return rsdp;
}