コード例 #1
0
ファイル: asf.c プロジェクト: 9elements/fwts
/*
 *  4.1.2.1 ASF_INFO
 */
static void asf_check_info(
	fwts_framework *fw,
	ssize_t length,
	uint8_t *data,
	bool *passed,
	bool *abort)
{
	fwts_acpi_table_asf_info *info = (fwts_acpi_table_asf_info *)data;

	if (length < (ssize_t)sizeof(fwts_acpi_table_asf_info)) {
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"ASF!InfoRecordTooShort",
			"ASF! ASF_INFO Record too short, "
			"expecting %zu bytes, instead got %zu bytes",
			sizeof(fwts_acpi_table_asf_info), length);
		*passed = false;
		*abort = true;
		return;
	}

#if ASF_DUMP
	fwts_log_info_verbatim(fw, "ASF! ASF_INFO Record:");
	fwts_log_info_verbatim(fw, "  Min Watchdog Reset Value: 0x%2.2" PRIx8, info->watchdog_reset_value);
	fwts_log_info_verbatim(fw, "  Min Poll Wait Time:       0x%2.2" PRIx8, info->min_sensor_poll_wait_time);
	fwts_log_info_verbatim(fw, "  System ID:                0x%2.2" PRIx8, info->id);
	fwts_log_info_verbatim(fw, "  IANA Manufacturer ID:     0x%2.2" PRIx8, info->iana_id);
	fwts_log_info_verbatim(fw, "  Feature Flags:            0x%2.2" PRIx8, info->flags);
	fwts_log_info_verbatim(fw, "  Reserved:                 0x%2.2" PRIx8, info->reserved1);
	fwts_log_info_verbatim(fw, "  Reserved:                 0x%2.2" PRIx8, info->reserved2);
	fwts_log_info_verbatim(fw, "  Reserved:                 0x%2.2" PRIx8, info->reserved3);
#endif

	if (info->watchdog_reset_value == 0) {
		*passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"ASF!InfoMinWatchDogInvalid",
			"ASF! ASF_INFO Minimum Watchdog Reset Value is 0x00 and "
			"must be in the range 0x01..0xff");
	}
	if (info->min_sensor_poll_wait_time < 2) {
		*passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"ASF!InfoMinPollWaitTimeInvalid",
			"ASF! ASF_INFO Minimum Poll Wait Time is 0x%" PRIx8
			" and must be in the range 0x02..0xff",
			info->min_sensor_poll_wait_time);
	}

	fwts_acpi_reserved_bits_check(fw, "ASF!", "ASF_INFO Feature Flags", info->flags, sizeof(info->flags), 1, 7, passed);
	fwts_acpi_reserved_zero_check(fw, "ASF!", "ASF_INFO Reserved1", info->reserved1, sizeof(info->reserved1), passed);
	fwts_acpi_reserved_zero_check(fw, "ASF!", "ASF_INFO Reserved2", info->reserved2, sizeof(info->reserved2), passed);
	fwts_acpi_reserved_zero_check(fw, "ASF!", "ASF_INFO Reserved3", info->reserved3, sizeof(info->reserved3), passed);

	if (*passed)
		fwts_passed(fw, "No issues found in ASF! ASF_INFO record.");
}
コード例 #2
0
ファイル: pdtt.c プロジェクト: ColinIanKing/fwts
static int pdtt_test1(fwts_framework *fw)
{
	fwts_acpi_table_pdtt *pdtt = (fwts_acpi_table_pdtt*) table->data;
	fwts_acpi_table_pdtt_channel *entry;
	uint32_t offset, count, i;
	uint32_t reserved;
	bool passed = true;

	reserved = (uint32_t) pdtt->reserved[0] + ((uint32_t) pdtt->reserved[1] << 8) +
		   ((uint32_t) pdtt->reserved[2] << 16);

	fwts_log_info_verbatim(fw, "PDTT Platform Debug Trigger Table:");
	fwts_log_info_verbatim(fw, "  Trigger Count:           0x%2.2" PRIx8, pdtt->trigger_count);
	fwts_log_info_verbatim(fw, "  Reserved[3]:             0x%6.6" PRIx32, reserved);
	fwts_log_info_verbatim(fw, "  Trigger ID Array Offset: 0x%2.2" PRIx8, pdtt->array_offset);

	fwts_acpi_reserved_zero_check(fw, "PDTT", "Reserved", reserved, sizeof(reserved), &passed);

	offset = pdtt->array_offset;
	entry = (fwts_acpi_table_pdtt_channel *) (table->data + offset);

	count = (pdtt->header.length - pdtt->array_offset) / sizeof(fwts_acpi_table_pdtt_channel);
	if (count != pdtt->trigger_count) {
		passed = false;
		fwts_failed(fw, LOG_LEVEL_CRITICAL,
			"PDTTBadIDCount",
			"PDTT should have %" PRId8 " ids, got %" PRId8,
			pdtt->trigger_count, count);
		return FWTS_OK;
	}

	fwts_log_info_verbatim(fw, "  Platform Communication Channel IDs");

	for (i = 0; i < pdtt->trigger_count; i++) {
		fwts_log_info_verbatim(fw, "    Sub channel ID:          0x%2.2" PRIx8, entry->sub_channel_id);
		fwts_log_info_verbatim(fw, "    Flags:                   0x%2.2" PRIx8, entry->flags);
		fwts_acpi_reserved_bits_check(fw, "PDTT", "Flags", entry->flags, sizeof(entry->flags), 3, 7, &passed);

		if ((offset += sizeof(fwts_acpi_table_pdtt_channel)) > table->length) {
			passed = false;
			fwts_failed(fw, LOG_LEVEL_CRITICAL,
				"PDTTBadTableLength",
				"PDTT has more channel IDs than its size can handle");
			break;
		}

		entry = (fwts_acpi_table_pdtt_channel *) (table->data + offset);
	}

	fwts_log_nl(fw);

	if (passed)
		fwts_passed(fw, "No issues found in PDTT table.");

	return FWTS_OK;
}
コード例 #3
0
ファイル: tpm2.c プロジェクト: ColinIanKing/fwts
/*
 * TPM2 table
 *   available @ https://trustedcomputinggroup.org/tcg-acpi-specification/
 */
