@@ -586,7 +586,18 @@ static const char *madt_sub_names[] = {
/* 0x0e */ "GICR Redistributor",
/* 0x0f */ "GIC Interrupt Translation Service (ITS)",
/* 0x10 */ "Multiprocessor Wakeup",
- /* 0x11 - 0x7f */ "Reserved. OSPM skips structures of the reserved type.",
+ /* 0x11 */ "FWTS_MADT_CORE_PIC",
+ /* 0x12 */ "FWTS_MADT_LIO_PIC",
+ /* 0x13 */ "FWTS_MADT_HT_PIC",
+ /* 0x14 */ "FWTS_MADT_EIO_PIC",
+ /* 0x15 */ "FWTS_MADT_MSI_PIC",
+ /* 0x16 */ "FWTS_MADT_BIO_PIC",
+ /* 0x17 */ "FWTS_MADT_LPC_PIC",
+ /* 0x18 */ "FWTS_MADT_RINTC",
+ /* 0x19 */ "FWTS_MADT_IMSIC",
+ /* 0x1a */ "FWTS_MADT_APLIC",
+ /* 0x1b */ "FWTS_MADT_PLIC",
+ /* 0x1c - 0x7f */ "Reserved. OSPM skips structures of the reserved type.",
/* 0x80 - 0xff */ "Reserved for OEM use",
NULL
};
@@ -1501,6 +1512,280 @@ static void madt_ioapic_sapic_compare(fwts_framework *fw,
"SAPIC entry.");
}
+static int madt_rintc(fwts_framework *fw,
+ fwts_acpi_madt_sub_table_header *hdr,
+ uint8_t *data)
+{
+ /* specific checks for subtable type 0x18: RINTC */
+ fwts_acpi_madt_rintc *rintc = (fwts_acpi_madt_rintc *) data;
+
+ if (rintc->version != 1)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTRINTCVersion",
+ "MADT %s version field should be 1, "
+ "but instead got 0x%" PRIx8 ".",
+ madt_sub_names[hdr->type], rintc->version);
+ else
+ fwts_passed(fw,
+ "MADT %s version field is properly set "
+ "to 1.",
+ madt_sub_names[hdr->type]);
+
+ if (rintc->reserved)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTRINTCReservedNonZero",
+ "MADT %s reserved field should be 0, "
+ "instead got 0x%" PRIx8 ".",
+ madt_sub_names[hdr->type], rintc->reserved);
+ else
+ fwts_passed(fw,
+ "MADT %s reserved field is properly set "
+ "to 0.",
+ madt_sub_names[hdr->type]);
+
+ if (rintc->flags & 0xfffffffc)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTRINTCFlags",
+ "MADT %s flags, bit 2..31 are reserved "
+ "and should be 0, but are set as: 0x%" PRIx32 ".",
+ madt_sub_names[hdr->type], rintc->flags);
+ else
+ fwts_passed(fw,
+ "MADT %s flags, bit 2..31 are reserved "
+ "and properly set to 0.",
+ madt_sub_names[hdr->type]);
+
+ madt_find_processor_uid(fw, rintc->uid, "RINTC");
+
+ return (hdr->length - sizeof(fwts_acpi_madt_sub_table_header));
+}
+
+static int madt_imsic(fwts_framework *fw,
+ fwts_acpi_madt_sub_table_header *hdr,
+ uint8_t *data)
+{
+ /* specific checks for subtable type 0x19: IMSIC */
+ fwts_acpi_madt_imsic *imsic = (fwts_acpi_madt_imsic *) data;
+
+ if (imsic->version != 1)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTIMSICVersion",
+ "MADT %s version field should be 1, "
+ "but instead got 0x%" PRIx8 ".",
+ madt_sub_names[hdr->type], imsic->version);
+ else
+ fwts_passed(fw,
+ "MADT %s version field is properly set "
+ "to 1.",
+ madt_sub_names[hdr->type]);
+
+ if (imsic->reserved)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "SPECMADTMIMSICReservedNonZero",
+ "MADT %s reserved field should be 0, "
+ "instead got 0x%" PRIx8 ".",
+ madt_sub_names[hdr->type], imsic->reserved);
+ else
+ fwts_passed(fw,
+ "MADT %s reserved field is properly set "
+ "to 0.",
+ madt_sub_names[hdr->type]);
+
+ if (imsic->flags)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTIMSICFlags",
+ "MADT %s flags field should be 0, "
+ "but are set as: 0x%" PRIx32 ".",
+ madt_sub_names[hdr->type], imsic->flags);
+ else
+ fwts_passed(fw,
+ "MADT %s flags field should be 0 "
+ "and properly set to 0.",
+ madt_sub_names[hdr->type]);
+
+ if (imsic->num_ids < 63 || imsic->num_ids > 2047)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTIMSICNumIDs",
+ "MADT %s num_ids field should be 63..2047, "
+ "but are set as: 0x%" PRIx16 ".",
+ madt_sub_names[hdr->type], imsic->num_ids);
+ else
+ fwts_passed(fw,
+ "MADT %s num_ids field should be 63..2047 "
+ "and properly set.",
+ madt_sub_names[hdr->type]);
+
+ if (imsic->num_guest_ids < 63 || imsic->num_guest_ids > 2047)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTIMSICNumGuestIDs",
+ "MADT %s num_guest_ids field should be 63..2047, "
+ "but are set as: 0x%" PRIx16 ".",
+ madt_sub_names[hdr->type], imsic->num_guest_ids);
+ else
+ fwts_passed(fw,
+ "MADT %s num_guest_ids field should be 63..2047 "
+ "and properly set.",
+ madt_sub_names[hdr->type]);
+
+ if (imsic->guest_index_bits > 7)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTIMSICGuestIndexBits",
+ "MADT %s guest_index_bits field should be 0..7, "
+ "but are set as: 0x%" PRIx8 ".",
+ madt_sub_names[hdr->type], imsic->guest_index_bits);
+ else
+ fwts_passed(fw,
+ "MADT %s guest_index_bits field should be 0..7 "
+ "and properly set.",
+ madt_sub_names[hdr->type]);
+
+ if (imsic->hart_index_bits > 15)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTIMSICHartIndexBits",
+ "MADT %s hart_index_bits field should be 0..15, "
+ "but are set as: 0x%" PRIx8 ".",
+ madt_sub_names[hdr->type], imsic->hart_index_bits);
+ else
+ fwts_passed(fw,
+ "MADT %s hart_index_bits field should be 0..15 "
+ "and properly set.",
+ madt_sub_names[hdr->type]);
+
+ if (imsic->group_index_bits > 7)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTIMSICGroupIndexBits",
+ "MADT %s group_index_bits field should be 0..7, "
+ "but are set as: 0x%" PRIx8 ".",
+ madt_sub_names[hdr->type], imsic->group_index_bits);
+ else
+ fwts_passed(fw,
+ "MADT %s group_index_bits field should be 0..7 "
+ "and properly set.",
+ madt_sub_names[hdr->type]);
+
+ if (imsic->group_index_shift > 55)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTIMSICGroupIndexShift",
+ "MADT %s group_index_shift field should be 0..55, "
+ "but are set as: 0x%" PRIx8 ".",
+ madt_sub_names[hdr->type], imsic->group_index_shift);
+ else
+ fwts_passed(fw,
+ "MADT %s group_index_shift field should be 0..55 "
+ "and properly set.",
+ madt_sub_names[hdr->type]);
+
+ return (hdr->length - sizeof(fwts_acpi_madt_sub_table_header));
+}
+
+static int madt_aplic(fwts_framework *fw,
+ fwts_acpi_madt_sub_table_header *hdr,
+ uint8_t *data)
+{
+ /* specific checks for subtable type 0x1a: APLIC */
+ fwts_acpi_madt_aplic *aplic = (fwts_acpi_madt_aplic *) data;
+
+ if (aplic->version != 1)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTAPLICVersion",
+ "MADT %s version field should be 1, "
+ "but instead got 0x%" PRIx8 ".",
+ madt_sub_names[hdr->type], aplic->version);
+ else
+ fwts_passed(fw,
+ "MADT %s version field is properly set "
+ "to 1.",
+ madt_sub_names[hdr->type]);
+
+ if (aplic->flags)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTAPLICFlags",
+ "MADT %s flags field should be 0, "
+ "but are set as: 0x%" PRIx32 ".",
+ madt_sub_names[hdr->type], aplic->flags);
+ else
+ fwts_passed(fw,
+ "MADT %s flags field should be 0 "
+ "and properly set to 0.",
+ madt_sub_names[hdr->type]);
+
+ if (aplic->num_sources < 1 || aplic->num_sources > 1023)
+ fwts_failed(fw, LOG_LEVEL_MEDIUM,
+ "MADTAPLICNumSources",
+ "MADT %s num_sources field is %" PRIu16 ", must be 1..1023.",
+ madt_sub_names[hdr->type], aplic->num_sources);
+ else
+ fwts_passed(fw,
+ "MADT %s num_sources field is %" PRIu16 " and in 1..1023.",
+ madt_sub_names[hdr->type], aplic->num_sources);
+
+ if (aplic->addr == 0)
+ fwts_failed(fw, LOG_LEVEL_MEDIUM,
+ "MADTAPLICADDR",
+ "MADT %s addr field is 0, appears not defined.",
+ madt_sub_names[hdr->type]);
+ else
+ fwts_passed(fw,
+ "MADT %s addr field is properly defined.",
+ madt_sub_names[hdr->type]);
+
+ return (hdr->length - sizeof(fwts_acpi_madt_sub_table_header));
+}
+
+static int madt_plic(fwts_framework *fw,
+ fwts_acpi_madt_sub_table_header *hdr,
+ uint8_t *data)
+{
+ /* specific checks for subtable type 0x1b: PLIC */
+ fwts_acpi_madt_plic *plic = (fwts_acpi_madt_plic *) data;
+
+ if (plic->version != 1)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTPLICVersion",
+ "MADT %s version field should be 1, "
+ "but instead got 0x%" PRIx8 ".",
+ madt_sub_names[hdr->type], plic->version);
+ else
+ fwts_passed(fw,
+ "MADT %s version field is properly set "
+ "to 1.",
+ madt_sub_names[hdr->type]);
+
+ if (plic->num_irqs < 1 || plic->num_irqs > 1023)
+ fwts_failed(fw, LOG_LEVEL_MEDIUM,
+ "MADTPLICNumIrqs",
+ "MADT %s num_irqs field is %" PRIu16 ", must be 1..1023.",
+ madt_sub_names[hdr->type], plic->num_irqs);
+ else
+ fwts_passed(fw,
+ "MADT %s num_irqs field is %" PRIu16 " and in 1..1023.",
+ madt_sub_names[hdr->type], plic->num_irqs);
+
+ if (plic->flags)
+ fwts_failed(fw, LOG_LEVEL_LOW,
+ "MADTPLICFlags",
+ "MADT %s flags field should be 0, "
+ "but are set as: 0x%" PRIx32 ".",
+ madt_sub_names[hdr->type], plic->flags);
+ else
+ fwts_passed(fw,
+ "MADT %s flags field should be 0 "
+ "and properly set to 0.",
+ madt_sub_names[hdr->type]);
+
+ if (plic->base_addr == 0)
+ fwts_failed(fw, LOG_LEVEL_MEDIUM,
+ "MADTPLICADDR",
+ "MADT %s base_addr field is 0, appears not defined.",
+ madt_sub_names[hdr->type]);
+ else
+ fwts_passed(fw,
+ "MADT %s base_addr field is properly defined.",
+ madt_sub_names[hdr->type]);
+
+ return (hdr->length - sizeof(fwts_acpi_madt_sub_table_header));
+}
+
static int madt_subtables(fwts_framework *fw)
{
fwts_acpi_table_madt *madt = (fwts_acpi_table_madt *)mtable->data;
@@ -1684,6 +1969,22 @@ static int madt_subtables(fwts_framework *fw)
skip = madt_mp_wakup(fw, hdr, data);
break;
+ case FWTS_MADT_RINTC:
+ skip = madt_rintc(fw, hdr, data);
+ break;
+
+ case FWTS_MADT_IMSIC:
+ skip = madt_imsic(fw, hdr, data);
+ break;
+
+ case FWTS_MADT_APLIC:
+ skip = madt_aplic(fw, hdr, data);
+ break;
+
+ case FWTS_MADT_PLIC:
+ skip = madt_plic(fw, hdr, data);
+ break;
+
case FWTS_MADT_RESERVED:
fwts_failed(fw, LOG_LEVEL_MEDIUM,
"SPECMADTSubReservedID",