Skip to content

Commit 0d5ad8a

Browse files
jsun26intellijinxia
authored andcommitted
HV: add simple parser for ACPI data table
Per ACPI spec, there are two fundamental types of ACPI tables: Tables that contain AML code produced from the ACPI Source Language (ASL). These include the DSDT, any SSDTs, and sometimes OEM-specific tables (OEMx). Tables that contain simple data and no AML byte code. These types of tables are known as ACPI Data Tables. They include tables such as the FADT, MADT, ECDT, SRAT, etc. -essentially any table other than a DSDT or SSDT. The second type of table, the ACPI Data Table, could be parsed here. If Kconfig of CONSTANT_ACPI is set to yes, this parser is not needed. Tracked-On: #1264 Signed-off-by: Victor Sun <victor.sun@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent a1e9fdc commit 0d5ad8a

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

hypervisor/boot/acpi.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#define ACPI_SIG_RSDP "RSD PTR " /* Root System Description Ptr */
3535
#define ACPI_OEM_ID_SIZE 6
3636
#define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */
37+
#define ACPI_SIG_FADT "FACP" /* Fixed ACPI Description Table */
3738
#define ACPI_SIG_DMAR "DMAR"
3839
#define RSDP_CHECKSUM_LENGTH 20
3940
#define ACPI_NAME_SIZE 4U
@@ -281,3 +282,86 @@ void *get_dmar_table(void)
281282
{
282283
return get_acpi_tbl(ACPI_SIG_DMAR);
283284
}
285+
286+
#ifndef CONFIG_CONSTANT_ACPI
287+
/* Per ACPI spec:
288+
* There are two fundamental types of ACPI tables:
289+
*
290+
* Tables that contain AML code produced from the ACPI Source Language (ASL).
291+
* These include the DSDT, any SSDTs, and sometimes OEM-specific tables (OEMx).
292+
*
293+
* Tables that contain simple data and no AML byte code. These types of tables
294+
* are known as ACPI Data Tables. They include tables such as the FADT, MADT,
295+
* ECDT, SRAT, etc. -essentially any table other than a DSDT or SSDT.
296+
*
297+
* The second type of table, the ACPI Data Table, could be parsed here.
298+
*
299+
* When ACRN go production, the platform ACPI data should be fixed. The
300+
* Kconfig of CONSTANT_ACPI will be set to yes, then this code is not needed.
301+
*/
302+
303+
#define ACPI_SIG_FACS 0x53434146U /* "FACS" */
304+
305+
/* FACP field offsets */
306+
#define OFFSET_FACS_ADDR 36U
307+
#define OFFSET_FACS_X_ADDR 132U
308+
309+
/* FACS field offsets */
310+
#define OFFSET_FACS_SIGNATURE 0U
311+
#define OFFSET_FACS_LENGTH 4U
312+
#define OFFSET_WAKE_VECTOR_32 12U
313+
#define OFFSET_WAKE_VECTOR_64 24U
314+
315+
/* get a dword value from given table and its offset */
316+
static inline uint32_t get_acpi_dt_dword(uint8_t *dt_addr, uint32_t dt_offset)
317+
{
318+
return *(uint32_t *)(dt_addr + dt_offset);
319+
}
320+
321+
/* get a qword value from given table and its offset */
322+
static inline uint64_t get_acpi_dt_qword(uint8_t *dt_addr, uint32_t dt_offset)
323+
{
324+
return *(uint64_t *)(dt_addr + dt_offset);
325+
}
326+
327+
static void *get_facs_table(void)
328+
{
329+
uint8_t *facp_addr, *facs_addr, *facs_x_addr;
330+
uint32_t signature, length;
331+
332+
facp_addr = (uint8_t *)get_acpi_tbl(ACPI_SIG_FADT);
333+
334+
if (facp_addr == NULL) {
335+
return NULL;
336+
}
337+
338+
facs_addr = (uint8_t *)(uint64_t)get_acpi_dt_dword(facp_addr,
339+
OFFSET_FACS_ADDR);
340+
341+
facs_x_addr = (uint8_t *)get_acpi_dt_qword(facp_addr,
342+
OFFSET_FACS_X_ADDR);
343+
344+
if (facs_x_addr != NULL) {
345+
facs_addr = facs_x_addr;
346+
}
347+
348+
if (facs_addr == NULL) {
349+
return NULL;
350+
}
351+
352+
signature = get_acpi_dt_dword(facs_addr, OFFSET_FACS_SIGNATURE);
353+
354+
if (signature != ACPI_SIG_FACS) {
355+
return NULL;
356+
}
357+
358+
length = get_acpi_dt_dword(facs_addr, OFFSET_FACS_LENGTH);
359+
360+
if (length < 64U) {
361+
return NULL;
362+
}
363+
364+
return facs_addr;
365+
}
366+
367+
#endif

0 commit comments

Comments
 (0)