static int tpm2_test1(fwts_framework *fw)
{
	fwts_acpi_table_tpm2 *tpm2 = (fwts_acpi_table_tpm2*) table->data;
	bool passed = true;

	fwts_log_info_verbatim(fw, "TPM2 Table:");
	fwts_log_info_verbatim(fw, "  Platform Class:                  0x%4.4"   PRIx16, tpm2->platform_class);
	fwts_log_info_verbatim(fw, "  Reserved:                        0x%4.4"   PRIx32, tpm2->reserved);
	fwts_log_info_verbatim(fw, "  Address of Control Area:         0x%16.16" PRIx64, tpm2->address_of_control_area);
	fwts_log_info_verbatim(fw, "  Start Method:                    0x%8.8"   PRIx32, tpm2->start_method);

	if (tpm2->platform_class != 0 && tpm2->platform_class != 1) {
		passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"TPM2BadPlatformClass",
			"TPM2's platform class must be zero (client) or one (server), got 0x%" PRIx16,
			tpm2->platform_class);
	}

	fwts_acpi_reserved_zero_check(fw, "TPM2", "Reserved", tpm2->reserved, sizeof(tpm2->reserved), &passed);

	if (tpm2->start_method < 1 || tpm2->start_method >= 12) {
		passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"TPM2BadStartMethod",
			"TPM2's Start Method must be between one to eleven, got 0x%" PRIx16,
			tpm2->start_method);
	}

	if (tpm2->start_method == 2 && table->length != sizeof(fwts_acpi_table_tpm2) + 4) {
		passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"TPM2BadPlatformParameters",
			"Table length must be 0x%" PRIx32 " if Start method equals 2, got 0x%" PRIx32,
			(uint32_t) sizeof(fwts_acpi_table_tpm2) + 4,
			(uint32_t) table->length);
	}

	if (tpm2->start_method == 11 && table->length < sizeof(fwts_acpi_table_tpm2) + 12) {
		passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"TPM2BadPlatformParameters",
			"Table length must be atleast 0x%" PRIx32 " if Start method equals 11, got 0x%" PRIx32,
			(uint32_t) sizeof(fwts_acpi_table_tpm2) + 12,
			(uint32_t) table->length);
	}

	if (passed)
		fwts_passed(fw, "No issues found in TPM2 table.");

	return FWTS_OK;
}
コード例 #4
0
ファイル: asf.c プロジェクト: 9elements/fwts
/*
 *  ASF! Hardware Error Source Table test
 *     http://www.dmtf.org/sites/default/files/standards/documents/DSP0136.pdf
 */
