1 /* ----------------------------------------------------------------------- *
3 * Copyright 2009-2011 Erwan Velu - All Rights Reserved
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use,
9 * copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom
11 * the Software is furnished to do so, subject to the following
14 * The above copyright notice and this permission notice shall
15 * be included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
26 * -----------------------------------------------------------------------
33 #include "acpi/acpi.h"
35 /* M1PS flags have to be interpreted as strings */
36 char *flags_to_string(char *buffer
, uint16_t flags
)
38 memset(buffer
, 0, sizeof(buffer
));
39 strcpy(buffer
, "default");
40 if ((flags
& POLARITY_ACTIVE_HIGH
) == POLARITY_ACTIVE_HIGH
)
41 strcpy(buffer
, "high");
42 else if ((flags
& POLARITY_ACTIVE_LOW
) == POLARITY_ACTIVE_LOW
)
43 strcpy(buffer
, "low");
44 if ((flags
& TRIGGER_EDGE
) == TRIGGER_EDGE
)
45 strncat(buffer
, " edge", 5);
46 else if ((flags
& TRIGGER_LEVEL
) == TRIGGER_LEVEL
)
47 strncat(buffer
, " level", 6);
49 strncat(buffer
, " default", 8);
54 void dbg_printf(const char *fmt
, ...)
58 vfprintf(stderr
, fmt
, args
);
62 void init_acpi(s_acpi
* acpi
)
64 memset(acpi
, 0, sizeof(s_acpi
));
67 int parse_acpi(s_acpi
* acpi
)
72 /* Let's seach for RSDP table */
73 if ((ret_val
= search_rsdp(acpi
)) != RSDP_TABLE_FOUND
)
76 /* Let's seach for RSDT table
77 * That's not a big deal not having it, XSDT is far more relevant */
78 parse_rsdt(&acpi
->rsdt
);
79 if (parse_xsdt(acpi
) != XSDT_TABLE_FOUND
) {
80 DEBUG_PRINT(("XSDT Detection failed\n"));
81 for (int table
=0; table
<acpi
->rsdt
.entry_count
; table
++) {
82 parse_header((uint64_t *)acpi
->rsdt
.entry
[table
],acpi
);
88 void get_acpi_description_header(uint8_t * q
, s_acpi_description_header
* adh
)
90 cp_str_struct(adh
->signature
);
91 cp_struct(&adh
->length
);
92 cp_struct(&adh
->revision
);
93 cp_struct(&adh
->checksum
);
94 cp_str_struct(adh
->oem_id
);
95 cp_str_struct(adh
->oem_table_id
);
96 cp_struct(&adh
->oem_revision
);
97 cp_str_struct(adh
->creator_id
);
98 cp_struct(&adh
->creator_revision
);
99 DEBUG_PRINT(("acpi_header at %p = %s | %s | %s\n", q
, adh
->signature
,adh
->oem_id
, adh
->creator_id
));
102 bool parse_header(uint64_t *address
, s_acpi
*acpi
) {
103 s_acpi_description_header adh
;
104 memset(&adh
, 0, sizeof(adh
));
106 get_acpi_description_header((uint8_t *)address
, &adh
);
108 /* Trying to determine the pointed table */
109 /* Looking for FADT */
110 if (memcmp(adh
.signature
, FACP
, sizeof(FACP
) - 1) == 0) {
111 DEBUG_PRINT(("FACP table found\n"));
112 s_fadt
*f
= &acpi
->fadt
;
113 s_facs
*fa
= &acpi
->facs
;
114 s_dsdt
*d
= &acpi
->dsdt
;
115 /* This structure is valid, let's fill it */
117 f
->address
= address
;
118 memcpy(&f
->header
, &adh
, sizeof(adh
));
121 /* FACS wasn't already detected
122 * FADT points to it, let's try to detect it */
123 if (fa
->valid
== false) {
124 fa
->address
= (uint64_t *)f
->x_firmware_ctrl
;
126 if (fa
->valid
== false) {
127 /* Let's try again */
128 fa
->address
= (uint64_t *)f
->firmware_ctrl
;
133 /* DSDT wasn't already detected
134 * FADT points to it, let's try to detect it */
135 if (d
->valid
== false) {
136 s_acpi_description_header new_adh
;
137 get_acpi_description_header((uint8_t *)f
->x_dsdt
,
139 if (memcmp(new_adh
.signature
, DSDT
, sizeof(DSDT
) - 1) == 0) {
140 DEBUG_PRINT(("DSDT table found via x_dsdt\n"));
142 d
->address
= (uint64_t *)f
->x_dsdt
;
143 memcpy(&d
->header
, &new_adh
, sizeof(new_adh
));
146 /* Let's try again */
147 get_acpi_description_header((uint8_t *)f
->dsdt_address
,
149 if (memcmp(new_adh
.signature
, DSDT
, sizeof(DSDT
) - 1) ==
151 DEBUG_PRINT(("DSDT table found via dsdt_address\n"));
153 d
->address
= (uint64_t *)f
->dsdt_address
;
154 memcpy(&d
->header
, &new_adh
, sizeof(new_adh
));
159 } /* Looking for MADT */
160 else if (memcmp(adh
.signature
, APIC
, sizeof(APIC
) - 1) == 0) {
161 DEBUG_PRINT(("MADT table found\n"));
162 s_madt
*m
= &acpi
->madt
;
163 /* This structure is valid, let's fill it */
166 memcpy(&m
->header
, &adh
, sizeof(adh
));
168 } else if (memcmp(adh
.signature
, DSDT
, sizeof(DSDT
) - 1) == 0) {
169 DEBUG_PRINT(("DSDT table found\n"));
170 s_dsdt
*d
= &acpi
->dsdt
;
171 /* This structure is valid, let's fill it */
173 d
->address
= address
;
174 memcpy(&d
->header
, &adh
, sizeof(adh
));
176 /* PSDT have to be considered as SSDT. Intel ACPI Spec @ 5.2.11.3 */
177 } else if ((memcmp(adh
.signature
, SSDT
, sizeof(SSDT
) - 1) == 0)
178 || (memcmp(adh
.signature
, PSDT
, sizeof(PSDT
) - 1) == 0)) {
180 DEBUG_PRINT(("SSDT table found with %s \n",adh
.signature
));
182 if ((acpi
->ssdt_count
>= MAX_SSDT
- 1))
185 /* We can have many SSDT, so let's allocate a new one */
186 if ((acpi
->ssdt
[acpi
->ssdt_count
] =
187 malloc(sizeof(s_ssdt
))) == NULL
)
189 s_ssdt
*s
= acpi
->ssdt
[acpi
->ssdt_count
];
191 /* This structure is valid, let's fill it */
193 s
->address
= address
;
194 memcpy(&s
->header
, &adh
, sizeof(adh
));
196 /* Searching how much definition blocks we must copy */
197 uint32_t definition_block_size
= adh
.length
- ACPI_HEADER_SIZE
;
198 if ((s
->definition_block
=
199 malloc(definition_block_size
)) != NULL
) {
200 memcpy(s
->definition_block
,
201 (s
->address
+ ACPI_HEADER_SIZE
),
202 definition_block_size
);
204 /* Increment the number of ssdt we have */
206 } else if (memcmp(adh
.signature
, SBST
, sizeof(SBST
) - 1) == 0) {
207 DEBUG_PRINT(("SBST table found\n"));
208 s_sbst
*s
= &acpi
->sbst
;
209 /* This structure is valid, let's fill it */
211 s
->address
= address
;
212 memcpy(&s
->header
, &adh
, sizeof(adh
));
214 } else if (memcmp(adh
.signature
, ECDT
, sizeof(ECDT
) - 1) == 0) {
215 DEBUG_PRINT(("ECDT table found\n"));
216 s_ecdt
*e
= &acpi
->ecdt
;
217 /* This structure is valid, let's fill it */
219 e
->address
= address
;
220 memcpy(&e
->header
, &adh
, sizeof(adh
));
222 } else if (memcmp(adh
.signature
, HPET
, sizeof(HPET
) - 1) == 0) {
223 DEBUG_PRINT(("HPET table found\n"));
224 s_hpet
*h
= &acpi
->hpet
;
225 /* This structure is valid, let's fill it */
227 h
->address
= address
;
228 memcpy(&h
->header
, &adh
, sizeof(adh
));
229 } else if (memcmp(adh
.signature
, TCPA
, sizeof(TCPA
) - 1) == 0) {
230 DEBUG_PRINT(("TCPA table found\n"));
231 s_tcpa
*t
= &acpi
->tcpa
;
232 /* This structure is valid, let's fill it */
234 t
->address
= address
;
235 memcpy(&t
->header
, &adh
, sizeof(adh
));
236 } else if (memcmp(adh
.signature
, MCFG
, sizeof(MCFG
) - 1) == 0) {
237 DEBUG_PRINT(("MCFG table found\n"));
238 s_mcfg
*m
= &acpi
->mcfg
;
239 /* This structure is valid, let's fill it */
241 m
->address
= address
;
242 memcpy(&m
->header
, &adh
, sizeof(adh
));
243 } else if (memcmp(adh
.signature
, SLIC
, sizeof(SLIC
) - 1) == 0) {
244 DEBUG_PRINT(("SLIC table found\n"));
245 s_slic
*s
= &acpi
->slic
;
246 /* This structure is valid, let's fill it */
248 s
->address
= address
;
249 memcpy(&s
->header
, &adh
, sizeof(adh
));
250 } else if (memcmp(adh
.signature
, BOOT
, sizeof(BOOT
) - 1) == 0) {
251 DEBUG_PRINT(("BOOT table found\n"));
252 s_boot
*b
= &acpi
->boot
;
253 /* This structure is valid, let's fill it */
255 b
->address
= address
;
256 memcpy(&b
->header
, &adh
, sizeof(adh
));