diff mbox series

[1/2] acpi: iort: update IORT table to specification version E.e

Message ID 20230822100658.88705-1-ivan.hu@canonical.com
State Accepted
Headers show
Series [1/2] acpi: iort: update IORT table to specification version E.e | expand

Commit Message

Ivan Hu Aug. 22, 2023, 10:06 a.m. UTC
BugLink: https://bugs.launchpad.net/fwts/+bug/2031286

Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
---
 src/acpi/iort/iort.c        | 71 ++++++++++++++++++++++++++++++++++---
 src/lib/include/fwts_acpi.h | 13 +++++++
 2 files changed, 80 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/src/acpi/iort/iort.c b/src/acpi/iort/iort.c
index 7150e0d6..2cbf5396 100644
--- a/src/acpi/iort/iort.c
+++ b/src/acpi/iort/iort.c
@@ -60,7 +60,7 @@  static void iort_node_check(
 {
 	fwts_acpi_table_iort_node *node = (fwts_acpi_table_iort_node *)data;
 
-	if (node->type == 1 || node->type == 2 || node->type == 4) {
+	if (node->type == 1 || node->type == 2) {
 		if (node->revision > 4) {
 			*passed = false;
 			fwts_failed(fw, LOG_LEVEL_LOW,
@@ -87,6 +87,15 @@  static void iort_node_check(
 				" and should be less than 3.",
 				node->revision);
 		}
+	} else if (node->type == 4) {
+		if (node->revision > 5) {
+			*passed = false;
+			fwts_failed(fw, LOG_LEVEL_LOW,
+				"IORTNodeRevisionInvalid",
+				"IORT Node Revision field is 0x%2.2" PRIx8
+				" and should be less than 6.",
+				node->revision);
+		}
 	} else {
 		/* type 0 */
 		if (node->revision > 1) {
@@ -606,15 +615,17 @@  static void iort_check_smmuv3(
 	iort_node_check(fw, data, false, false, passed);
 	iort_id_mappings_check(fw, data, node_end, passed);
 
-	if (node->model > 0) {
+	fwts_acpi_reserved_bits("IORT", "SMMUv3 Reserved Flags", node->flags, 5, 31, passed);
+	fwts_acpi_reserved_zero("IORT", "Reserved", node->reserved, passed);
+
+	if (node->model > 2) {
 		*passed = false;
 		fwts_failed(fw, LOG_LEVEL_HIGH,
 			"IORTSmmuv3InvalidModel",
 			"IORT SMMUv3 Model is 0x%" PRIx32 " and was expecting "
-			"a model value of 0.", node->model);
+			"a model value less than 3.", node->model);
 	}
 
-	fwts_acpi_reserved_bits("IORT", "SMMUv3 Reserved Flags", node->flags, 4, 31, passed);
 	fwts_log_nl(fw);
 }
 
@@ -644,6 +655,52 @@  static void iort_check_pmcg(
 	fwts_log_nl(fw);
 }
 
+/*
+ *  Check IORT Reserved Memory Range node (RMR)
+ */
+static void iort_check_rmr(
+	fwts_framework *fw,
+	uint8_t *data,
+	uint8_t *node_end,
+	bool *passed)
+{
+	uint32_t i;
+
+	fwts_acpi_table_iort_rmr_node *node =
+		(fwts_acpi_table_iort_rmr_node *)data;
+
+	iort_node_dump(fw, "IORT RMR node", (fwts_acpi_table_iort_node *)data);
+	fwts_log_info_simp_int(fw, "  Flags:		    ", node->flags);
+	fwts_log_info_simp_int(fw, "  Number of memory range descriptors:    ", node->num_mem_rng_des);
+	fwts_log_info_simp_int(fw, "  Reference to memory range descriptors: ", node->mem_rng_des_offset);
+
+	iort_node_check(fw, data, false, false, passed);
+	iort_id_mappings_check(fw, data, node_end, passed);
+
+	fwts_acpi_reserved_bits("IORT", "RMR Reserved Flags", node->flags, 10, 31, passed);
+
+	fwts_acpi_table_iort_mem_rng_des *descriptor = (fwts_acpi_table_iort_mem_rng_des *)(data + node->mem_rng_des_offset);
+
+	for (i = 0; i < node->num_mem_rng_des; i++, descriptor++) {
+		if (sizeof(*descriptor) + (uint8_t *)descriptor > node_end) {
+			*passed = false;
+			fwts_failed(fw, LOG_LEVEL_HIGH,
+				"IORTMemRangeDescriptorOutsideTable",
+				"IORT memory range descriptors %" PRIu32 " is outside the "
+				"IORT ACPI table. Either the offset is incorrect "
+				"or the IORT table size or the node is too small.", i);
+			break;
+		}
+
+		fwts_log_info_simp_int(fw, "    Physical Range offset:               ", descriptor->physical_range_offset);
+		fwts_log_info_simp_int(fw, "    Physical Range length:               ", descriptor->physical_range_length);
+		fwts_log_info_simp_int(fw, "    Reserved:                            ", descriptor->reserved);
+		fwts_acpi_reserved_zero("IORT", "Reserved", descriptor->reserved, passed);
+	}
+
+	fwts_log_nl(fw);
+}
+
 /*
  *  IORT Remapping Table
  *     http://infocenter.arm.com/help/topic/com.arm.doc.den0049a/DEN0049A_IO_Remapping_Table.pdf
@@ -681,6 +738,9 @@  static int iort_test1(fwts_framework *fw)
 	fwts_log_info_simp_int(fw, "  Number of IORT Nodes:     ", iort->io_rt_nodes_count);
 	fwts_log_info_simp_int(fw, "  IORT Node Array Offset:   ", iort->io_rt_offset);
 	fwts_log_info_simp_int(fw, "  Reserved:                 ", iort->reserved);
+
+	fwts_acpi_reserved_zero("IORT", "Reserved", iort->reserved, &passed);
+
 	fwts_log_nl(fw);
 
 	data = (uint8_t *)table->data + iort->io_rt_offset;
@@ -719,6 +779,9 @@  static int iort_test1(fwts_framework *fw)
 		case 0x05:
 			iort_check_pmcg(fw, data, node_end, &passed);
 			break;
+		case 0x06:
+			iort_check_rmr(fw, data, node_end, &passed);
+			break;
 		default:
 			/* reserved */
 			passed = false;
diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h
index eb958b0e..249460b7 100644
--- a/src/lib/include/fwts_acpi.h
+++ b/src/lib/include/fwts_acpi.h
@@ -2153,6 +2153,19 @@  typedef struct {
 	*/
 } __attribute__ ((packed)) fwts_acpi_table_iort_pmcg_node;
 
+typedef struct {
+	uint64_t	physical_range_offset;
+	uint64_t	physical_range_length;
+	uint32_t	reserved;
+} __attribute__ ((packed)) fwts_acpi_table_iort_mem_rng_des;
+
+typedef struct {
+	fwts_acpi_table_iort_node iort_node;
+	uint32_t	flags;
+	uint32_t	num_mem_rng_des;
+	uint32_t	mem_rng_des_offset;
+} __attribute__ ((packed)) fwts_acpi_table_iort_rmr_node;
+
 /*
  * ACPI STAO (Status Override Table)
  *   http://wiki.xenproject.org/mediawiki/images/0/02/Status-override-table.pdf