static int asf_test1(fwts_framework *fw)
{
	bool passed = true;
	bool abort = false;
	fwts_acpi_table_header *hdr = (fwts_acpi_table_header *)table->data;
        uint8_t *data = (uint8_t *)table->data;
        ssize_t length = (ssize_t)hdr->length;

	fwts_log_info_verbatim(fw, "ASF! Hardware Error Source Table");

        data += sizeof(fwts_acpi_table_header);
        length -= sizeof(fwts_acpi_table_header);

	while (!abort && (length > 0)) {
		bool asf_passed = true;

		fwts_acpi_table_asf_header *asf_hdr =
			(fwts_acpi_table_asf_header *)data;

		/* Must have enough for a info header */
		if (length < (ssize_t)sizeof(fwts_acpi_table_asf_header)) {
			passed = false;
			fwts_failed(fw, LOG_LEVEL_HIGH,
				"ASF!TooShort",
				"ASF! table too short, expecting at least %zu bytes "
				"for an ASF! information record header, "
				"instead got %zu bytes",
				sizeof(fwts_acpi_table_asf_header), table->length);
			break;
		}

#if ASF_DUMP
		fwts_log_info_verbatim(fw, "Type:                       0x%2.2" PRIx8, asf_hdr->type);
		fwts_log_info_verbatim(fw, "Reserved:                   0x%2.2" PRIx8, asf_hdr->reserved);
		fwts_log_info_verbatim(fw, "Length:                     0x%4.4" PRIx16, asf_hdr->length);
#endif

		fwts_acpi_reserved_zero_check(fw, "ASF!", "Information Record Reserved", asf_hdr->reserved, sizeof(asf_hdr->reserved), &passed);

		if (asf_hdr->length > (uint32_t)length) {
			passed = false;
			fwts_failed(fw, LOG_LEVEL_HIGH,
				"ASF!InfoRecordLengthTooLong",
				"ASF! Information Record Reserved length is %" PRIu32
				" and this is too long for the size given by "
				"the ASF! table. Expected at most %zu bytes.",
				asf_hdr->length, length);
			/* Since we can't trust the table, abort */
			break;
		}

		switch (asf_hdr->type) {
		case 0x00:
		case 0x80:
			asf_check_info(fw, length - sizeof(*asf_hdr), data + sizeof(*asf_hdr), &asf_passed, &abort);
			data += asf_hdr->length;
			length -= asf_hdr->length;
			break;
		case 0x01:
		case 0x81:
			asf_check_alrt(fw, asf_hdr->length,
				length - sizeof(*asf_hdr), data + sizeof(*asf_hdr), &asf_passed, &abort);
			data += asf_hdr->length;
			length -= asf_hdr->length;
			break;
		case 0x02:
		case 0x82:
			asf_check_rctl(fw, asf_hdr->length,
				length - sizeof(*asf_hdr), data + sizeof(*asf_hdr), &asf_passed, &abort);
			data += asf_hdr->length;
			length -= asf_hdr->length;
			break;
		case 0x03:
		case 0x83:
			asf_check_rmcp(fw, length - sizeof(*asf_hdr), data + sizeof(*asf_hdr), &asf_passed, &abort);
			data += asf_hdr->length;
			length -= asf_hdr->length;
			break;
		case 0x04:
		case 0x84:
			asf_check_addr(fw, asf_hdr->length,
				length - sizeof(*asf_hdr), data + sizeof(*asf_hdr), &asf_passed, &abort);
			data += asf_hdr->length;
			length -= asf_hdr->length;
			break;
		default:
			fwts_failed(fw, LOG_LEVEL_HIGH,
				"ASF!InvalidType",
				"ASF! Information Record Type 0x%4.4" PRIx16 " is invalid, aborting check",
				asf_hdr->type);
			passed = false;
			length = 0;
			break;
		}
		passed &= asf_passed;
#if ASF_DUMP
		fwts_log_nl(fw);
#endif
	}
#if ASF_DUMP
	fwts_log_nl(fw);
#endif

	if (passed)
		fwts_passed(fw, "No issues found in ASF! table.");

	return FWTS_OK;
}
コード例 #5
0
ファイル: pcct.c プロジェクト: ColinIanKing/fwts
static int pcct_test1(fwts_framework *fw)
{
	fwts_acpi_table_pcct *pcct = (fwts_acpi_table_pcct*) table->data;
	fwts_acpi_table_pcct_subspace_header *pcct_sub;
	size_t offset;
	bool passed = true;

	fwts_log_info_verbatim(fw, "PCC Table:");
	fwts_log_info_verbatim(fw, "  Flags:     0x%8.8"   PRIx32, pcct->flags);
	fwts_log_info_verbatim(fw, "  Reserved:  0x%16.16"   PRIx64, pcct->reserved);
	fwts_log_nl(fw);

	fwts_acpi_reserved_bits_check(fw, "PCCT", "Flags", pcct->flags, sizeof(pcct->flags), 1, 31, &passed);
	fwts_acpi_reserved_zero_check(fw, "PCCT", "Reserved", pcct->reserved, sizeof(pcct->reserved), &passed);

	offset = sizeof(fwts_acpi_table_pcct);
	pcct_sub = (fwts_acpi_table_pcct_subspace_header *) (table->data + offset);

	while (offset < table->length) {

		fwts_log_info_verbatim(fw, "  PCC Subspace Structure:");
		fwts_log_info_verbatim(fw, "    Type:                        0x%2.2"   PRIx8, pcct_sub->type);
		fwts_log_info_verbatim(fw, "    Length:                      0x%2.2"   PRIx8, pcct_sub->length);

		if (pcct_sub->type == 0) {
			fwts_acpi_table_pcct_subspace_type_0 *subspace = (fwts_acpi_table_pcct_subspace_type_0 *) pcct_sub;

			if(!subspace_length_equal(fw, 0, sizeof(fwts_acpi_table_pcct_subspace_type_0), pcct_sub->length)) {
				passed = false;
				break;
			}

			generic_comm_test(fw, subspace, &passed);

		} else if (pcct_sub->type == 1) {
			fwts_acpi_table_pcct_subspace_type_1 *subspace = (fwts_acpi_table_pcct_subspace_type_1 *) pcct_sub;

			if(!subspace_length_equal(fw, 0, sizeof(fwts_acpi_table_pcct_subspace_type_1), pcct_sub->length)) {
				passed = false;
				break;
			}

			hw_reduced_comm_test_type1(fw, subspace, &passed);

		} else if (pcct_sub->type == 2) {
			fwts_acpi_table_pcct_subspace_type_2 *subspace = (fwts_acpi_table_pcct_subspace_type_2 *) pcct_sub;

			if(!subspace_length_equal(fw, 0, sizeof(fwts_acpi_table_pcct_subspace_type_2), pcct_sub->length)) {
				passed = false;
				break;
			}

			hw_reduced_comm_test_type2(fw, subspace, &passed);

		} else if (pcct_sub->type == 3) {
			fwts_acpi_table_pcct_subspace_type_3_4 *subspace = (fwts_acpi_table_pcct_subspace_type_3_4 *) pcct_sub;

			if(!subspace_length_equal(fw, 0, sizeof(fwts_acpi_table_pcct_subspace_type_3_4), pcct_sub->length)) {
				passed = false;
				break;
			}

			extended_pcc_test(fw, subspace, &passed);

		} else if (pcct_sub->type == 4) {
			fwts_acpi_table_pcct_subspace_type_3_4 *subspace = (fwts_acpi_table_pcct_subspace_type_3_4 *) pcct_sub;

			if(!subspace_length_equal(fw, 0, sizeof(fwts_acpi_table_pcct_subspace_type_3_4), pcct_sub->length)) {
				passed = false;
				break;
			}

			if (!(pcct->flags & 0x01)) {
				passed = false;
				fwts_failed(fw, LOG_LEVEL_HIGH,
					"PCCTBadFlags",
					"PCCT Platform Interrupt in flags must be set when subspace "
					"type 4 is present, got 0x%8.8" PRIx32 " instead", pcct->flags);
			}

			extended_pcc_test(fw, subspace, &passed);

		} else {
			passed = false;
			fwts_failed(fw, LOG_LEVEL_HIGH,
				"PCCTBadSubType",
				"PCCT Subspace Structure supports type 0..4, got "
				"0x%2.2" PRIx8 " instead", pcct_sub->type);
			break;
		}

		fwts_log_nl(fw);

		offset += pcct_sub->length;
		pcct_sub = (fwts_acpi_table_pcct_subspace_header *) (table->data + offset);
	}

	if (passed)
		fwts_passed(fw, "No issues found in PCC table.");

	return FWTS_OK;
}
コード例 #6
0
ファイル: spcr.c プロジェクト: ColinIanKing/fwts
static int spcr_test1(fwts_framework *fw)
{
	char *str;
	uint32_t reserved1;
	bool reserved = false;
	bool pci = true;
	bool passed = true;

	/*
	 * Assuming revision 2, full list from
	 * http://go.microsoft.com/fwlink/p/?LinkId=234837)
	 */
	switch (spcr->interface_type) {
	case 0x00:
		str = "16550 compatible";
		break;
	case 0x01:
		str = "16450 compatible";
		break;
	case 0x03:
		str = "ARM PL011 UART";
		break;
	case 0x02:
	case 0x04 ... 0x0c:
		str = "Reserved (Do not Use)";
		reserved = true;
		break;
	case 0x0d:
		str = "(deprecated) ARM SBSA";
		break;
	case 0x0e:
		str = "ARM SBSA Generic UART";
		break;
	case 0x0f:
		str = "ARM DCC";
		break;
	case 0x10:
		str = "BCM2835";
		break;
	default:
		str = "Reserved";
		reserved = true;
		break;
	}

	fwts_log_info_verbatim(fw, "Serial Interface: %s", str);
	if (reserved) {
		passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"SPCRInterfaceReserved",
			"SPCR Serial interface type 0x%2.2" PRIx8
			" is a reserved interface", spcr->interface_type);
	}

	reserved1 = spcr->reserved1[0] + (spcr->reserved1[1] << 8) + (spcr->reserved1[2] << 16);
	fwts_acpi_reserved_zero_check(fw, "SPCR", "Reserved1", reserved1, sizeof(reserved1), &passed);

	if (spcr->interrupt_type == 0) {
		passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"SPCRUnknownInterruptType",
			"SPCR interrupt type field is zero, expecting support bits to be set");
	}
	if (spcr->interrupt_type & 0xf0) {
		passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"SPCRIllegalReservedInterruptType",
			"SPCR interrupt type reserved bits are non-zero zero, got 0x%" PRIx8,
				spcr->interrupt_type);
	}

	/* Check PC-AT compatible UART IRQs */
	if (spcr->interrupt_type & 1) {
		switch (spcr->irq) {
		case  2 ...  7:
		case  9 ... 12:
		case 14 ... 15:
			break;
		default:
			passed = false;
			fwts_failed(fw, LOG_LEVEL_HIGH,
				"SPCRIllegalIRQ",
				"SPCR PC-AT compatible IRQ 0x%" PRIx8 " is invalid", spcr->irq);
			break;
		}
	}

	reserved = false;
	switch (spcr->baud_rate) {
	case 0x03:
		str = "9600";
		break;
	case 0x04:
		str = "19200";
		break;
	case 0x06:
		str = "57600";
		break;
	case 0x07:
		str = "115200";
		break;
	default:
		str = "Reserved";
		reserved = true;
	}
	fwts_log_info_verbatim(fw, "Baud Rate:        %s", str);
	if (reserved) {
		passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"SPCRBaudRateReserved",
			"SPCR Serial baud rate type 0x%2.2" PRIx8
			" is a reserved baud rate", spcr->baud_rate);
	}

	if (spcr->parity != 0) {
		passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"SPCRReservedValueUsed",
			"SPCR Parity field must be zero, got 0x%2.2" PRIx8 " instead",
			spcr->parity);
	}

	if (spcr->stop_bits != 1) {
		passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"SPCRReservedValueUsed",
			"SPCR Stop field must be 1, got 0x%2.2" PRIx8 " instead",
			spcr->stop_bits);
	}

	fwts_acpi_reserved_bits_check(fw, "SPCR", "Flow control", spcr->flow_control, sizeof(spcr->flow_control), 3, 7, &passed);

	reserved = false;
	switch (spcr->terminal_type) {
	case 0x00:
		str = "VT100";
		break;
	case 0x01:
		str = "VT100+";
		break;
	case 0x02:
		str = "VT-UTF8";
		break;
	case 0x03:
		str = "ANSI";
		break;
	default:
		str = "Reserved";
		reserved = true;
	}
	fwts_log_info_verbatim(fw, "Terminal Type:    %s", str);
	if (reserved) {
		passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"SPCRTerminalTypeReserved",
			"SPCR terminal type type 0x%2.2" PRIx8
			" is a reserved terminal type", spcr->terminal_type);
	}

	fwts_acpi_reserved_zero_check(fw, "SPCR", "Reserved2", spcr->reserved2, sizeof(spcr->reserved2), &passed);

	/* According to the spec, these values indicate NOT a PCI device */
	if ((spcr->pci_device_id == 0xffff) &&
	    (spcr->pci_vendor_id == 0xffff) &&
	    (spcr->pci_bus_number == 0) &&
	    (spcr->pci_device_number == 0) &&
	    (spcr->pci_function_number == 0))
		pci = false;

	/* Now validate all pci specific fields if not-PCI enabled */
	if (pci) {
		if (spcr->pci_device_id == 0xffff) {
			passed = false;
			fwts_failed(fw, LOG_LEVEL_HIGH,
				"SPCRPciDeviceID",
				"SPCR PCI device ID is 0x%4.4" PRIx16
				", expecting non-0xffff for PCI device",
				spcr->pci_device_id);
		}
		if (spcr->pci_vendor_id == 0xffff) {
			passed = false;
			fwts_failed(fw, LOG_LEVEL_HIGH,
				"SPCRPciVendorID",
				"SPCR PCI vendor ID is 0x%4.4" PRIx16
				", expecting non-0xffff for non-PCI device",
				spcr->pci_vendor_id);
		}
		if ((spcr->pci_flags & 1) == 0) {
			passed = false;
			fwts_failed(fw, LOG_LEVEL_HIGH,
				"SPCRPciFlagsBit0",
				"SPCR PCI flags compatibility bit 0 is %" PRIx32
				", expecting 1 for PCI device",
				spcr->pci_flags & 1);
		}
	}

	fwts_acpi_reserved_bits_check(fw, "SPCR", "PCI Flags", spcr->pci_flags, sizeof(spcr->pci_flags), 1, 31, &passed);
	fwts_acpi_reserved_zero_check(fw, "SPCR", "Reserved3", spcr->reserved3, sizeof(spcr->reserved3), &passed);

	if (passed)
		fwts_passed(fw, "No issues found in SPCR table.");

	return FWTS_OK;
}
コード例 #7
0
ファイル: hest.c プロジェクト: 9elements/fwts
/*
 *  ACPI Section 18.3.2.5 PCI Express/PCI-X Bridge AER Structure
 */
