Message ID | 1406286341-16115-1-git-send-email-colin.king@canonical.com |
---|---|
State | Accepted |
Headers | show |
On 07/25/2014 07:05 PM, Colin King wrote: > From: Colin Ian King <colin.king@canonical.com> > > ACPI 5.1 sections 5.2.12.14 to 5.2.12.17 describe new MADT > structures, so add these structures to fwts and update the acpidump > and acpitables tests accordingly. > > Signed-off-by: Colin Ian King <colin.king@canonical.com> > --- > src/acpi/acpidump/acpidump.c | 65 ++++++++++++++++++++-------- > src/acpi/acpitables/acpitables.c | 93 +++++++++++++++++++++++++++++++++------- > src/lib/include/fwts_acpi.h | 46 +++++++++++++++++++- > 3 files changed, 169 insertions(+), 35 deletions(-) > > diff --git a/src/acpi/acpidump/acpidump.c b/src/acpi/acpidump/acpidump.c > index ee148b0..15a4e5d 100644 > --- a/src/acpi/acpidump/acpidump.c > +++ b/src/acpi/acpidump/acpidump.c > @@ -813,7 +813,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > offset += sizeof(fwts_acpi_madt_sub_table_header); > > switch (hdr->type) { > - case 0: { > + case FWTS_ACPI_MADT_LOCAL_APIC: { > static const fwts_acpidump_field fields_processor_local_apic[] = { > FIELD_UINT(" ACPI CPU ID", fwts_acpi_madt_processor_local_apic, acpi_processor_id), > FIELD_UINT(" APIC ID", fwts_acpi_madt_processor_local_apic, apic_id), > @@ -825,7 +825,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > skip = sizeof(fwts_acpi_madt_processor_local_apic); > } > break; > - case 1: { > + case FWTS_ACPI_MADT_IO_APIC: { > static const fwts_acpidump_field fields_io_apic[] = { > FIELD_UINT(" I/O APIC ID", fwts_acpi_madt_io_apic, io_apic_id), > FIELD_UINT(" I/O APIC Addr", fwts_acpi_madt_io_apic, io_apic_phys_address), > @@ -836,7 +836,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > skip = sizeof(fwts_acpi_madt_io_apic); > } > break; > - case 2: { > + case FWTS_ACPI_MADT_INTERRUPT_OVERRIDE: { > static const fwts_acpidump_field fields_madt_interrupt_override[] = { > FIELD_UINT(" Bus", fwts_acpi_madt_interrupt_override, bus), > FIELD_UINT(" Source", fwts_acpi_madt_interrupt_override, source), > @@ -850,7 +850,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > skip = sizeof(fwts_acpi_madt_interrupt_override); > } > break; > - case 3: { > + case FWTS_ACPI_MADT_NMI_SOURCE: { > static const fwts_acpidump_field fields_madt_nmi[] = { > FIELD_UINT(" Flags", fwts_acpi_madt_nmi, flags), > FIELD_UINT(" Gbl Sys Int", fwts_acpi_madt_nmi, gsi), > @@ -860,7 +860,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > skip = sizeof(fwts_acpi_madt_nmi); > } > break; > - case 4: { > + case FWTS_ACPI_MADT_LOCAL_APIC_NMI: { > static const fwts_acpidump_field fields_madt_local_apic_nmi[] = { > FIELD_UINT(" ACPI CPU ID", fwts_acpi_madt_local_apic_nmi, acpi_processor_id), > FIELD_UINT(" Flags", fwts_acpi_madt_local_apic_nmi, flags), > @@ -871,7 +871,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > skip = sizeof(fwts_acpi_madt_local_apic_nmi); > } > break; > - case 5: { > + case FWTS_ACPI_MADT_LOCAL_APIC_OVERRIDE: { > static const fwts_acpidump_field fields_madt_local_apic_addr_override[] = { > FIELD_UINT(" Local APIC Addr", fwts_acpi_madt_local_apic_addr_override, address), > FIELD_END > @@ -880,7 +880,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > skip = sizeof(fwts_acpi_madt_local_apic_addr_override); > } > break; > - case 6: { > + case FWTS_ACPI_MADT_IO_SAPIC: { > static const fwts_acpidump_field fields_madt_io_sapic[] = { > FIELD_UINT(" I/O SAPIC ID", fwts_acpi_madt_io_sapic, io_sapic_id), > FIELD_UINT(" Gbl Sys Int", fwts_acpi_madt_io_sapic, gsi), > @@ -891,7 +891,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > skip = sizeof(fwts_acpi_madt_io_sapic); > } > break; > - case 7: { > + case FWTS_ACPI_MADT_LOCAL_SAPIC: { > fwts_acpi_madt_local_sapic *local_sapic = (fwts_acpi_madt_local_sapic *)data; > static const fwts_acpidump_field fields_madt_local_sapic[] = { > FIELD_UINT(" ACPI CPU ID", fwts_acpi_madt_local_sapic, acpi_processor_id), > @@ -907,7 +907,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > strlen(local_sapic->uid_string) + 1); > } > break; > - case 8: { > + case FWTS_ACPI_MADT_INTERRUPT_SOURCE: { > static const fwts_acpidump_field fields_madt_local_sapic[] = { > FIELD_UINT(" Flags", fwts_acpi_madt_platform_int_source, flags), > FIELD_UINT(" Type", fwts_acpi_madt_platform_int_source, type), > @@ -919,10 +919,10 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > FIELD_END > }; > __acpi_dump_table_fields(fw, data, fields_madt_local_sapic, offset); > - skip = (sizeof(fwts_acpi_madt_platform_int_source)); > + skip = sizeof(fwts_acpi_madt_platform_int_source); > } > break; > - case 9: { > + case FWTS_ACPI_MADT_LOCAL_X2APIC: { > static const fwts_acpidump_field fields_madt_local_x2apic[] = { > FIELD_UINT(" x2APIC ID", fwts_acpi_madt_local_x2apic, x2apic_id), > FIELD_UINT(" Flags", fwts_acpi_madt_local_x2apic, flags), > @@ -930,10 +930,10 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > FIELD_END > }; > __acpi_dump_table_fields(fw, data, fields_madt_local_x2apic, offset); > - skip = (sizeof(fwts_acpi_madt_local_x2apic)); > + skip = sizeof(fwts_acpi_madt_local_x2apic); > } > break; > - case 10: { > + case FWTS_ACPI_MADT_LOCAL_X2APIC_NMI: { > static const fwts_acpidump_field fields_madt_local_x2apic_nmi[] = { > FIELD_UINT(" Flags", fwts_acpi_madt_local_x2apic_nmi, flags), > FIELD_UINT(" Processor UID", fwts_acpi_madt_local_x2apic_nmi, processor_uid), > @@ -941,10 +941,10 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > FIELD_END > }; > __acpi_dump_table_fields(fw, data, fields_madt_local_x2apic_nmi, offset); > - skip = (sizeof(fwts_acpi_madt_local_x2apic_nmi)); > + skip = sizeof(fwts_acpi_madt_local_x2apic_nmi); > } > break; > - case 11: { > + case FWTS_ACPI_MADT_GIC_C_CPU_INTERFACE: { > static const fwts_acpidump_field fields_madt_gic[] = { > FIELD_UINT(" Reserved", fwts_acpi_madt_gic, reserved), > FIELD_UINT(" GIC ID", fwts_acpi_madt_gic, gic_id), > @@ -954,12 +954,17 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > FIELD_UINT(" Perf. Int. GSIV", fwts_acpi_madt_gic, performance_interrupt_gsiv), > FIELD_UINT(" Parked Address", fwts_acpi_madt_gic, parked_address), > FIELD_UINT(" Phys. Base. Addr",fwts_acpi_madt_gic, physical_base_address), > + FIELD_UINT(" GICV", fwts_acpi_madt_gic, gicv), > + FIELD_UINT(" GICH", fwts_acpi_madt_gic, gich), > + FIELD_UINT(" VGIC Interrupt", fwts_acpi_madt_gic, vgic), > + FIELD_UINT(" GICR Base. Addr", fwts_acpi_madt_gic, gicr_base_address), > + FIELD_UINT(" MPIDR", fwts_acpi_madt_gic, mpidr), > }; > __acpi_dump_table_fields(fw, data, fields_madt_gic, offset); > - skip = (sizeof(fwts_acpi_madt_gic)); > + skip = sizeof(fwts_acpi_madt_gic); > } > break; > - case 12: { > + case FWTS_ACPI_MADT_GIC_D_GOC_DISTRIBUTOR: { > static const fwts_acpidump_field fields_madt_gicd[] = { > FIELD_UINT(" Reserved", fwts_acpi_madt_gicd, reserved), > FIELD_UINT(" GIC ID", fwts_acpi_madt_gicd, gic_id), > @@ -968,7 +973,31 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > FIELD_UINT(" Reserved", fwts_acpi_madt_gicd, reserved2), > }; > __acpi_dump_table_fields(fw, data, fields_madt_gicd, offset); > - skip = (sizeof(fwts_acpi_madt_gicd)); > + skip = sizeof(fwts_acpi_madt_gicd); > + } > + break; > + case FWTS_ACPI_MADT_GIC_V2M_MSI_FRAME: { > + static const fwts_acpidump_field fields_madt_gic_msi[] = { > + FIELD_UINT(" Reserved", fwts_acpi_madt_gic_msi, reserved), > + FIELD_UINT(" Frame ID", fwts_acpi_madt_gic_msi, frame_id), > + FIELD_UINT(" Phys. Base. Addr",fwts_acpi_madt_gic_msi, physical_base_address), > + FIELD_UINT(" Flags", fwts_acpi_madt_gic_msi, flags), > + FIELD_UINT(" SPI Count", fwts_acpi_madt_gic_msi, spi_count), > + FIELD_UINT(" SPI Base", fwts_acpi_madt_gic_msi, spi_base), > + FIELD_UINT(" SPI Flags", fwts_acpi_madt_gic_msi, spi_flags), > + }; > + __acpi_dump_table_fields(fw, data, fields_madt_gic_msi, offset); > + skip = sizeof(fwts_acpi_madt_gic_msi); > + } > + break; > + case FWTS_ACPI_MADT_GIC_R_REDISTRIBUTOR: { > + static const fwts_acpidump_field fields_madt_gicr[] = { > + FIELD_UINT(" Reserved", fwts_acpi_madt_gicr, reserved), > + FIELD_UINT(" Disc. Base Addr", fwts_acpi_madt_gicr, discovery_range_base_address), > + FIELD_UINT(" Disc. Range Len", fwts_acpi_madt_gicr, discovery_range_length), > + }; > + __acpi_dump_table_fields(fw, data, fields_madt_gicr, offset); > + skip = sizeof(fwts_acpi_madt_gicr); > } > break; > default: > diff --git a/src/acpi/acpitables/acpitables.c b/src/acpi/acpitables/acpitables.c > index 46cd3bf..255261c 100644 > --- a/src/acpi/acpitables/acpitables.c > +++ b/src/acpi/acpitables/acpitables.c > @@ -309,10 +309,13 @@ static void acpi_table_check_xsdt(fwts_framework *fw, fwts_acpi_table_info *tabl > static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *table) > { > fwts_acpi_table_madt *madt = (fwts_acpi_table_madt*)table->data; > + fwts_list msi_frame_ids; > const uint8_t *data = table->data; > size_t length = table->length; > int i = 0; > > + fwts_list_init(&msi_frame_ids); > + > if (madt->flags & 0xfffffffe) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTFlagsNonZero", > "MADT flags field, bits 1..31 are reserved and " > @@ -331,7 +334,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > length -= sizeof(fwts_acpi_madt_sub_table_header); > > switch (hdr->type) { > - case 0: { > + case FWTS_ACPI_MADT_LOCAL_APIC: { > fwts_acpi_madt_processor_local_apic *lapic = (fwts_acpi_madt_processor_local_apic *)data; > if (lapic->flags & 0xfffffffe) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTAPICFlagsNonZero", > @@ -341,7 +344,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > skip = sizeof(fwts_acpi_madt_processor_local_apic); > } > break; > - case 1: { > + case FWTS_ACPI_MADT_IO_APIC: { > fwts_acpi_madt_io_apic *ioapic = (fwts_acpi_madt_io_apic*)data; > if (ioapic->io_apic_phys_address == 0) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTIOAPICAddrZero", "MADT IO APIC address is zero, appears not to be defined."); > @@ -352,7 +355,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > skip = sizeof(fwts_acpi_madt_io_apic); > } > break; > - case 2: { > + case FWTS_ACPI_MADT_INTERRUPT_OVERRIDE: { > fwts_acpi_madt_interrupt_override *int_override = (fwts_acpi_madt_interrupt_override*)data; > if (int_override->bus != 0) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTIRQSrcISA", "MADT Interrupt Source Override Bus should be 0 for ISA bus."); > @@ -364,7 +367,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > skip = sizeof(fwts_acpi_madt_interrupt_override); > } > break; > - case 3: { > + case FWTS_ACPI_MADT_NMI_SOURCE: { > fwts_acpi_madt_nmi *nmi = (fwts_acpi_madt_nmi*)data; > if (nmi->flags & 0xfffffff0) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTNMISrcFlags", > @@ -374,7 +377,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > skip = sizeof(fwts_acpi_madt_nmi); > } > break; > - case 4: { > + case FWTS_ACPI_MADT_LOCAL_APIC_NMI: { > fwts_acpi_madt_local_apic_nmi *nmi = (fwts_acpi_madt_local_apic_nmi*)data; > if (nmi->flags & 0xfffffff0) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTLAPICNMIFlags", > @@ -384,22 +387,22 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > skip = sizeof(fwts_acpi_madt_local_apic_nmi); > } > break; > - case 5: > + case FWTS_ACPI_MADT_LOCAL_APIC_OVERRIDE: > skip = sizeof(fwts_acpi_madt_local_apic_addr_override); > break; > - case 6: { > + case FWTS_ACPI_MADT_IO_SAPIC: { > fwts_acpi_madt_io_sapic *sapic = (fwts_acpi_madt_io_sapic*)data; > if (sapic->address == 0) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADIOSPAICAddrZero", "MADT I/O SAPIC address is zero, appears not to be defined."); > skip = sizeof(fwts_acpi_madt_io_sapic); > } > break; > - case 7: { > + case FWTS_ACPI_MADT_LOCAL_SAPIC: { > fwts_acpi_madt_local_sapic *local_sapic = (fwts_acpi_madt_local_sapic*)data; > skip = sizeof(fwts_acpi_madt_local_sapic) + strlen(local_sapic->uid_string) + 1; > } > break; > - case 8: { > + case FWTS_ACPI_MADT_INTERRUPT_SOURCE: { > fwts_acpi_madt_platform_int_source *src = (fwts_acpi_madt_platform_int_source*)data; > if (src->flags & 0xfffffff0) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTPlatIRQSrcFlags", > @@ -421,10 +424,10 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > skip = (sizeof(fwts_acpi_madt_platform_int_source)); > } > break; > - case 9: > + case FWTS_ACPI_MADT_LOCAL_X2APIC: > skip = (sizeof(fwts_acpi_madt_local_x2apic)); > break; > - case 10: { > + case FWTS_ACPI_MADT_LOCAL_X2APIC_NMI: { > fwts_acpi_madt_local_x2apic_nmi *nmi = (fwts_acpi_madt_local_x2apic_nmi*)data; > if (nmi->flags & 0xfffffff0) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTLAPICX2APICNMIFlags", > @@ -434,21 +437,80 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > skip = (sizeof(fwts_acpi_madt_local_x2apic_nmi)); > } > break; > - case 11: { > + case FWTS_ACPI_MADT_GIC_C_CPU_INTERFACE: { > fwts_acpi_madt_gic *gic = (fwts_acpi_madt_gic*)data; > > + if (gic->reserved) > + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICCReservedNonZero", > + "MADT GIC C Structure reserved field should be zero, " > + "instead got 0x%" PRIx32 ".", gic->reserved); > + > if (gic->flags & 0xfffffffc) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTGICFLags", > "MADT GIC, flags, bits 2..31 are reserved " > "and should be zero, but are set as: %" PRIx32 ".", > - gic->flags); > + gic->flags & 0xfffffffc); > + > skip = sizeof(fwts_acpi_madt_gic); > } > break; > - case 12: > - /* Not much to sanity check */ > + case FWTS_ACPI_MADT_GIC_D_GOC_DISTRIBUTOR: { > + fwts_acpi_madt_gicd *gicd = (fwts_acpi_madt_gicd*)data; > + > + if (gicd->reserved) > + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICDReservedNonZero", > + "MADT GIC Distributor Structure reserved field should be zero, " > + "instead got 0x%" PRIx32 ".", gicd->reserved); > + if (gicd->reserved2) > + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICDReserved2NonZero", > + "MADT GIC Distributor Structure second reserved field should be zero, " > + "instead got 0x%" PRIx32 ".", gicd->reserved2); > + } > skip = sizeof(fwts_acpi_madt_gicd); > break; > + case FWTS_ACPI_MADT_GIC_V2M_MSI_FRAME: { > + fwts_acpi_madt_gic_msi *gic_msi = (fwts_acpi_madt_gic_msi*)data; > + fwts_list_link *item; > + > + if (gic_msi->reserved) > + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICMSIReservedNonZero", > + "MADT GIC MSI Structure reserved field should be zero, " > + "instead got 0x%" PRIx32 ".", gic_msi->reserved); > + > + if (gic_msi->flags & 0xfffffffe) { > + fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTGICMSIFLags", > + "MADT GIC MSI Frame, flags, bits 1..31 are reserved " > + "and should be zero, but are set as: %" PRIx32 ".", > + gic_msi->flags); > + } > + > + /* Check against previously IDs to see if unique */ > + fwts_list_foreach(item, &msi_frame_ids) { > + uint32_t *frame_id = fwts_list_data(uint32_t *, item); > + > + /* Frame ID must be unique according to the spec */ > + if (*frame_id == gic_msi->frame_id) { > + fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTGICMSINonUniqueFrameId", > + "MADT GIC MSI Frame ID 0x%" PRIx32 " is not unique " > + "and has already be defined in a previous GIC MSI " > + "Frame.", gic_msi->frame_id); > + } else { > + fwts_list_append(&msi_frame_ids, &(gic_msi->frame_id)); > + } > + } > + } > + skip = sizeof(fwts_acpi_madt_gic_msi); > + break; > + case FWTS_ACPI_MADT_GIC_R_REDISTRIBUTOR: { > + fwts_acpi_madt_gicr *gicr = (fwts_acpi_madt_gicr*)data; > + > + if (gicr->reserved) > + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICRReservedNonZero", > + "MADT GIC Redistributor Structure reserved field should be zero, " > + "instead got 0x%" PRIx32 ".", gicr->reserved); > + } > + skip = sizeof(fwts_acpi_madt_gicr); > + break; > default: > skip = 0; > break; > @@ -456,6 +518,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > data += skip; > length -= skip; > } > + fwts_list_free_items(&msi_frame_ids, NULL); > } > > static void acpi_table_check_mcfg(fwts_framework *fw, fwts_acpi_table_info *table) > diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h > index 1ea0daf..ceb6507 100644 > --- a/src/lib/include/fwts_acpi.h > +++ b/src/lib/include/fwts_acpi.h > @@ -333,15 +333,21 @@ typedef enum { > FWTS_ACPI_MADT_INTERRUPT_SOURCE, > FWTS_ACPI_MADT_LOCAL_X2APIC, > FWTS_ACPI_MADT_LOCAL_X2APIC_NMI, > + FWTS_ACPI_MADT_GIC_C_CPU_INTERFACE, > + FWTS_ACPI_MADT_GIC_D_GOC_DISTRIBUTOR, > + FWTS_ACPI_MADT_GIC_V2M_MSI_FRAME, > + FWTS_ACPI_MADT_GIC_R_REDISTRIBUTOR, > FWTS_ACPI_MADT_RESERVED > } fwts_acpi_madt_type; > > +/* Type 0, FWTS_ACPI_MADT_LOCAL_APIC */ > typedef struct { > uint8_t acpi_processor_id; > uint8_t apic_id; > uint32_t flags; > } __attribute__ ((packed)) fwts_acpi_madt_processor_local_apic; > > +/* Type 1, FWTS_ACPI_MADT_IO_APIC */ > typedef struct { > uint8_t io_apic_id; > uint8_t reserved; > @@ -349,6 +355,7 @@ typedef struct { > uint32_t global_irq_base; > } __attribute__ ((packed)) fwts_acpi_madt_io_apic; > > +/* Type 2, FWTS_ACPI_MADT_INTERRUPT_OVERRIDE */ > typedef struct { > uint8_t bus; > uint8_t source; > @@ -356,22 +363,26 @@ typedef struct { > uint16_t flags; > } __attribute__ ((packed)) fwts_acpi_madt_interrupt_override; > > +/* Type 3, FWTS_ACPI_MADT_NMI_SOURCE */ > typedef struct { > uint16_t flags; > uint32_t gsi; > } __attribute__ ((packed)) fwts_acpi_madt_nmi; > > +/* Type 4, FWTS_ACPI_MADT_LOCAL_APIC_NMI */ > typedef struct { > uint8_t acpi_processor_id; > uint16_t flags; > uint8_t local_apic_lint; > } __attribute__ ((packed)) fwts_acpi_madt_local_apic_nmi; > > +/* Type 5, FWTS_ACPI_MADT_LOCAL_APIC_OVERRIDE */ > typedef struct { > uint16_t reserved; > uint64_t address; > } __attribute__ ((packed)) fwts_acpi_madt_local_apic_addr_override; > > +/* Type 6, FWTS_ACPI_MADT_IO_SAPIC */ > typedef struct { > uint8_t io_sapic_id; > uint8_t reserved; > @@ -379,6 +390,7 @@ typedef struct { > uint64_t address; > } __attribute__ ((packed)) fwts_acpi_madt_io_sapic; > > +/* Type 7, FWTS_ACPI_MADT_LOCAL_SAPIC */ > typedef struct { > uint8_t acpi_processor_id; > uint8_t local_sapic_id; > @@ -389,6 +401,7 @@ typedef struct { > char uid_string[0]; > } __attribute__ ((packed)) fwts_acpi_madt_local_sapic; > > +/* Type 8, FWTS_ACPI_MADT_INTERRUPT_SOURCE */ > typedef struct { > uint16_t flags; > uint8_t type; > @@ -399,6 +412,7 @@ typedef struct { > uint32_t pis_flags; > } __attribute__ ((packed)) fwts_acpi_madt_platform_int_source; > > +/* Type 9, FWTS_ACPI_MADT_LOCAL_X2APIC */ > typedef struct { > uint16_t reserved; > uint32_t x2apic_id; > @@ -406,6 +420,7 @@ typedef struct { > uint32_t processor_uid; > } __attribute__ ((packed)) fwts_acpi_madt_local_x2apic; > > +/* Type 10, FWTS_ACPI_MADT_LOCAL_X2APIC_NMI */ > typedef struct { > uint16_t flags; > uint32_t processor_uid; > @@ -413,9 +428,10 @@ typedef struct { > uint8_t reserved[3]; > } __attribute__ ((packed)) fwts_acpi_madt_local_x2apic_nmi; > > +/* Type 11, FWTS_ACPI_MADT_GIC_C_CPU_INTERFACE */ > /* New in ACPI 5.0, GIC, section 5.2.12.14 */ > typedef struct { > - uint8_t reserved[2]; > + uint16_t reserved; > uint32_t gic_id; > uint32_t processor_uid; > uint32_t flags; > @@ -423,17 +439,43 @@ typedef struct { > uint32_t performance_interrupt_gsiv; > uint64_t parked_address; > uint64_t physical_base_address; > + uint64_t gicv; > + uint64_t gich; > + uint32_t vgic; > + uint64_t gicr_base_address; > + uint64_t mpidr; > } __attribute__ ((packed)) fwts_acpi_madt_gic; > > /* New in ACPI 5.0, GICD, section 5.2.12.15 */ > +/* Type 12, FWTS_ACPI_MADT_GIC_D_GOC_DISTRIBUTOR */ > typedef struct { > - uint8_t reserved[2]; > + uint16_t reserved; > uint32_t gic_id; > uint64_t physical_base_address; > uint32_t system_vector_base; > uint32_t reserved2; > } __attribute__ ((packed)) fwts_acpi_madt_gicd; > > +/* New in ACPI 5.1, GIC MSI Frame structure, 5.2.12.16 */ > +/* Type 13, FWTS_ACPI_MADT_GIC_V2M_MSI_FRAME */ > +typedef struct { > + uint16_t reserved; > + uint32_t frame_id; > + uint64_t physical_base_address; > + uint32_t flags; > + uint16_t spi_count; > + uint16_t spi_base; > + uint32_t spi_flags; /* bit 0 just used at the moment */ > +} __attribute__ ((packed)) fwts_acpi_madt_gic_msi; > + > +/* New in ACPI 5.1, GICR structure, 5.2.12.17 */ > +/* Type 14, FWTS_ACPI_MADT_GIC_R_REDISTRIBUTOR */ > +typedef struct { > + uint16_t reserved; > + uint64_t discovery_range_base_address; > + uint32_t discovery_range_length; > +} __attribute__ ((packed)) fwts_acpi_madt_gicr; > + > /* From http://www.kuro5hin.org/story/2002/10/27/16622/530, > and also http://www.cl.cam.ac.uk/~rja14/tcpa-faq.html */ > typedef struct { > Acked-by: Alex Hung <alex.hung@canonical.com>
On 07/25/2014 07:05 PM, Colin King wrote: > From: Colin Ian King <colin.king@canonical.com> > > ACPI 5.1 sections 5.2.12.14 to 5.2.12.17 describe new MADT > structures, so add these structures to fwts and update the acpidump > and acpitables tests accordingly. > > Signed-off-by: Colin Ian King <colin.king@canonical.com> > --- > src/acpi/acpidump/acpidump.c | 65 ++++++++++++++++++++-------- > src/acpi/acpitables/acpitables.c | 93 +++++++++++++++++++++++++++++++++------- > src/lib/include/fwts_acpi.h | 46 +++++++++++++++++++- > 3 files changed, 169 insertions(+), 35 deletions(-) > > diff --git a/src/acpi/acpidump/acpidump.c b/src/acpi/acpidump/acpidump.c > index ee148b0..15a4e5d 100644 > --- a/src/acpi/acpidump/acpidump.c > +++ b/src/acpi/acpidump/acpidump.c > @@ -813,7 +813,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > offset += sizeof(fwts_acpi_madt_sub_table_header); > > switch (hdr->type) { > - case 0: { > + case FWTS_ACPI_MADT_LOCAL_APIC: { > static const fwts_acpidump_field fields_processor_local_apic[] = { > FIELD_UINT(" ACPI CPU ID", fwts_acpi_madt_processor_local_apic, acpi_processor_id), > FIELD_UINT(" APIC ID", fwts_acpi_madt_processor_local_apic, apic_id), > @@ -825,7 +825,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > skip = sizeof(fwts_acpi_madt_processor_local_apic); > } > break; > - case 1: { > + case FWTS_ACPI_MADT_IO_APIC: { > static const fwts_acpidump_field fields_io_apic[] = { > FIELD_UINT(" I/O APIC ID", fwts_acpi_madt_io_apic, io_apic_id), > FIELD_UINT(" I/O APIC Addr", fwts_acpi_madt_io_apic, io_apic_phys_address), > @@ -836,7 +836,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > skip = sizeof(fwts_acpi_madt_io_apic); > } > break; > - case 2: { > + case FWTS_ACPI_MADT_INTERRUPT_OVERRIDE: { > static const fwts_acpidump_field fields_madt_interrupt_override[] = { > FIELD_UINT(" Bus", fwts_acpi_madt_interrupt_override, bus), > FIELD_UINT(" Source", fwts_acpi_madt_interrupt_override, source), > @@ -850,7 +850,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > skip = sizeof(fwts_acpi_madt_interrupt_override); > } > break; > - case 3: { > + case FWTS_ACPI_MADT_NMI_SOURCE: { > static const fwts_acpidump_field fields_madt_nmi[] = { > FIELD_UINT(" Flags", fwts_acpi_madt_nmi, flags), > FIELD_UINT(" Gbl Sys Int", fwts_acpi_madt_nmi, gsi), > @@ -860,7 +860,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > skip = sizeof(fwts_acpi_madt_nmi); > } > break; > - case 4: { > + case FWTS_ACPI_MADT_LOCAL_APIC_NMI: { > static const fwts_acpidump_field fields_madt_local_apic_nmi[] = { > FIELD_UINT(" ACPI CPU ID", fwts_acpi_madt_local_apic_nmi, acpi_processor_id), > FIELD_UINT(" Flags", fwts_acpi_madt_local_apic_nmi, flags), > @@ -871,7 +871,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > skip = sizeof(fwts_acpi_madt_local_apic_nmi); > } > break; > - case 5: { > + case FWTS_ACPI_MADT_LOCAL_APIC_OVERRIDE: { > static const fwts_acpidump_field fields_madt_local_apic_addr_override[] = { > FIELD_UINT(" Local APIC Addr", fwts_acpi_madt_local_apic_addr_override, address), > FIELD_END > @@ -880,7 +880,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > skip = sizeof(fwts_acpi_madt_local_apic_addr_override); > } > break; > - case 6: { > + case FWTS_ACPI_MADT_IO_SAPIC: { > static const fwts_acpidump_field fields_madt_io_sapic[] = { > FIELD_UINT(" I/O SAPIC ID", fwts_acpi_madt_io_sapic, io_sapic_id), > FIELD_UINT(" Gbl Sys Int", fwts_acpi_madt_io_sapic, gsi), > @@ -891,7 +891,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > skip = sizeof(fwts_acpi_madt_io_sapic); > } > break; > - case 7: { > + case FWTS_ACPI_MADT_LOCAL_SAPIC: { > fwts_acpi_madt_local_sapic *local_sapic = (fwts_acpi_madt_local_sapic *)data; > static const fwts_acpidump_field fields_madt_local_sapic[] = { > FIELD_UINT(" ACPI CPU ID", fwts_acpi_madt_local_sapic, acpi_processor_id), > @@ -907,7 +907,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > strlen(local_sapic->uid_string) + 1); > } > break; > - case 8: { > + case FWTS_ACPI_MADT_INTERRUPT_SOURCE: { > static const fwts_acpidump_field fields_madt_local_sapic[] = { > FIELD_UINT(" Flags", fwts_acpi_madt_platform_int_source, flags), > FIELD_UINT(" Type", fwts_acpi_madt_platform_int_source, type), > @@ -919,10 +919,10 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > FIELD_END > }; > __acpi_dump_table_fields(fw, data, fields_madt_local_sapic, offset); > - skip = (sizeof(fwts_acpi_madt_platform_int_source)); > + skip = sizeof(fwts_acpi_madt_platform_int_source); > } > break; > - case 9: { > + case FWTS_ACPI_MADT_LOCAL_X2APIC: { > static const fwts_acpidump_field fields_madt_local_x2apic[] = { > FIELD_UINT(" x2APIC ID", fwts_acpi_madt_local_x2apic, x2apic_id), > FIELD_UINT(" Flags", fwts_acpi_madt_local_x2apic, flags), > @@ -930,10 +930,10 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > FIELD_END > }; > __acpi_dump_table_fields(fw, data, fields_madt_local_x2apic, offset); > - skip = (sizeof(fwts_acpi_madt_local_x2apic)); > + skip = sizeof(fwts_acpi_madt_local_x2apic); > } > break; > - case 10: { > + case FWTS_ACPI_MADT_LOCAL_X2APIC_NMI: { > static const fwts_acpidump_field fields_madt_local_x2apic_nmi[] = { > FIELD_UINT(" Flags", fwts_acpi_madt_local_x2apic_nmi, flags), > FIELD_UINT(" Processor UID", fwts_acpi_madt_local_x2apic_nmi, processor_uid), > @@ -941,10 +941,10 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > FIELD_END > }; > __acpi_dump_table_fields(fw, data, fields_madt_local_x2apic_nmi, offset); > - skip = (sizeof(fwts_acpi_madt_local_x2apic_nmi)); > + skip = sizeof(fwts_acpi_madt_local_x2apic_nmi); > } > break; > - case 11: { > + case FWTS_ACPI_MADT_GIC_C_CPU_INTERFACE: { > static const fwts_acpidump_field fields_madt_gic[] = { > FIELD_UINT(" Reserved", fwts_acpi_madt_gic, reserved), > FIELD_UINT(" GIC ID", fwts_acpi_madt_gic, gic_id), > @@ -954,12 +954,17 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > FIELD_UINT(" Perf. Int. GSIV", fwts_acpi_madt_gic, performance_interrupt_gsiv), > FIELD_UINT(" Parked Address", fwts_acpi_madt_gic, parked_address), > FIELD_UINT(" Phys. Base. Addr",fwts_acpi_madt_gic, physical_base_address), > + FIELD_UINT(" GICV", fwts_acpi_madt_gic, gicv), > + FIELD_UINT(" GICH", fwts_acpi_madt_gic, gich), > + FIELD_UINT(" VGIC Interrupt", fwts_acpi_madt_gic, vgic), > + FIELD_UINT(" GICR Base. Addr", fwts_acpi_madt_gic, gicr_base_address), > + FIELD_UINT(" MPIDR", fwts_acpi_madt_gic, mpidr), > }; > __acpi_dump_table_fields(fw, data, fields_madt_gic, offset); > - skip = (sizeof(fwts_acpi_madt_gic)); > + skip = sizeof(fwts_acpi_madt_gic); > } > break; > - case 12: { > + case FWTS_ACPI_MADT_GIC_D_GOC_DISTRIBUTOR: { > static const fwts_acpidump_field fields_madt_gicd[] = { > FIELD_UINT(" Reserved", fwts_acpi_madt_gicd, reserved), > FIELD_UINT(" GIC ID", fwts_acpi_madt_gicd, gic_id), > @@ -968,7 +973,31 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) > FIELD_UINT(" Reserved", fwts_acpi_madt_gicd, reserved2), > }; > __acpi_dump_table_fields(fw, data, fields_madt_gicd, offset); > - skip = (sizeof(fwts_acpi_madt_gicd)); > + skip = sizeof(fwts_acpi_madt_gicd); > + } > + break; > + case FWTS_ACPI_MADT_GIC_V2M_MSI_FRAME: { > + static const fwts_acpidump_field fields_madt_gic_msi[] = { > + FIELD_UINT(" Reserved", fwts_acpi_madt_gic_msi, reserved), > + FIELD_UINT(" Frame ID", fwts_acpi_madt_gic_msi, frame_id), > + FIELD_UINT(" Phys. Base. Addr",fwts_acpi_madt_gic_msi, physical_base_address), > + FIELD_UINT(" Flags", fwts_acpi_madt_gic_msi, flags), > + FIELD_UINT(" SPI Count", fwts_acpi_madt_gic_msi, spi_count), > + FIELD_UINT(" SPI Base", fwts_acpi_madt_gic_msi, spi_base), > + FIELD_UINT(" SPI Flags", fwts_acpi_madt_gic_msi, spi_flags), > + }; > + __acpi_dump_table_fields(fw, data, fields_madt_gic_msi, offset); > + skip = sizeof(fwts_acpi_madt_gic_msi); > + } > + break; > + case FWTS_ACPI_MADT_GIC_R_REDISTRIBUTOR: { > + static const fwts_acpidump_field fields_madt_gicr[] = { > + FIELD_UINT(" Reserved", fwts_acpi_madt_gicr, reserved), > + FIELD_UINT(" Disc. Base Addr", fwts_acpi_madt_gicr, discovery_range_base_address), > + FIELD_UINT(" Disc. Range Len", fwts_acpi_madt_gicr, discovery_range_length), > + }; > + __acpi_dump_table_fields(fw, data, fields_madt_gicr, offset); > + skip = sizeof(fwts_acpi_madt_gicr); > } > break; > default: > diff --git a/src/acpi/acpitables/acpitables.c b/src/acpi/acpitables/acpitables.c > index 46cd3bf..255261c 100644 > --- a/src/acpi/acpitables/acpitables.c > +++ b/src/acpi/acpitables/acpitables.c > @@ -309,10 +309,13 @@ static void acpi_table_check_xsdt(fwts_framework *fw, fwts_acpi_table_info *tabl > static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *table) > { > fwts_acpi_table_madt *madt = (fwts_acpi_table_madt*)table->data; > + fwts_list msi_frame_ids; > const uint8_t *data = table->data; > size_t length = table->length; > int i = 0; > > + fwts_list_init(&msi_frame_ids); > + > if (madt->flags & 0xfffffffe) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTFlagsNonZero", > "MADT flags field, bits 1..31 are reserved and " > @@ -331,7 +334,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > length -= sizeof(fwts_acpi_madt_sub_table_header); > > switch (hdr->type) { > - case 0: { > + case FWTS_ACPI_MADT_LOCAL_APIC: { > fwts_acpi_madt_processor_local_apic *lapic = (fwts_acpi_madt_processor_local_apic *)data; > if (lapic->flags & 0xfffffffe) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTAPICFlagsNonZero", > @@ -341,7 +344,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > skip = sizeof(fwts_acpi_madt_processor_local_apic); > } > break; > - case 1: { > + case FWTS_ACPI_MADT_IO_APIC: { > fwts_acpi_madt_io_apic *ioapic = (fwts_acpi_madt_io_apic*)data; > if (ioapic->io_apic_phys_address == 0) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTIOAPICAddrZero", "MADT IO APIC address is zero, appears not to be defined."); > @@ -352,7 +355,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > skip = sizeof(fwts_acpi_madt_io_apic); > } > break; > - case 2: { > + case FWTS_ACPI_MADT_INTERRUPT_OVERRIDE: { > fwts_acpi_madt_interrupt_override *int_override = (fwts_acpi_madt_interrupt_override*)data; > if (int_override->bus != 0) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTIRQSrcISA", "MADT Interrupt Source Override Bus should be 0 for ISA bus."); > @@ -364,7 +367,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > skip = sizeof(fwts_acpi_madt_interrupt_override); > } > break; > - case 3: { > + case FWTS_ACPI_MADT_NMI_SOURCE: { > fwts_acpi_madt_nmi *nmi = (fwts_acpi_madt_nmi*)data; > if (nmi->flags & 0xfffffff0) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTNMISrcFlags", > @@ -374,7 +377,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > skip = sizeof(fwts_acpi_madt_nmi); > } > break; > - case 4: { > + case FWTS_ACPI_MADT_LOCAL_APIC_NMI: { > fwts_acpi_madt_local_apic_nmi *nmi = (fwts_acpi_madt_local_apic_nmi*)data; > if (nmi->flags & 0xfffffff0) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTLAPICNMIFlags", > @@ -384,22 +387,22 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > skip = sizeof(fwts_acpi_madt_local_apic_nmi); > } > break; > - case 5: > + case FWTS_ACPI_MADT_LOCAL_APIC_OVERRIDE: > skip = sizeof(fwts_acpi_madt_local_apic_addr_override); > break; > - case 6: { > + case FWTS_ACPI_MADT_IO_SAPIC: { > fwts_acpi_madt_io_sapic *sapic = (fwts_acpi_madt_io_sapic*)data; > if (sapic->address == 0) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADIOSPAICAddrZero", "MADT I/O SAPIC address is zero, appears not to be defined."); > skip = sizeof(fwts_acpi_madt_io_sapic); > } > break; > - case 7: { > + case FWTS_ACPI_MADT_LOCAL_SAPIC: { > fwts_acpi_madt_local_sapic *local_sapic = (fwts_acpi_madt_local_sapic*)data; > skip = sizeof(fwts_acpi_madt_local_sapic) + strlen(local_sapic->uid_string) + 1; > } > break; > - case 8: { > + case FWTS_ACPI_MADT_INTERRUPT_SOURCE: { > fwts_acpi_madt_platform_int_source *src = (fwts_acpi_madt_platform_int_source*)data; > if (src->flags & 0xfffffff0) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTPlatIRQSrcFlags", > @@ -421,10 +424,10 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > skip = (sizeof(fwts_acpi_madt_platform_int_source)); > } > break; > - case 9: > + case FWTS_ACPI_MADT_LOCAL_X2APIC: > skip = (sizeof(fwts_acpi_madt_local_x2apic)); > break; > - case 10: { > + case FWTS_ACPI_MADT_LOCAL_X2APIC_NMI: { > fwts_acpi_madt_local_x2apic_nmi *nmi = (fwts_acpi_madt_local_x2apic_nmi*)data; > if (nmi->flags & 0xfffffff0) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTLAPICX2APICNMIFlags", > @@ -434,21 +437,80 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > skip = (sizeof(fwts_acpi_madt_local_x2apic_nmi)); > } > break; > - case 11: { > + case FWTS_ACPI_MADT_GIC_C_CPU_INTERFACE: { > fwts_acpi_madt_gic *gic = (fwts_acpi_madt_gic*)data; > > + if (gic->reserved) > + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICCReservedNonZero", > + "MADT GIC C Structure reserved field should be zero, " > + "instead got 0x%" PRIx32 ".", gic->reserved); > + > if (gic->flags & 0xfffffffc) > fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTGICFLags", > "MADT GIC, flags, bits 2..31 are reserved " > "and should be zero, but are set as: %" PRIx32 ".", > - gic->flags); > + gic->flags & 0xfffffffc); > + > skip = sizeof(fwts_acpi_madt_gic); > } > break; > - case 12: > - /* Not much to sanity check */ > + case FWTS_ACPI_MADT_GIC_D_GOC_DISTRIBUTOR: { > + fwts_acpi_madt_gicd *gicd = (fwts_acpi_madt_gicd*)data; > + > + if (gicd->reserved) > + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICDReservedNonZero", > + "MADT GIC Distributor Structure reserved field should be zero, " > + "instead got 0x%" PRIx32 ".", gicd->reserved); > + if (gicd->reserved2) > + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICDReserved2NonZero", > + "MADT GIC Distributor Structure second reserved field should be zero, " > + "instead got 0x%" PRIx32 ".", gicd->reserved2); > + } > skip = sizeof(fwts_acpi_madt_gicd); > break; > + case FWTS_ACPI_MADT_GIC_V2M_MSI_FRAME: { > + fwts_acpi_madt_gic_msi *gic_msi = (fwts_acpi_madt_gic_msi*)data; > + fwts_list_link *item; > + > + if (gic_msi->reserved) > + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICMSIReservedNonZero", > + "MADT GIC MSI Structure reserved field should be zero, " > + "instead got 0x%" PRIx32 ".", gic_msi->reserved); > + > + if (gic_msi->flags & 0xfffffffe) { > + fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTGICMSIFLags", > + "MADT GIC MSI Frame, flags, bits 1..31 are reserved " > + "and should be zero, but are set as: %" PRIx32 ".", > + gic_msi->flags); > + } > + > + /* Check against previously IDs to see if unique */ > + fwts_list_foreach(item, &msi_frame_ids) { > + uint32_t *frame_id = fwts_list_data(uint32_t *, item); > + > + /* Frame ID must be unique according to the spec */ > + if (*frame_id == gic_msi->frame_id) { > + fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTGICMSINonUniqueFrameId", > + "MADT GIC MSI Frame ID 0x%" PRIx32 " is not unique " > + "and has already be defined in a previous GIC MSI " > + "Frame.", gic_msi->frame_id); > + } else { > + fwts_list_append(&msi_frame_ids, &(gic_msi->frame_id)); > + } > + } > + } > + skip = sizeof(fwts_acpi_madt_gic_msi); > + break; > + case FWTS_ACPI_MADT_GIC_R_REDISTRIBUTOR: { > + fwts_acpi_madt_gicr *gicr = (fwts_acpi_madt_gicr*)data; > + > + if (gicr->reserved) > + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICRReservedNonZero", > + "MADT GIC Redistributor Structure reserved field should be zero, " > + "instead got 0x%" PRIx32 ".", gicr->reserved); > + } > + skip = sizeof(fwts_acpi_madt_gicr); > + break; > default: > skip = 0; > break; > @@ -456,6 +518,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl > data += skip; > length -= skip; > } > + fwts_list_free_items(&msi_frame_ids, NULL); > } > > static void acpi_table_check_mcfg(fwts_framework *fw, fwts_acpi_table_info *table) > diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h > index 1ea0daf..ceb6507 100644 > --- a/src/lib/include/fwts_acpi.h > +++ b/src/lib/include/fwts_acpi.h > @@ -333,15 +333,21 @@ typedef enum { > FWTS_ACPI_MADT_INTERRUPT_SOURCE, > FWTS_ACPI_MADT_LOCAL_X2APIC, > FWTS_ACPI_MADT_LOCAL_X2APIC_NMI, > + FWTS_ACPI_MADT_GIC_C_CPU_INTERFACE, > + FWTS_ACPI_MADT_GIC_D_GOC_DISTRIBUTOR, > + FWTS_ACPI_MADT_GIC_V2M_MSI_FRAME, > + FWTS_ACPI_MADT_GIC_R_REDISTRIBUTOR, > FWTS_ACPI_MADT_RESERVED > } fwts_acpi_madt_type; > > +/* Type 0, FWTS_ACPI_MADT_LOCAL_APIC */ > typedef struct { > uint8_t acpi_processor_id; > uint8_t apic_id; > uint32_t flags; > } __attribute__ ((packed)) fwts_acpi_madt_processor_local_apic; > > +/* Type 1, FWTS_ACPI_MADT_IO_APIC */ > typedef struct { > uint8_t io_apic_id; > uint8_t reserved; > @@ -349,6 +355,7 @@ typedef struct { > uint32_t global_irq_base; > } __attribute__ ((packed)) fwts_acpi_madt_io_apic; > > +/* Type 2, FWTS_ACPI_MADT_INTERRUPT_OVERRIDE */ > typedef struct { > uint8_t bus; > uint8_t source; > @@ -356,22 +363,26 @@ typedef struct { > uint16_t flags; > } __attribute__ ((packed)) fwts_acpi_madt_interrupt_override; > > +/* Type 3, FWTS_ACPI_MADT_NMI_SOURCE */ > typedef struct { > uint16_t flags; > uint32_t gsi; > } __attribute__ ((packed)) fwts_acpi_madt_nmi; > > +/* Type 4, FWTS_ACPI_MADT_LOCAL_APIC_NMI */ > typedef struct { > uint8_t acpi_processor_id; > uint16_t flags; > uint8_t local_apic_lint; > } __attribute__ ((packed)) fwts_acpi_madt_local_apic_nmi; > > +/* Type 5, FWTS_ACPI_MADT_LOCAL_APIC_OVERRIDE */ > typedef struct { > uint16_t reserved; > uint64_t address; > } __attribute__ ((packed)) fwts_acpi_madt_local_apic_addr_override; > > +/* Type 6, FWTS_ACPI_MADT_IO_SAPIC */ > typedef struct { > uint8_t io_sapic_id; > uint8_t reserved; > @@ -379,6 +390,7 @@ typedef struct { > uint64_t address; > } __attribute__ ((packed)) fwts_acpi_madt_io_sapic; > > +/* Type 7, FWTS_ACPI_MADT_LOCAL_SAPIC */ > typedef struct { > uint8_t acpi_processor_id; > uint8_t local_sapic_id; > @@ -389,6 +401,7 @@ typedef struct { > char uid_string[0]; > } __attribute__ ((packed)) fwts_acpi_madt_local_sapic; > > +/* Type 8, FWTS_ACPI_MADT_INTERRUPT_SOURCE */ > typedef struct { > uint16_t flags; > uint8_t type; > @@ -399,6 +412,7 @@ typedef struct { > uint32_t pis_flags; > } __attribute__ ((packed)) fwts_acpi_madt_platform_int_source; > > +/* Type 9, FWTS_ACPI_MADT_LOCAL_X2APIC */ > typedef struct { > uint16_t reserved; > uint32_t x2apic_id; > @@ -406,6 +420,7 @@ typedef struct { > uint32_t processor_uid; > } __attribute__ ((packed)) fwts_acpi_madt_local_x2apic; > > +/* Type 10, FWTS_ACPI_MADT_LOCAL_X2APIC_NMI */ > typedef struct { > uint16_t flags; > uint32_t processor_uid; > @@ -413,9 +428,10 @@ typedef struct { > uint8_t reserved[3]; > } __attribute__ ((packed)) fwts_acpi_madt_local_x2apic_nmi; > > +/* Type 11, FWTS_ACPI_MADT_GIC_C_CPU_INTERFACE */ > /* New in ACPI 5.0, GIC, section 5.2.12.14 */ > typedef struct { > - uint8_t reserved[2]; > + uint16_t reserved; > uint32_t gic_id; > uint32_t processor_uid; > uint32_t flags; > @@ -423,17 +439,43 @@ typedef struct { > uint32_t performance_interrupt_gsiv; > uint64_t parked_address; > uint64_t physical_base_address; > + uint64_t gicv; > + uint64_t gich; > + uint32_t vgic; > + uint64_t gicr_base_address; > + uint64_t mpidr; > } __attribute__ ((packed)) fwts_acpi_madt_gic; > > /* New in ACPI 5.0, GICD, section 5.2.12.15 */ > +/* Type 12, FWTS_ACPI_MADT_GIC_D_GOC_DISTRIBUTOR */ > typedef struct { > - uint8_t reserved[2]; > + uint16_t reserved; > uint32_t gic_id; > uint64_t physical_base_address; > uint32_t system_vector_base; > uint32_t reserved2; > } __attribute__ ((packed)) fwts_acpi_madt_gicd; > > +/* New in ACPI 5.1, GIC MSI Frame structure, 5.2.12.16 */ > +/* Type 13, FWTS_ACPI_MADT_GIC_V2M_MSI_FRAME */ > +typedef struct { > + uint16_t reserved; > + uint32_t frame_id; > + uint64_t physical_base_address; > + uint32_t flags; > + uint16_t spi_count; > + uint16_t spi_base; > + uint32_t spi_flags; /* bit 0 just used at the moment */ > +} __attribute__ ((packed)) fwts_acpi_madt_gic_msi; > + > +/* New in ACPI 5.1, GICR structure, 5.2.12.17 */ > +/* Type 14, FWTS_ACPI_MADT_GIC_R_REDISTRIBUTOR */ > +typedef struct { > + uint16_t reserved; > + uint64_t discovery_range_base_address; > + uint32_t discovery_range_length; > +} __attribute__ ((packed)) fwts_acpi_madt_gicr; > + > /* From http://www.kuro5hin.org/story/2002/10/27/16622/530, > and also http://www.cl.cam.ac.uk/~rja14/tcpa-faq.html */ > typedef struct { > Acked-by: Ivan Hu <ivan.hu@canonical.com>
diff --git a/src/acpi/acpidump/acpidump.c b/src/acpi/acpidump/acpidump.c index ee148b0..15a4e5d 100644 --- a/src/acpi/acpidump/acpidump.c +++ b/src/acpi/acpidump/acpidump.c @@ -813,7 +813,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) offset += sizeof(fwts_acpi_madt_sub_table_header); switch (hdr->type) { - case 0: { + case FWTS_ACPI_MADT_LOCAL_APIC: { static const fwts_acpidump_field fields_processor_local_apic[] = { FIELD_UINT(" ACPI CPU ID", fwts_acpi_madt_processor_local_apic, acpi_processor_id), FIELD_UINT(" APIC ID", fwts_acpi_madt_processor_local_apic, apic_id), @@ -825,7 +825,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) skip = sizeof(fwts_acpi_madt_processor_local_apic); } break; - case 1: { + case FWTS_ACPI_MADT_IO_APIC: { static const fwts_acpidump_field fields_io_apic[] = { FIELD_UINT(" I/O APIC ID", fwts_acpi_madt_io_apic, io_apic_id), FIELD_UINT(" I/O APIC Addr", fwts_acpi_madt_io_apic, io_apic_phys_address), @@ -836,7 +836,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) skip = sizeof(fwts_acpi_madt_io_apic); } break; - case 2: { + case FWTS_ACPI_MADT_INTERRUPT_OVERRIDE: { static const fwts_acpidump_field fields_madt_interrupt_override[] = { FIELD_UINT(" Bus", fwts_acpi_madt_interrupt_override, bus), FIELD_UINT(" Source", fwts_acpi_madt_interrupt_override, source), @@ -850,7 +850,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) skip = sizeof(fwts_acpi_madt_interrupt_override); } break; - case 3: { + case FWTS_ACPI_MADT_NMI_SOURCE: { static const fwts_acpidump_field fields_madt_nmi[] = { FIELD_UINT(" Flags", fwts_acpi_madt_nmi, flags), FIELD_UINT(" Gbl Sys Int", fwts_acpi_madt_nmi, gsi), @@ -860,7 +860,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) skip = sizeof(fwts_acpi_madt_nmi); } break; - case 4: { + case FWTS_ACPI_MADT_LOCAL_APIC_NMI: { static const fwts_acpidump_field fields_madt_local_apic_nmi[] = { FIELD_UINT(" ACPI CPU ID", fwts_acpi_madt_local_apic_nmi, acpi_processor_id), FIELD_UINT(" Flags", fwts_acpi_madt_local_apic_nmi, flags), @@ -871,7 +871,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) skip = sizeof(fwts_acpi_madt_local_apic_nmi); } break; - case 5: { + case FWTS_ACPI_MADT_LOCAL_APIC_OVERRIDE: { static const fwts_acpidump_field fields_madt_local_apic_addr_override[] = { FIELD_UINT(" Local APIC Addr", fwts_acpi_madt_local_apic_addr_override, address), FIELD_END @@ -880,7 +880,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) skip = sizeof(fwts_acpi_madt_local_apic_addr_override); } break; - case 6: { + case FWTS_ACPI_MADT_IO_SAPIC: { static const fwts_acpidump_field fields_madt_io_sapic[] = { FIELD_UINT(" I/O SAPIC ID", fwts_acpi_madt_io_sapic, io_sapic_id), FIELD_UINT(" Gbl Sys Int", fwts_acpi_madt_io_sapic, gsi), @@ -891,7 +891,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) skip = sizeof(fwts_acpi_madt_io_sapic); } break; - case 7: { + case FWTS_ACPI_MADT_LOCAL_SAPIC: { fwts_acpi_madt_local_sapic *local_sapic = (fwts_acpi_madt_local_sapic *)data; static const fwts_acpidump_field fields_madt_local_sapic[] = { FIELD_UINT(" ACPI CPU ID", fwts_acpi_madt_local_sapic, acpi_processor_id), @@ -907,7 +907,7 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) strlen(local_sapic->uid_string) + 1); } break; - case 8: { + case FWTS_ACPI_MADT_INTERRUPT_SOURCE: { static const fwts_acpidump_field fields_madt_local_sapic[] = { FIELD_UINT(" Flags", fwts_acpi_madt_platform_int_source, flags), FIELD_UINT(" Type", fwts_acpi_madt_platform_int_source, type), @@ -919,10 +919,10 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) FIELD_END }; __acpi_dump_table_fields(fw, data, fields_madt_local_sapic, offset); - skip = (sizeof(fwts_acpi_madt_platform_int_source)); + skip = sizeof(fwts_acpi_madt_platform_int_source); } break; - case 9: { + case FWTS_ACPI_MADT_LOCAL_X2APIC: { static const fwts_acpidump_field fields_madt_local_x2apic[] = { FIELD_UINT(" x2APIC ID", fwts_acpi_madt_local_x2apic, x2apic_id), FIELD_UINT(" Flags", fwts_acpi_madt_local_x2apic, flags), @@ -930,10 +930,10 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) FIELD_END }; __acpi_dump_table_fields(fw, data, fields_madt_local_x2apic, offset); - skip = (sizeof(fwts_acpi_madt_local_x2apic)); + skip = sizeof(fwts_acpi_madt_local_x2apic); } break; - case 10: { + case FWTS_ACPI_MADT_LOCAL_X2APIC_NMI: { static const fwts_acpidump_field fields_madt_local_x2apic_nmi[] = { FIELD_UINT(" Flags", fwts_acpi_madt_local_x2apic_nmi, flags), FIELD_UINT(" Processor UID", fwts_acpi_madt_local_x2apic_nmi, processor_uid), @@ -941,10 +941,10 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) FIELD_END }; __acpi_dump_table_fields(fw, data, fields_madt_local_x2apic_nmi, offset); - skip = (sizeof(fwts_acpi_madt_local_x2apic_nmi)); + skip = sizeof(fwts_acpi_madt_local_x2apic_nmi); } break; - case 11: { + case FWTS_ACPI_MADT_GIC_C_CPU_INTERFACE: { static const fwts_acpidump_field fields_madt_gic[] = { FIELD_UINT(" Reserved", fwts_acpi_madt_gic, reserved), FIELD_UINT(" GIC ID", fwts_acpi_madt_gic, gic_id), @@ -954,12 +954,17 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) FIELD_UINT(" Perf. Int. GSIV", fwts_acpi_madt_gic, performance_interrupt_gsiv), FIELD_UINT(" Parked Address", fwts_acpi_madt_gic, parked_address), FIELD_UINT(" Phys. Base. Addr",fwts_acpi_madt_gic, physical_base_address), + FIELD_UINT(" GICV", fwts_acpi_madt_gic, gicv), + FIELD_UINT(" GICH", fwts_acpi_madt_gic, gich), + FIELD_UINT(" VGIC Interrupt", fwts_acpi_madt_gic, vgic), + FIELD_UINT(" GICR Base. Addr", fwts_acpi_madt_gic, gicr_base_address), + FIELD_UINT(" MPIDR", fwts_acpi_madt_gic, mpidr), }; __acpi_dump_table_fields(fw, data, fields_madt_gic, offset); - skip = (sizeof(fwts_acpi_madt_gic)); + skip = sizeof(fwts_acpi_madt_gic); } break; - case 12: { + case FWTS_ACPI_MADT_GIC_D_GOC_DISTRIBUTOR: { static const fwts_acpidump_field fields_madt_gicd[] = { FIELD_UINT(" Reserved", fwts_acpi_madt_gicd, reserved), FIELD_UINT(" GIC ID", fwts_acpi_madt_gicd, gic_id), @@ -968,7 +973,31 @@ static void acpidump_madt(fwts_framework *fw, const fwts_acpi_table_info *table) FIELD_UINT(" Reserved", fwts_acpi_madt_gicd, reserved2), }; __acpi_dump_table_fields(fw, data, fields_madt_gicd, offset); - skip = (sizeof(fwts_acpi_madt_gicd)); + skip = sizeof(fwts_acpi_madt_gicd); + } + break; + case FWTS_ACPI_MADT_GIC_V2M_MSI_FRAME: { + static const fwts_acpidump_field fields_madt_gic_msi[] = { + FIELD_UINT(" Reserved", fwts_acpi_madt_gic_msi, reserved), + FIELD_UINT(" Frame ID", fwts_acpi_madt_gic_msi, frame_id), + FIELD_UINT(" Phys. Base. Addr",fwts_acpi_madt_gic_msi, physical_base_address), + FIELD_UINT(" Flags", fwts_acpi_madt_gic_msi, flags), + FIELD_UINT(" SPI Count", fwts_acpi_madt_gic_msi, spi_count), + FIELD_UINT(" SPI Base", fwts_acpi_madt_gic_msi, spi_base), + FIELD_UINT(" SPI Flags", fwts_acpi_madt_gic_msi, spi_flags), + }; + __acpi_dump_table_fields(fw, data, fields_madt_gic_msi, offset); + skip = sizeof(fwts_acpi_madt_gic_msi); + } + break; + case FWTS_ACPI_MADT_GIC_R_REDISTRIBUTOR: { + static const fwts_acpidump_field fields_madt_gicr[] = { + FIELD_UINT(" Reserved", fwts_acpi_madt_gicr, reserved), + FIELD_UINT(" Disc. Base Addr", fwts_acpi_madt_gicr, discovery_range_base_address), + FIELD_UINT(" Disc. Range Len", fwts_acpi_madt_gicr, discovery_range_length), + }; + __acpi_dump_table_fields(fw, data, fields_madt_gicr, offset); + skip = sizeof(fwts_acpi_madt_gicr); } break; default: diff --git a/src/acpi/acpitables/acpitables.c b/src/acpi/acpitables/acpitables.c index 46cd3bf..255261c 100644 --- a/src/acpi/acpitables/acpitables.c +++ b/src/acpi/acpitables/acpitables.c @@ -309,10 +309,13 @@ static void acpi_table_check_xsdt(fwts_framework *fw, fwts_acpi_table_info *tabl static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *table) { fwts_acpi_table_madt *madt = (fwts_acpi_table_madt*)table->data; + fwts_list msi_frame_ids; const uint8_t *data = table->data; size_t length = table->length; int i = 0; + fwts_list_init(&msi_frame_ids); + if (madt->flags & 0xfffffffe) fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTFlagsNonZero", "MADT flags field, bits 1..31 are reserved and " @@ -331,7 +334,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl length -= sizeof(fwts_acpi_madt_sub_table_header); switch (hdr->type) { - case 0: { + case FWTS_ACPI_MADT_LOCAL_APIC: { fwts_acpi_madt_processor_local_apic *lapic = (fwts_acpi_madt_processor_local_apic *)data; if (lapic->flags & 0xfffffffe) fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTAPICFlagsNonZero", @@ -341,7 +344,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl skip = sizeof(fwts_acpi_madt_processor_local_apic); } break; - case 1: { + case FWTS_ACPI_MADT_IO_APIC: { fwts_acpi_madt_io_apic *ioapic = (fwts_acpi_madt_io_apic*)data; if (ioapic->io_apic_phys_address == 0) fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTIOAPICAddrZero", "MADT IO APIC address is zero, appears not to be defined."); @@ -352,7 +355,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl skip = sizeof(fwts_acpi_madt_io_apic); } break; - case 2: { + case FWTS_ACPI_MADT_INTERRUPT_OVERRIDE: { fwts_acpi_madt_interrupt_override *int_override = (fwts_acpi_madt_interrupt_override*)data; if (int_override->bus != 0) fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTIRQSrcISA", "MADT Interrupt Source Override Bus should be 0 for ISA bus."); @@ -364,7 +367,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl skip = sizeof(fwts_acpi_madt_interrupt_override); } break; - case 3: { + case FWTS_ACPI_MADT_NMI_SOURCE: { fwts_acpi_madt_nmi *nmi = (fwts_acpi_madt_nmi*)data; if (nmi->flags & 0xfffffff0) fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTNMISrcFlags", @@ -374,7 +377,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl skip = sizeof(fwts_acpi_madt_nmi); } break; - case 4: { + case FWTS_ACPI_MADT_LOCAL_APIC_NMI: { fwts_acpi_madt_local_apic_nmi *nmi = (fwts_acpi_madt_local_apic_nmi*)data; if (nmi->flags & 0xfffffff0) fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTLAPICNMIFlags", @@ -384,22 +387,22 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl skip = sizeof(fwts_acpi_madt_local_apic_nmi); } break; - case 5: + case FWTS_ACPI_MADT_LOCAL_APIC_OVERRIDE: skip = sizeof(fwts_acpi_madt_local_apic_addr_override); break; - case 6: { + case FWTS_ACPI_MADT_IO_SAPIC: { fwts_acpi_madt_io_sapic *sapic = (fwts_acpi_madt_io_sapic*)data; if (sapic->address == 0) fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADIOSPAICAddrZero", "MADT I/O SAPIC address is zero, appears not to be defined."); skip = sizeof(fwts_acpi_madt_io_sapic); } break; - case 7: { + case FWTS_ACPI_MADT_LOCAL_SAPIC: { fwts_acpi_madt_local_sapic *local_sapic = (fwts_acpi_madt_local_sapic*)data; skip = sizeof(fwts_acpi_madt_local_sapic) + strlen(local_sapic->uid_string) + 1; } break; - case 8: { + case FWTS_ACPI_MADT_INTERRUPT_SOURCE: { fwts_acpi_madt_platform_int_source *src = (fwts_acpi_madt_platform_int_source*)data; if (src->flags & 0xfffffff0) fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTPlatIRQSrcFlags", @@ -421,10 +424,10 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl skip = (sizeof(fwts_acpi_madt_platform_int_source)); } break; - case 9: + case FWTS_ACPI_MADT_LOCAL_X2APIC: skip = (sizeof(fwts_acpi_madt_local_x2apic)); break; - case 10: { + case FWTS_ACPI_MADT_LOCAL_X2APIC_NMI: { fwts_acpi_madt_local_x2apic_nmi *nmi = (fwts_acpi_madt_local_x2apic_nmi*)data; if (nmi->flags & 0xfffffff0) fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTLAPICX2APICNMIFlags", @@ -434,21 +437,80 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl skip = (sizeof(fwts_acpi_madt_local_x2apic_nmi)); } break; - case 11: { + case FWTS_ACPI_MADT_GIC_C_CPU_INTERFACE: { fwts_acpi_madt_gic *gic = (fwts_acpi_madt_gic*)data; + if (gic->reserved) + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICCReservedNonZero", + "MADT GIC C Structure reserved field should be zero, " + "instead got 0x%" PRIx32 ".", gic->reserved); + if (gic->flags & 0xfffffffc) fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTGICFLags", "MADT GIC, flags, bits 2..31 are reserved " "and should be zero, but are set as: %" PRIx32 ".", - gic->flags); + gic->flags & 0xfffffffc); + skip = sizeof(fwts_acpi_madt_gic); } break; - case 12: - /* Not much to sanity check */ + case FWTS_ACPI_MADT_GIC_D_GOC_DISTRIBUTOR: { + fwts_acpi_madt_gicd *gicd = (fwts_acpi_madt_gicd*)data; + + if (gicd->reserved) + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICDReservedNonZero", + "MADT GIC Distributor Structure reserved field should be zero, " + "instead got 0x%" PRIx32 ".", gicd->reserved); + if (gicd->reserved2) + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICDReserved2NonZero", + "MADT GIC Distributor Structure second reserved field should be zero, " + "instead got 0x%" PRIx32 ".", gicd->reserved2); + } skip = sizeof(fwts_acpi_madt_gicd); break; + case FWTS_ACPI_MADT_GIC_V2M_MSI_FRAME: { + fwts_acpi_madt_gic_msi *gic_msi = (fwts_acpi_madt_gic_msi*)data; + fwts_list_link *item; + + if (gic_msi->reserved) + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICMSIReservedNonZero", + "MADT GIC MSI Structure reserved field should be zero, " + "instead got 0x%" PRIx32 ".", gic_msi->reserved); + + if (gic_msi->flags & 0xfffffffe) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTGICMSIFLags", + "MADT GIC MSI Frame, flags, bits 1..31 are reserved " + "and should be zero, but are set as: %" PRIx32 ".", + gic_msi->flags); + } + + /* Check against previously IDs to see if unique */ + fwts_list_foreach(item, &msi_frame_ids) { + uint32_t *frame_id = fwts_list_data(uint32_t *, item); + + /* Frame ID must be unique according to the spec */ + if (*frame_id == gic_msi->frame_id) { + fwts_failed(fw, LOG_LEVEL_MEDIUM, "MADTGICMSINonUniqueFrameId", + "MADT GIC MSI Frame ID 0x%" PRIx32 " is not unique " + "and has already be defined in a previous GIC MSI " + "Frame.", gic_msi->frame_id); + } else { + fwts_list_append(&msi_frame_ids, &(gic_msi->frame_id)); + } + } + } + skip = sizeof(fwts_acpi_madt_gic_msi); + break; + case FWTS_ACPI_MADT_GIC_R_REDISTRIBUTOR: { + fwts_acpi_madt_gicr *gicr = (fwts_acpi_madt_gicr*)data; + + if (gicr->reserved) + fwts_failed(fw, LOG_LEVEL_LOW, "MADTGICRReservedNonZero", + "MADT GIC Redistributor Structure reserved field should be zero, " + "instead got 0x%" PRIx32 ".", gicr->reserved); + } + skip = sizeof(fwts_acpi_madt_gicr); + break; default: skip = 0; break; @@ -456,6 +518,7 @@ static void acpi_table_check_madt(fwts_framework *fw, fwts_acpi_table_info *tabl data += skip; length -= skip; } + fwts_list_free_items(&msi_frame_ids, NULL); } static void acpi_table_check_mcfg(fwts_framework *fw, fwts_acpi_table_info *table) diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h index 1ea0daf..ceb6507 100644 --- a/src/lib/include/fwts_acpi.h +++ b/src/lib/include/fwts_acpi.h @@ -333,15 +333,21 @@ typedef enum { FWTS_ACPI_MADT_INTERRUPT_SOURCE, FWTS_ACPI_MADT_LOCAL_X2APIC, FWTS_ACPI_MADT_LOCAL_X2APIC_NMI, + FWTS_ACPI_MADT_GIC_C_CPU_INTERFACE, + FWTS_ACPI_MADT_GIC_D_GOC_DISTRIBUTOR, + FWTS_ACPI_MADT_GIC_V2M_MSI_FRAME, + FWTS_ACPI_MADT_GIC_R_REDISTRIBUTOR, FWTS_ACPI_MADT_RESERVED } fwts_acpi_madt_type; +/* Type 0, FWTS_ACPI_MADT_LOCAL_APIC */ typedef struct { uint8_t acpi_processor_id; uint8_t apic_id; uint32_t flags; } __attribute__ ((packed)) fwts_acpi_madt_processor_local_apic; +/* Type 1, FWTS_ACPI_MADT_IO_APIC */ typedef struct { uint8_t io_apic_id; uint8_t reserved; @@ -349,6 +355,7 @@ typedef struct { uint32_t global_irq_base; } __attribute__ ((packed)) fwts_acpi_madt_io_apic; +/* Type 2, FWTS_ACPI_MADT_INTERRUPT_OVERRIDE */ typedef struct { uint8_t bus; uint8_t source; @@ -356,22 +363,26 @@ typedef struct { uint16_t flags; } __attribute__ ((packed)) fwts_acpi_madt_interrupt_override; +/* Type 3, FWTS_ACPI_MADT_NMI_SOURCE */ typedef struct { uint16_t flags; uint32_t gsi; } __attribute__ ((packed)) fwts_acpi_madt_nmi; +/* Type 4, FWTS_ACPI_MADT_LOCAL_APIC_NMI */ typedef struct { uint8_t acpi_processor_id; uint16_t flags; uint8_t local_apic_lint; } __attribute__ ((packed)) fwts_acpi_madt_local_apic_nmi; +/* Type 5, FWTS_ACPI_MADT_LOCAL_APIC_OVERRIDE */ typedef struct { uint16_t reserved; uint64_t address; } __attribute__ ((packed)) fwts_acpi_madt_local_apic_addr_override; +/* Type 6, FWTS_ACPI_MADT_IO_SAPIC */ typedef struct { uint8_t io_sapic_id; uint8_t reserved; @@ -379,6 +390,7 @@ typedef struct { uint64_t address; } __attribute__ ((packed)) fwts_acpi_madt_io_sapic; +/* Type 7, FWTS_ACPI_MADT_LOCAL_SAPIC */ typedef struct { uint8_t acpi_processor_id; uint8_t local_sapic_id; @@ -389,6 +401,7 @@ typedef struct { char uid_string[0]; } __attribute__ ((packed)) fwts_acpi_madt_local_sapic; +/* Type 8, FWTS_ACPI_MADT_INTERRUPT_SOURCE */ typedef struct { uint16_t flags; uint8_t type; @@ -399,6 +412,7 @@ typedef struct { uint32_t pis_flags; } __attribute__ ((packed)) fwts_acpi_madt_platform_int_source; +/* Type 9, FWTS_ACPI_MADT_LOCAL_X2APIC */ typedef struct { uint16_t reserved; uint32_t x2apic_id; @@ -406,6 +420,7 @@ typedef struct { uint32_t processor_uid; } __attribute__ ((packed)) fwts_acpi_madt_local_x2apic; +/* Type 10, FWTS_ACPI_MADT_LOCAL_X2APIC_NMI */ typedef struct { uint16_t flags; uint32_t processor_uid; @@ -413,9 +428,10 @@ typedef struct { uint8_t reserved[3]; } __attribute__ ((packed)) fwts_acpi_madt_local_x2apic_nmi; +/* Type 11, FWTS_ACPI_MADT_GIC_C_CPU_INTERFACE */ /* New in ACPI 5.0, GIC, section 5.2.12.14 */ typedef struct { - uint8_t reserved[2]; + uint16_t reserved; uint32_t gic_id; uint32_t processor_uid; uint32_t flags; @@ -423,17 +439,43 @@ typedef struct { uint32_t performance_interrupt_gsiv; uint64_t parked_address; uint64_t physical_base_address; + uint64_t gicv; + uint64_t gich; + uint32_t vgic; + uint64_t gicr_base_address; + uint64_t mpidr; } __attribute__ ((packed)) fwts_acpi_madt_gic; /* New in ACPI 5.0, GICD, section 5.2.12.15 */ +/* Type 12, FWTS_ACPI_MADT_GIC_D_GOC_DISTRIBUTOR */ typedef struct { - uint8_t reserved[2]; + uint16_t reserved; uint32_t gic_id; uint64_t physical_base_address; uint32_t system_vector_base; uint32_t reserved2; } __attribute__ ((packed)) fwts_acpi_madt_gicd; +/* New in ACPI 5.1, GIC MSI Frame structure, 5.2.12.16 */ +/* Type 13, FWTS_ACPI_MADT_GIC_V2M_MSI_FRAME */ +typedef struct { + uint16_t reserved; + uint32_t frame_id; + uint64_t physical_base_address; + uint32_t flags; + uint16_t spi_count; + uint16_t spi_base; + uint32_t spi_flags; /* bit 0 just used at the moment */ +} __attribute__ ((packed)) fwts_acpi_madt_gic_msi; + +/* New in ACPI 5.1, GICR structure, 5.2.12.17 */ +/* Type 14, FWTS_ACPI_MADT_GIC_R_REDISTRIBUTOR */ +typedef struct { + uint16_t reserved; + uint64_t discovery_range_base_address; + uint32_t discovery_range_length; +} __attribute__ ((packed)) fwts_acpi_madt_gicr; + /* From http://www.kuro5hin.org/story/2002/10/27/16622/530, and also http://www.cl.cam.ac.uk/~rja14/tcpa-faq.html */ typedef struct {