diff mbox series

[1/2] acpi: aspt: support for the aspt revision 2

Message ID 20250609072037.41119-1-ivan.hu@canonical.com
State Accepted
Headers show
Series [1/2] acpi: aspt: support for the aspt revision 2 | expand

Commit Message

Ivan Hu June 9, 2025, 7:20 a.m. UTC
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(-)
diff mbox series

Patch

diff --git a/src/acpi/aspt/aspt.c b/src/acpi/aspt/aspt.c
index c39d7cdb..2809e28f 100644
--- a/src/acpi/aspt/aspt.c
+++ b/src/acpi/aspt/aspt.c
@@ -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.");
 
diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h
index 43d1d7cd..e6702aff 100644
--- a/src/lib/include/fwts_acpi.h
+++ b/src/lib/include/fwts_acpi.h
@@ -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;