static void hest_heck_pci_express_bridge_aer(
	fwts_framework *fw,
	ssize_t *length,
	uint8_t **data,
	bool *passed)
{
	fwts_acpi_table_hest_pci_express_bridge_aer *aer =
		(fwts_acpi_table_hest_pci_express_bridge_aer *)*data;

	if (*length < (ssize_t)sizeof(fwts_acpi_table_hest_pci_express_bridge_aer)) {
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"HESTPciExpressBridgeAerTooShort",
			"HEST PCI Express Bridge AER "
			"too short, expecting %zu bytes, "
			"instead got %zu bytes",
			sizeof(fwts_acpi_table_hest_pci_express_bridge_aer), *length);
		*passed = false;
		*length = 0;	/* Forces an early abort */
		return;
	}

	fwts_log_info_verbatim(fw, "HEST PCI Express Bridge AER:");
	fwts_log_info_verbatim(fw, "  Type:                     0x%2.2" PRIx8, aer->type);
	fwts_log_info_verbatim(fw, "  Source ID:                0x%4.4" PRIx16, aer->source_id);
	fwts_log_info_verbatim(fw, "  Reserved:                 0x%4.4" PRIx16, aer->reserved1);
	fwts_log_info_verbatim(fw, "  Flags:                    0x%2.2" PRIx8, aer->flags);
	fwts_log_info_verbatim(fw, "  Enabled:                  0x%2.2" PRIx8, aer->enabled);
	fwts_log_info_verbatim(fw, "  Number of Records:        0x%8.8" PRIx32, aer->number_of_records_to_preallocate);
	fwts_log_info_verbatim(fw, "  Max Sections Per Record:  0x%8.8" PRIx32, aer->max_sections_per_record);
	fwts_log_info_verbatim(fw, "  Bus:                      0x%8.8" PRIx32, aer->bus);
	fwts_log_info_verbatim(fw, "  Device:                   0x%4.4" PRIx16, aer->device);
	fwts_log_info_verbatim(fw, "  Function:                 0x%4.4" PRIx16, aer->function);
	fwts_log_info_verbatim(fw, "  Device Control:           0x%4.4" PRIx16, aer->device_control);
	fwts_log_info_verbatim(fw, "  Reserved:                 0x%4.4" PRIx16, aer->reserved2);
	fwts_log_info_verbatim(fw, "  Uncorrectable Mask:       0x%8.8" PRIx32, aer->uncorrectable_error_mask);
	fwts_log_info_verbatim(fw, "  Uncorrectable Severity:   0x%8.8" PRIx32, aer->uncorrectable_error_severity);
	fwts_log_info_verbatim(fw, "  Correctable Mask:         0x%8.8" PRIx32, aer->correctable_error_mask);
	fwts_log_info_verbatim(fw, "  Advanced Capabilities:    0x%8.8" PRIx32, aer->advanced_error_capabilities_and_control);
	fwts_log_info_verbatim(fw, "  2nd Uncorrectable Mask:   0x%8.8" PRIx32, aer->secondary_uncorrectable_error_mask);
	fwts_log_info_verbatim(fw, "  2nd Uncurrectable Svrity: 0x%8.8" PRIx32, aer->secondary_uncorrectable_error_severity);
	fwts_log_info_verbatim(fw, "  2nd Advanced Capabilities:0x%8.8" PRIx32, aer->secondary_advanced_error_capabilities_and_control);
	fwts_log_nl(fw);

	fwts_acpi_reserved_zero_check(fw, "HEST", "PCI Express Bridge Reserved1", aer->reserved1, sizeof(aer->reserved1), passed);
	fwts_acpi_reserved_bits_check(fw, "HEST", "PCI Express Bridge Flags", aer->flags, sizeof(aer->flags), 2, 7, passed);
	fwts_acpi_reserved_zero_check(fw, "HEST", "PCI Express Bridge Reserved2", aer->reserved2, sizeof(aer->reserved2), passed);

	if (aer->number_of_records_to_preallocate < 1) {
		*passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"HESTInvalidRecordsToPreallocate",
			"HEST PCI Express Bridge Number of Records "
			"to Preallocate is 0x%" PRIx16 " and must be "
			"more than zero.",
			aer->number_of_records_to_preallocate);
	}
	if (aer->max_sections_per_record < 1) {
		*passed = false;
		fwts_failed(fw, LOG_LEVEL_HIGH,
			"HESTInvalidMaxSectionsPerRecord",
			"HEST PCI Express Brdige Max Sections Per "
			"Record is 0x%" PRIx16 " and must be "
			"more than zero.",
			aer->max_sections_per_record);
	}
	*length -= sizeof(fwts_acpi_table_hest_pci_express_bridge_aer);
	*data += sizeof(fwts_acpi_table_hest_pci_express_bridge_aer);
}