diff mbox

ACPI: Add new ACPI 5.1 MADT stuctures and checks (LP: #1348581)

Message ID 1406286341-16115-1-git-send-email-colin.king@canonical.com
State Accepted
Headers show

Commit Message

Colin Ian King July 25, 2014, 11:05 a.m. UTC
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(-)

Comments

Alex Hung July 30, 2014, 2:53 a.m. UTC | #1
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>
Ivan Hu Aug. 1, 2014, 2:24 a.m. UTC | #2
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 mbox

Patch

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 {