1
2
3
4
5
6#include <common.h>
7#include <log.h>
8#include <acpi/acpi_table.h>
9#include <asm/io.h>
10#include <asm/tables.h>
11
12static struct acpi_rsdp *acpi_valid_rsdp(struct acpi_rsdp *rsdp)
13{
14 if (strncmp((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0)
15 return NULL;
16
17 debug("Looking on %p for valid checksum\n", rsdp);
18
19 if (table_compute_checksum((void *)rsdp, 20) != 0)
20 return NULL;
21 debug("acpi rsdp checksum 1 passed\n");
22
23 if ((rsdp->revision > 1) &&
24 (table_compute_checksum((void *)rsdp, rsdp->length) != 0))
25 return NULL;
26 debug("acpi rsdp checksum 2 passed\n");
27
28 return rsdp;
29}
30
31struct acpi_fadt *acpi_find_fadt(void)
32{
33 char *p, *end;
34 struct acpi_rsdp *rsdp = NULL;
35 struct acpi_rsdt *rsdt;
36 struct acpi_fadt *fadt = NULL;
37 int i;
38
39
40 for (p = (char *)ROM_TABLE_ADDR; p < (char *)ROM_TABLE_END; p += 16) {
41 rsdp = acpi_valid_rsdp((struct acpi_rsdp *)p);
42 if (rsdp)
43 break;
44 }
45
46 if (!rsdp)
47 return NULL;
48
49 debug("RSDP found at %p\n", rsdp);
50 rsdt = (struct acpi_rsdt *)(uintptr_t)rsdp->rsdt_address;
51
52 end = (char *)rsdt + rsdt->header.length;
53 debug("RSDT found at %p ends at %p\n", rsdt, end);
54
55 for (i = 0; ((char *)&rsdt->entry[i]) < end; i++) {
56 fadt = (struct acpi_fadt *)(uintptr_t)rsdt->entry[i];
57 if (strncmp((char *)fadt, "FACP", 4) == 0)
58 break;
59 fadt = NULL;
60 }
61
62 if (!fadt)
63 return NULL;
64
65 debug("FADT found at %p\n", fadt);
66 return fadt;
67}
68
69void *acpi_find_wakeup_vector(struct acpi_fadt *fadt)
70{
71 struct acpi_facs *facs;
72 void *wake_vec;
73
74 debug("Trying to find the wakeup vector...\n");
75
76 facs = (struct acpi_facs *)(uintptr_t)fadt->firmware_ctrl;
77
78 if (!facs) {
79 debug("No FACS found, wake up from S3 not possible.\n");
80 return NULL;
81 }
82
83 debug("FACS found at %p\n", facs);
84 wake_vec = (void *)(uintptr_t)facs->firmware_waking_vector;
85 debug("OS waking vector is %p\n", wake_vec);
86
87 return wake_vec;
88}
89
90void enter_acpi_mode(int pm1_cnt)
91{
92 u16 val = inw(pm1_cnt);
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108 outw(val | PM1_CNT_SCI_EN, pm1_cnt);
109}
110