@@ -29,22 +29,16 @@
static fwts_acpi_table_info *table;
acpi_table_init(ASPT, &table)
-/*
- * ASPT Table
- * (reverse engineered, table is common on AMD machines)
- */
-static int aspt_test1(fwts_framework *fw)
+static int aspt_revision1_test(fwts_framework *fw, fwts_acpi_table_aspt *aspt)
{
bool passed = true;
uint32_t offset;
- fwts_acpi_table_aspt *aspt = (fwts_acpi_table_aspt *)table->data;
fwts_log_info_verbatim(fw, "AMD Secure Processor Table:");
- fwts_log_info_simp_int(fw, " ASP Register Structure Count: ", aspt->asp_reg_count);
-
- offset = sizeof(aspt->header) + sizeof(aspt->asp_reg_count);
+ fwts_log_info_simp_int(fw, " ASP Register Structure Count: ", aspt->v1.asp_reg_count);
+ offset = sizeof(aspt->header) + sizeof(aspt->v1.asp_reg_count);
- for (uint32_t i = 0; i < aspt->asp_reg_count; i++) {
+ for (uint32_t i = 0; i < aspt->v1.asp_reg_count; i++) {
if ((offset + sizeof(fwts_aspt_sub_header)) > table->length) {
fwts_failed(fw, LOG_LEVEL_HIGH,
"ASPTOutOfRangeOffset",
@@ -61,9 +55,9 @@ static int aspt_test1(fwts_framework *fw)
fwts_log_info_simp_int(fw, " Length: ", entry_global->header.length);
fwts_log_info_simp_int(fw, " Reserved: ", entry_global->reserved);
fwts_acpi_reserved_zero("ASPT", "Reserved", entry_global->reserved, &passed);
- fwts_log_info_simp_int(fw, " Feature Register Address: ", entry_global->feature_reg_addr);
- fwts_log_info_simp_int(fw, " Interrupt Enable Register Address: ", entry_global->interrupt_enable_reg_addr);
- fwts_log_info_simp_int(fw, " Interrupt Status Register Address: ", entry_global->interrupt_stable_reg_addr);
+ fwts_log_info_simp_int(fw, " Feature Register Address: ", entry_global->v1.feature_reg_addr);
+ fwts_log_info_simp_int(fw, " Interrupt Enable Register Address: ", entry_global->v1.interrupt_enable_reg_addr);
+ fwts_log_info_simp_int(fw, " Interrupt Status Register Address: ", entry_global->v1.interrupt_stable_reg_addr);
offset += entry_global->header.length;
break;
case 1:
@@ -77,9 +71,9 @@ static int aspt_test1(fwts_framework *fw)
fwts_log_info_verbatim(fw, " Reserved:");
fwts_hexdump_data_prefix_all(fw, entry_sev->reserved, " ", sizeof(entry_sev->reserved));
fwts_acpi_reserved_zero_array(fw, "ASPT", "Reserved", entry_sev->reserved, sizeof(entry_sev->reserved), &passed);
- fwts_log_info_simp_int(fw, " CmdResp Register Address: ", entry_sev->cmdresp_reg_addr);
- fwts_log_info_simp_int(fw, " CmdBufAddr_Lo Register Address: ", entry_sev->cmdbufaddr_lo_reg_addr);
- fwts_log_info_simp_int(fw, " CmdBufAddr_Hi Register Address: ", entry_sev->cmdbufaddr_hi_reg_addr);
+ fwts_log_info_simp_int(fw, " CmdResp Register Address: ", entry_sev->v1.cmdresp_reg_addr);
+ fwts_log_info_simp_int(fw, " CmdBufAddr_Lo Register Address: ", entry_sev->v1.cmdbufaddr_lo_reg_addr);
+ fwts_log_info_simp_int(fw, " CmdBufAddr_Hi Register Address: ", entry_sev->v1.cmdbufaddr_hi_reg_addr);
offset += entry_sev->header.length;
break;
case 2:
@@ -90,10 +84,10 @@ static int aspt_test1(fwts_framework *fw)
fwts_log_info_simp_int(fw, " Length: ", entry_acpi->header.length);
fwts_log_info_simp_int(fw, " Reserved: ", entry_acpi->reserved);
fwts_acpi_reserved_zero("ASPT", "Reserved", entry_acpi->reserved, &passed);
- fwts_log_info_simp_int(fw, " CmdResp Register Address: ", entry_acpi->cmdresp_reg_addr);
+ fwts_log_info_simp_int(fw, " CmdResp Register Address: ", entry_acpi->v1.cmdresp_reg_addr);
fwts_log_info_verbatim(fw, " Reserved:");
- fwts_hexdump_data_prefix_all(fw, entry_acpi->reserved1, " ", sizeof(entry_acpi->reserved1));
- fwts_acpi_reserved_zero_array(fw, "ASPT", "Reserved", entry_acpi->reserved1, sizeof(entry_acpi->reserved1), &passed);
+ fwts_hexdump_data_prefix_all(fw, entry_acpi->v1.reserved1, " ", sizeof(entry_acpi->v1.reserved1));
+ fwts_acpi_reserved_zero_array(fw, "ASPT", "Reserved", entry_acpi->v1.reserved1, sizeof(entry_acpi->v1.reserved1), &passed);
offset += entry_acpi->header.length;
break;
default:
@@ -103,12 +97,115 @@ static int aspt_test1(fwts_framework *fw)
"ASPT register structures must have type with 0, 1 "
"and 2, got %" PRIu16 " instead",
((fwts_aspt_sub_header *)((uint8_t *)table->data + offset))->type);
- return FWTS_OK;
- break;
+ return passed;
fwts_log_nl(fw);
}
}
+ return passed;
+}
+
+static int aspt_revision2_test(fwts_framework *fw, fwts_acpi_table_aspt *aspt)
+{
+ bool passed = true;
+ uint32_t offset;
+
+ fwts_log_info_verbatim(fw, "AMD Secure Processor Table:");
+ fwts_log_info_simp_int(fw, " ASP Register Base Address: ", aspt->v2.asp_reg_base_addr);
+ fwts_log_info_simp_int(fw, " ASP Register Space Pages: ", aspt->v2.asp_reg_apace_pages);
+ fwts_log_info_simp_int(fw, " ASP Register Structure Count: ", aspt->v2.asp_reg_count);
+ offset = sizeof(aspt->header) + sizeof(aspt->v2.asp_reg_base_addr) +
+ sizeof(aspt->v2.asp_reg_apace_pages) + sizeof(aspt->v2.asp_reg_count);
+
+ for (uint32_t i = 0; i < aspt->v2.asp_reg_count; i++) {
+ if ((offset + sizeof(fwts_aspt_sub_header)) > table->length) {
+ fwts_failed(fw, LOG_LEVEL_HIGH,
+ "ASPTOutOfRangeOffset",
+ "ASPT offset is out of range.");
+ return FWTS_OK;
+ }
+ uint16_t type = ((fwts_aspt_sub_header *)((uint8_t *)table->data + offset))->type;
+ switch (type) {
+ case 0:
+ fwts_acpi_table_asp_global *entry_global;
+ entry_global = (fwts_acpi_table_asp_global *)((uint8_t *)table->data + offset);
+ fwts_log_info_verbatim(fw, " ASP Global Registers:");
+ fwts_log_info_simp_int(fw, " Type: ", entry_global->header.type);
+ fwts_log_info_simp_int(fw, " Length: ", entry_global->header.length);
+ fwts_log_info_simp_int(fw, " Reserved: ", entry_global->reserved);
+ fwts_acpi_reserved_zero("ASPT", "Reserved", entry_global->reserved, &passed);
+ fwts_log_info_simp_int(fw, " Feature Register Offset: ", entry_global->v2.feature_reg_offset);
+ fwts_log_info_simp_int(fw, " Interrupt Enable Register Offset: ", entry_global->v2.interrupt_enable_reg_offset);
+ fwts_log_info_simp_int(fw, " Interrupt Status Register Offset: ", entry_global->v2.interrupt_stable_reg_offset);
+ offset += entry_global->header.length;
+ break;
+ case 1:
+ fwts_acpi_table_sev_mailbox *entry_sev;
+ entry_sev = (fwts_acpi_table_sev_mailbox *)((uint8_t *)table->data + offset);
+ fwts_log_info_verbatim(fw, " SEV Mailbox Registers:");
+ fwts_log_info_simp_int(fw, " Type: ", entry_sev->header.type);
+ fwts_log_info_simp_int(fw, " Length: ", entry_sev->header.length);
+ fwts_log_info_simp_int(fw, " Mailbox Interrupt ID: ", entry_sev->mailbox_interrupt_id);
+ fwts_acpi_reserved_bits("ASPT", "Mailbox Interrupt ID", entry_sev->mailbox_interrupt_id, 6, 7, &passed);
+ fwts_log_info_verbatim(fw, " Reserved:");
+ fwts_hexdump_data_prefix_all(fw, entry_sev->reserved, " ", sizeof(entry_sev->reserved));
+ fwts_acpi_reserved_zero_array(fw, "ASPT", "Reserved", entry_sev->reserved, sizeof(entry_sev->reserved), &passed);
+ fwts_log_info_simp_int(fw, " CmdResp Register Offset: ", entry_sev->v2.cmdresp_reg_offset);
+ fwts_log_info_simp_int(fw, " CmdBufAddr_Lo Register Offset: ", entry_sev->v2.cmdbufaddr_lo_reg_offset);
+ fwts_log_info_simp_int(fw, " CmdBufAddr_Hi Register Offset: ", entry_sev->v2.cmdbufaddr_hi_reg_offset);
+ offset += entry_sev->header.length;
+ break;
+ case 2:
+ fwts_acpi_table_acpi_mailbox *entry_acpi;
+ entry_acpi = (fwts_acpi_table_acpi_mailbox *)((uint8_t *)table->data + offset);
+ fwts_log_info_verbatim(fw, " ACPI Mailbox Registers:");
+ fwts_log_info_simp_int(fw, " Type: ", entry_acpi->header.type);
+ fwts_log_info_simp_int(fw, " Length: ", entry_acpi->header.length);
+ fwts_log_info_simp_int(fw, " Reserved: ", entry_acpi->reserved);
+ fwts_acpi_reserved_zero("ASPT", "Reserved", entry_acpi->reserved, &passed);
+ fwts_log_info_simp_int(fw, " CmdResp Register Offset: ", entry_acpi->v2.cmdresp_reg_offset);
+ fwts_log_info_verbatim(fw, " Reserved:");
+ fwts_hexdump_data_prefix_all(fw, entry_acpi->v2.reserved1, " ", sizeof(entry_acpi->v2.reserved1));
+ fwts_acpi_reserved_zero_array(fw, "ASPT", "Reserved", entry_acpi->v2.reserved1, sizeof(entry_acpi->v2.reserved1), &passed);
+ offset += entry_acpi->header.length;
+ break;
+ default:
+ passed = false;
+ fwts_failed(fw, LOG_LEVEL_HIGH,
+ "ASPTBadType",
+ "ASPT register structures must have type with 0, 1 "
+ "and 2, got %" PRIu16 " instead",
+ ((fwts_aspt_sub_header *)((uint8_t *)table->data + offset))->type);
+ return passed;
+ fwts_log_nl(fw);
+ }
+ }
+
+ return passed;
+}
+
+static int aspt_test1(fwts_framework *fw)
+{
+ bool passed = true;
+
+ fwts_acpi_table_aspt *aspt = (fwts_acpi_table_aspt *)table->data;
+
+ switch (aspt->header.revision) {
+ case 1:
+ passed = aspt_revision1_test(fw, aspt);
+ break;
+ case 2:
+ passed = aspt_revision2_test(fw, aspt);
+ break;
+ default:
+ passed = false;
+ fwts_failed(fw, LOG_LEVEL_HIGH,
+ "ASPTUnknowRevision",
+ "ASPT revision is unknown, currently must be one or two, "
+ " but got %" PRIu8 " instead", aspt->header.revision);
+ return FWTS_OK;
+ }
+
if (passed)
fwts_passed(fw, "No issues found in ASPT table.");
@@ -2283,30 +2283,65 @@ typedef struct {
typedef struct {
fwts_aspt_sub_header header;
uint32_t reserved;
- uint64_t feature_reg_addr;
- uint64_t interrupt_enable_reg_addr;
- uint64_t interrupt_stable_reg_addr;
+ union {
+ struct{
+ uint64_t feature_reg_addr;
+ uint64_t interrupt_enable_reg_addr;
+ uint64_t interrupt_stable_reg_addr;
+ } __attribute__ ((packed)) v1;
+ struct {
+ uint32_t feature_reg_offset;
+ uint32_t interrupt_enable_reg_offset;
+ uint32_t interrupt_stable_reg_offset;
+ } __attribute__ ((packed)) v2;
+ };
} __attribute__ ((packed)) fwts_acpi_table_asp_global;
typedef struct {
fwts_aspt_sub_header header;
uint8_t mailbox_interrupt_id;
uint8_t reserved[3];
- uint64_t cmdresp_reg_addr;
- uint64_t cmdbufaddr_lo_reg_addr;
- uint64_t cmdbufaddr_hi_reg_addr;
+ union {
+ struct{
+ uint64_t cmdresp_reg_addr;
+ uint64_t cmdbufaddr_lo_reg_addr;
+ uint64_t cmdbufaddr_hi_reg_addr;
+ } __attribute__ ((packed)) v1;
+ struct {
+ uint32_t cmdresp_reg_offset;
+ uint32_t cmdbufaddr_lo_reg_offset;
+ uint32_t cmdbufaddr_hi_reg_offset;
+ } __attribute__ ((packed)) v2;
+ };
} __attribute__ ((packed)) fwts_acpi_table_sev_mailbox;
typedef struct {
fwts_aspt_sub_header header;
uint32_t reserved;
- uint64_t cmdresp_reg_addr;
- uint8_t reserved1[16];
+ union {
+ struct{
+ uint64_t cmdresp_reg_addr;
+ uint8_t reserved1[16];
+ } __attribute__ ((packed)) v1;
+ struct {
+ uint32_t cmdresp_reg_offset;
+ uint8_t reserved1[8];
+ } __attribute__ ((packed)) v2;
+ };
} __attribute__ ((packed)) fwts_acpi_table_acpi_mailbox;
typedef struct {
fwts_acpi_table_header header;
- uint32_t asp_reg_count;
+ union {
+ struct{
+ uint32_t asp_reg_count;
+ } __attribute__ ((packed)) v1;
+ struct {
+ uint64_t asp_reg_base_addr;
+ uint32_t asp_reg_apace_pages;
+ uint32_t asp_reg_count;
+ } __attribute__ ((packed)) v2;
+ };
uint8_t asp_reg_structure[0];
} __attribute__ ((packed)) fwts_acpi_table_aspt;
Buglink: https://bugs.launchpad.net/fwts/+bug/2112299 Add tests for supporting the ASPT specification revision 2 https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/58193_1_00-PUB.pdf Signed-off-by: Ivan Hu <ivan.hu@canonical.com> --- src/acpi/aspt/aspt.c | 139 ++++++++++++++++++++++++++++++------ src/lib/include/fwts_acpi.h | 53 +++++++++++--- 2 files changed, 162 insertions(+), 30 deletions(-)