Message ID | 1502995192-21160-2-git-send-email-alex.hung@canonical.com |
---|---|
State | Accepted |
Headers | show |
On 17/08/17 19:39, Alex Hung wrote: > 1. Added type 3 & type 4 > 2. Updated doorbell to platform in some cases > 3. Fixed typos > > Signed-off-by: Alex Hung <alex.hung@canonical.com> > --- > src/acpi/pcct/pcct.c | 232 +++++++++++++++++++++++++------------------- > src/lib/include/fwts_acpi.h | 40 ++++++-- > 2 files changed, 167 insertions(+), 105 deletions(-) > > diff --git a/src/acpi/pcct/pcct.c b/src/acpi/pcct/pcct.c > index 9d79dc5..5753325 100644 > --- a/src/acpi/pcct/pcct.c > +++ b/src/acpi/pcct/pcct.c > @@ -52,6 +52,64 @@ static bool subspace_length_equal(fwts_framework *fw, uint8_t type, uint8_t type > return true; > } > > +static void platform_interrupt_flags(fwts_framework *fw, uint8_t flags, bool *passed) > +{ > + fwts_log_info_verbatim(fw, " Platform Interrupt Flags: 0x%2.2" PRIx8, flags); > + > + if (flags & ~0x3) { > + *passed = false; > + fwts_failed(fw, LOG_LEVEL_HIGH, > + "PCCTBadSubtypePlatformbInterruptlags", > + "PCCT Subspace Platform Interrupt Flags's bit [7:2] be zero, got " > + "0x%2.2" PRIx8 " instead", flags); > + } > +} > + > +static void gas_messages(fwts_framework *fw, uint8_t type, fwts_acpi_gas *gas, bool *passed) > +{ > + fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas->address_space_id); > + fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas->register_bit_width); > + fwts_log_info_verbatim(fw, " Register Bit Offset 0x%2.2" PRIx8, gas->register_bit_offset); > + fwts_log_info_verbatim(fw, " Access Size 0x%2.2" PRIx8, gas->access_width); > + fwts_log_info_verbatim(fw, " Address 0x%16.16" PRIx64, gas->address); > + > + if ((gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_IO) && > + (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_MEMORY) && > + (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_FFH)) { > + *passed = false; > + fwts_failed(fw, LOG_LEVEL_HIGH, > + "PCCTSubspaceInvalidAddrSpaceID", > + "PCCT Subspace Type %" PRId8 " has space ID = %" PRId8 > + " which is not System I/O, Memory or FFH", type, gas->address_space_id); > + } > +} > + > +static void memory_length(fwts_framework *fw, uint8_t type, uint64_t memory_range, uint64_t min_length, bool *passed) > +{ > + switch (type) { > + case 0 ... 2: > + fwts_log_info_verbatim(fw, " Length: 0x%16.16" PRIx64, memory_range); > + if (memory_range <= min_length) { > + *passed = false; > + fwts_failed(fw, LOG_LEVEL_HIGH, > + "PCCTBadSubtypeMemoryLength", > + "PCCT Subspace Type %" PRId8 " must have memory length > 0x%16.16" PRIx64 > + ", got 0x%16.16" PRIx64 " instead", type, min_length, memory_range); > + } > + break; > + case 3 ... 4: > + fwts_log_info_verbatim(fw, " Length: 0x%8.8" PRIx32, (uint32_t)memory_range); > + if (memory_range <= min_length) { > + *passed = false; > + fwts_failed(fw, LOG_LEVEL_HIGH, > + "PCCTBadSubtypeMemoryLength", > + "PCCT Subspace Type %" PRId8 " must have memory length > 0x%8.8" PRIx32 > + ", got 0x%8.8" PRIx32 " instead", type, (uint32_t)min_length, (uint32_t)memory_range); > + } > + break; > + } > +} > + > static void generic_comm_test(fwts_framework *fw, fwts_acpi_table_pcct_subspace_type_0 *entry, bool *passed) > { > fwts_acpi_gas *gas = &entry->doorbell_register; > @@ -63,7 +121,7 @@ static void generic_comm_test(fwts_framework *fw, fwts_acpi_table_pcct_subspace_ > > fwts_log_info_verbatim(fw, " Reserved: 0x%16.16" PRIx64, reserved); > fwts_log_info_verbatim(fw, " Base Address: 0x%16.16" PRIx64, entry->base_address); > - fwts_log_info_verbatim(fw, " Length: 0x%16.16" PRIx64, entry->length); > + memory_length(fw, entry->header.type, entry->length, 8, passed); > fwts_log_info_verbatim(fw, " Doorbell Register:"); > fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas->address_space_id); > fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas->register_bit_width); > @@ -82,113 +140,76 @@ static void generic_comm_test(fwts_framework *fw, fwts_acpi_table_pcct_subspace_ > fwts_failed(fw, LOG_LEVEL_HIGH, > "PCCTSubspaceInvalidAddrSpaceID", > "PCCT Subspace Type 0 has space ID = 0x%2.2" PRIx8 > - " which is not System I/O Space or System Memory Space", > + " which is not System I/O or Memory", > gas->address_space_id); > } > } > > static void hw_reduced_comm_test_type1(fwts_framework *fw, fwts_acpi_table_pcct_subspace_type_1 *entry, bool *passed) > { > - fwts_acpi_gas *gas = &entry->doorbell_register; > - uint8_t doorbell_int_flags = entry->doorbell_interrupt_flags; > - > - fwts_log_info_verbatim(fw, " Doorbell Interrupt: 0x%8.8" PRIx32, entry->doorbell_interrupt); > - fwts_log_info_verbatim(fw, " Doorbell Interrupt Flags: 0x%2.2" PRIx8, entry->doorbell_interrupt_flags); > + fwts_log_info_verbatim(fw, " Platform Interrupt: 0x%8.8" PRIx32, entry->platform_interrupt); > + platform_interrupt_flags(fw, entry->platform_interrupt_flags, passed); > fwts_log_info_verbatim(fw, " Reserved: 0x%2.2" PRIx8, entry->reserved); > fwts_log_info_verbatim(fw, " Base Address: 0x%16.16" PRIx64, entry->base_address); > - fwts_log_info_verbatim(fw, " Length: 0x%16.16" PRIx64, entry->length); > + memory_length(fw, entry->header.type, entry->length, 8, passed); > fwts_log_info_verbatim(fw, " Doorbell Register:"); > - fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas->address_space_id); > - fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas->register_bit_width); > - fwts_log_info_verbatim(fw, " Register Bit Offset 0x%2.2" PRIx8, gas->register_bit_offset); > - fwts_log_info_verbatim(fw, " Access Size 0x%2.2" PRIx8, gas->access_width); > - fwts_log_info_verbatim(fw, " Address 0x%16.16" PRIx64, gas->address); > + gas_messages(fw, entry->header.type, &entry->doorbell_register, passed); > fwts_log_info_verbatim(fw, " Doorbell Preserve: 0x%16.16" PRIx64, entry->doorbell_preserve); > fwts_log_info_verbatim(fw, " Doorbell Write: 0x%16.16" PRIx64, entry->doorbell_write); > fwts_log_info_verbatim(fw, " Nominal Latency: 0x%8.8" PRIx32, entry->nominal_latency); > fwts_log_info_verbatim(fw, " Max Periodic Access Rate: 0x%8.8" PRIx32, entry->max_periodic_access_rate); > fwts_log_info_verbatim(fw, " Min Request Turnaround Time: 0x%8.8" PRIx32, entry->min_request_turnaround_time); > - > - if ((gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_IO) && > - (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_MEMORY) && > - (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_FFH)) { > - *passed = false; > - fwts_failed(fw, LOG_LEVEL_HIGH, > - "PCCTSubspaceInvalidAddrSpaceID", > - "PCCT Subspace Type 1 has space ID = 0x%2.2" PRIx8 > - " which is not System I/O Space or System Memory Space", > - gas->address_space_id); > - } > - > - if (doorbell_int_flags & ~0x3) { > - *passed = false; > - fwts_failed(fw, LOG_LEVEL_HIGH, > - "PCCTBadSubtypeDoorbellFlags", > - "PCCT Subspace Doorbell Interrupt's bit 2..7 be zero, got " > - "0x%2.2" PRIx8 " instead", doorbell_int_flags); > - } > } > > static void hw_reduced_comm_test_type2(fwts_framework *fw, fwts_acpi_table_pcct_subspace_type_2 *entry, bool *passed) > { > - fwts_acpi_gas *gas = &entry->doorbell_register; > - fwts_acpi_gas *gas2 = &entry->doorbell_ack_register; > - uint8_t doorbell_int_flags = entry->doorbell_interrupt_flags; > - > - fwts_log_info_verbatim(fw, " Doorbell Interrupt: 0x%8.8" PRIx32, entry->doorbell_interrupt); > - fwts_log_info_verbatim(fw, " Doorbell Interrupt Flags: 0x%2.2" PRIx8, entry->doorbell_interrupt_flags); > + fwts_log_info_verbatim(fw, " Platform Interrupt: 0x%8.8" PRIx32, entry->platform_interrupt); > + platform_interrupt_flags(fw, entry->platform_interrupt_flags, passed); > fwts_log_info_verbatim(fw, " Reserved: 0x%2.2" PRIx8, entry->reserved); > fwts_log_info_verbatim(fw, " Base Address: 0x%16.16" PRIx64, entry->base_address); > - fwts_log_info_verbatim(fw, " Length: 0x%16.16" PRIx64, entry->length); > + memory_length(fw, entry->header.type, entry->length, 8, passed); > fwts_log_info_verbatim(fw, " Doorbell Register:"); > - fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas->address_space_id); > - fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas->register_bit_width); > - fwts_log_info_verbatim(fw, " Register Bit Offset 0x%2.2" PRIx8, gas->register_bit_offset); > - fwts_log_info_verbatim(fw, " Access Size 0x%2.2" PRIx8, gas->access_width); > - fwts_log_info_verbatim(fw, " Address 0x%16.16" PRIx64, gas->address); > + gas_messages(fw, entry->header.type, &entry->doorbell_register, passed); > fwts_log_info_verbatim(fw, " Doorbell Preserve: 0x%16.16" PRIx64, entry->doorbell_preserve); > fwts_log_info_verbatim(fw, " Doorbell Write: 0x%16.16" PRIx64, entry->doorbell_write); > fwts_log_info_verbatim(fw, " Nominal Latency: 0x%8.8" PRIx32, entry->nominal_latency); > fwts_log_info_verbatim(fw, " Max Periodic Access Rate: 0x%8.8" PRIx32, entry->max_periodic_access_rate); > fwts_log_info_verbatim(fw, " Min Request Turnaround Time: 0x%8.8" PRIx32, entry->min_request_turnaround_time); > - fwts_log_info_verbatim(fw, " Doorbell Ack Register:"); > - fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas2->address_space_id); > - fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas2->register_bit_width); > - fwts_log_info_verbatim(fw, " Register Bit Offset 0x%2.2" PRIx8, gas2->register_bit_offset); > - fwts_log_info_verbatim(fw, " Access Size 0x%2.2" PRIx8, gas2->access_width); > - fwts_log_info_verbatim(fw, " Address 0x%16.16" PRIx64, gas2->address); > - fwts_log_info_verbatim(fw, " Doorbell Ack Preserve: 0x%16.16" PRIx64, entry->doorbell_ack_preserve); > - fwts_log_info_verbatim(fw, " Doorbell Ack Write: 0x%16.16" PRIx64, entry->doorbell_ack_write); > - > - if ((gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_IO) && > - (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_MEMORY) && > - (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_FFH)) { > - *passed = false; > - fwts_failed(fw, LOG_LEVEL_HIGH, > - "PCCTSubspaceInvalidAddrSpaceID", > - "PCCT Subspace Type 2 has space ID = 0x%2.2" PRIx8 > - " which is not System I/O Space or System Memory Space", > - gas->address_space_id); > - } > - > - if ((gas2->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_IO) && > - (gas2->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_MEMORY) && > - (gas2->address_space_id != FWTS_GAS_ADDR_SPACE_ID_FFH)) { > - *passed = false; > - fwts_failed(fw, LOG_LEVEL_HIGH, > - "PCCTSubspaceInvalidAddrSpaceID", > - "PCCT Subspace Type 2 has space ID = 0x%2.2" PRIx8 > - " which is not System I/O Space or System Memory Space", > - gas->address_space_id); > - } > + fwts_log_info_verbatim(fw, " Platform Interrupt Ack Register:"); > + gas_messages(fw, entry->header.type, &entry->platform_ack_register, passed); > + fwts_log_info_verbatim(fw, " Platform Ack Preserve: 0x%16.16" PRIx64, entry->platform_ack_preserve); > + fwts_log_info_verbatim(fw, " Platform Ack Write: 0x%16.16" PRIx64, entry->platform_ack_write); > +} > > - if (doorbell_int_flags & ~0x3) { > - *passed = false; > - fwts_failed(fw, LOG_LEVEL_HIGH, > - "PCCTBadSubtypeDoorbellFlags", > - "PCCT Subspace Doorbell Interrupt's bit 2..7 be zero, got " > - "0x%2.2" PRIx8 " instead", doorbell_int_flags); > - } > +static void extended_pcc_test(fwts_framework *fw, fwts_acpi_table_pcct_subspace_type_3_4 *entry, bool *passed) > +{ > + fwts_log_info_verbatim(fw, " Platform Interrupt: 0x%8.8" PRIx32, entry->platform_interrupt); > + platform_interrupt_flags(fw, entry->platform_interrupt_flags, passed); > + fwts_log_info_verbatim(fw, " Reserved: 0x%2.2" PRIx8, entry->reserved1); > + fwts_log_info_verbatim(fw, " Base Address: 0x%16.16" PRIx64, entry->base_address); > + memory_length(fw, entry->header.type, entry->length, 16, passed); > + fwts_log_info_verbatim(fw, " Doorbell Register:"); > + gas_messages(fw, entry->header.type, &entry->doorbell_register, passed); > + fwts_log_info_verbatim(fw, " Doorbell Preserve: 0x%16.16" PRIx64, entry->doorbell_preserve); > + fwts_log_info_verbatim(fw, " Doorbell Write: 0x%16.16" PRIx64, entry->doorbell_write); > + fwts_log_info_verbatim(fw, " Nominal Latency: 0x%8.8" PRIx32, entry->nominal_latency); > + fwts_log_info_verbatim(fw, " Max Periodic Access Rate: 0x%8.8" PRIx32, entry->max_periodic_access_rate); > + fwts_log_info_verbatim(fw, " Min Request Turnaround Time: 0x%8.8" PRIx32, entry->min_request_turnaround_time); > + fwts_log_info_verbatim(fw, " Command Complete Check Register:"); > + gas_messages(fw, entry->header.type, &entry->platform_ack_register, passed); > + fwts_log_info_verbatim(fw, " Doorbell Ack Preserve: 0x%16.16" PRIx64, entry->platform_ack_preserve); > + fwts_log_info_verbatim(fw, " Doorbell Ack Write: 0x%16.16" PRIx64, entry->platform_ack_write); > + fwts_log_info_verbatim(fw, " Reserved: 0x%16.16" PRIx64, entry->reserved2); > + fwts_log_info_verbatim(fw, " Cmd Complete Check Register:"); > + gas_messages(fw, entry->header.type, &entry->cmd_complete_register, passed); > + fwts_log_info_verbatim(fw, " Cmd Complete Check Mask: 0x%16.16" PRIx64, entry->cmd_complete_mask); > + fwts_log_info_verbatim(fw, " Cmd Complete Update Register:"); > + gas_messages(fw, entry->header.type, &entry->cmd_update_register, passed); > + fwts_log_info_verbatim(fw, " Cmd Complete Update Mask: 0x%16.16" PRIx64, entry->cmd_update_preserve_mask); > + fwts_log_info_verbatim(fw, " Cmd Complete Set Mask: 0x%16.16" PRIx64, entry->cmd_update_preserve_mask); > + fwts_log_info_verbatim(fw, " Error Status Register:"); > + gas_messages(fw, entry->header.type, &entry->error_status_register, passed); > + fwts_log_info_verbatim(fw, " Error Status Mask: 0x%16.16" PRIx64, entry->error_status_mask); > } > > static int pcct_test1(fwts_framework *fw) > @@ -206,10 +227,10 @@ static int pcct_test1(fwts_framework *fw) > if ((pcct->flags & ~0x01) != 0) { > passed = false; > fwts_failed(fw, LOG_LEVEL_HIGH, > - "PCCTReservedNonZero", > + "PCCTBadFlags", > "PCCT flags field's bit 1..31 be zero, got " > "0x%8.8" PRIx32 " instead", pcct->flags); > - } > + } > > if (pcct->reserved != 0) { > passed = false; > @@ -223,7 +244,6 @@ static int pcct_test1(fwts_framework *fw) > pcct_sub = (fwts_acpi_table_pcct_subspace_header *) (table->data + offset); > > while (offset < table->length) { > - uint64_t addr_length = 8; > > fwts_log_info_verbatim(fw, " PCC Subspace Structure:"); > fwts_log_info_verbatim(fw, " Type: 0x%2.2" PRIx8, pcct_sub->type); > @@ -238,7 +258,6 @@ static int pcct_test1(fwts_framework *fw) > } > > generic_comm_test(fw, subspace, &passed); > - addr_length = subspace->length; > > } else if (pcct_sub->type == 1) { > fwts_acpi_table_pcct_subspace_type_1 *subspace = (fwts_acpi_table_pcct_subspace_type_1 *) pcct_sub; > @@ -249,7 +268,6 @@ static int pcct_test1(fwts_framework *fw) > } > > hw_reduced_comm_test_type1(fw, subspace, &passed); > - addr_length = subspace->length; > > } else if (pcct_sub->type == 2) { > fwts_acpi_table_pcct_subspace_type_2 *subspace = (fwts_acpi_table_pcct_subspace_type_2 *) pcct_sub; > @@ -260,26 +278,44 @@ static int pcct_test1(fwts_framework *fw) > } > > hw_reduced_comm_test_type2(fw, subspace, &passed); > - addr_length = subspace->length; > + > + } 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 Plaform 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..2, got " > + "PCCT Subspace Structure supports type 0..4, got " > "0x%2.2" PRIx8 " instead", pcct_sub->type); > + break; > } > > - if (addr_length <= 8) { > - passed = false; > - fwts_failed(fw, LOG_LEVEL_HIGH, > - "PCCTBadSubtypeMemoryLength", > - "PCCT Subspace Structure must have memory length > 8, got " > - "0x%16.16" PRIx64 " instead", addr_length); > - } > - > - > - > fwts_log_nl(fw); > > offset += pcct_sub->length; > diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h > index 12d63aa..5484cf3 100644 > --- a/src/lib/include/fwts_acpi.h > +++ b/src/lib/include/fwts_acpi.h > @@ -1380,8 +1380,8 @@ typedef struct { > > typedef struct { > fwts_acpi_table_pcct_subspace_header header; > - uint32_t doorbell_interrupt; > - uint8_t doorbell_interrupt_flags; > + uint32_t platform_interrupt; > + uint8_t platform_interrupt_flags; > uint8_t reserved; > uint64_t base_address; > uint64_t length; > @@ -1395,8 +1395,8 @@ typedef struct { > > typedef struct { > fwts_acpi_table_pcct_subspace_header header; > - uint32_t doorbell_interrupt; > - uint8_t doorbell_interrupt_flags; > + uint32_t platform_interrupt; > + uint8_t platform_interrupt_flags; > uint8_t reserved; > uint64_t base_address; > uint64_t length; > @@ -1406,11 +1406,37 @@ typedef struct { > uint32_t nominal_latency; > uint32_t max_periodic_access_rate; > uint16_t min_request_turnaround_time; > - fwts_acpi_gas doorbell_ack_register; > - uint64_t doorbell_ack_preserve; > - uint64_t doorbell_ack_write; > + fwts_acpi_gas platform_ack_register; > + uint64_t platform_ack_preserve; > + uint64_t platform_ack_write; > } __attribute__ ((packed)) fwts_acpi_table_pcct_subspace_type_2; > > +typedef struct { > + fwts_acpi_table_pcct_subspace_header header; > + uint32_t platform_interrupt; > + uint8_t platform_interrupt_flags; > + uint8_t reserved1; > + uint64_t base_address; > + uint32_t length; > + fwts_acpi_gas doorbell_register; > + uint64_t doorbell_preserve; > + uint64_t doorbell_write; > + uint32_t nominal_latency; > + uint32_t max_periodic_access_rate; > + uint32_t min_request_turnaround_time; > + fwts_acpi_gas platform_ack_register; > + uint64_t platform_ack_preserve; > + uint64_t platform_ack_write; > + uint64_t reserved2; > + fwts_acpi_gas cmd_complete_register; > + uint64_t cmd_complete_mask; > + fwts_acpi_gas cmd_update_register; > + uint64_t cmd_update_preserve_mask; > + uint64_t cmd_update_set_mask; > + fwts_acpi_gas error_status_register; > + uint64_t error_status_mask; > +} __attribute__ ((packed)) fwts_acpi_table_pcct_subspace_type_3_4; > + > /* > * ACPI SPCR (Serial Port Console Redirection Table) > * http://msdn.microsoft.com/en-us/library/windows/hardware/dn639132(v=vs.85).aspx > Acked-by: Colin Ian King <colin.king@canonical.com>
On 08/18/2017 02:39 AM, Alex Hung wrote: > 1. Added type 3 & type 4 > 2. Updated doorbell to platform in some cases > 3. Fixed typos > > Signed-off-by: Alex Hung <alex.hung@canonical.com> > --- > src/acpi/pcct/pcct.c | 232 +++++++++++++++++++++++++------------------- > src/lib/include/fwts_acpi.h | 40 ++++++-- > 2 files changed, 167 insertions(+), 105 deletions(-) > > diff --git a/src/acpi/pcct/pcct.c b/src/acpi/pcct/pcct.c > index 9d79dc5..5753325 100644 > --- a/src/acpi/pcct/pcct.c > +++ b/src/acpi/pcct/pcct.c > @@ -52,6 +52,64 @@ static bool subspace_length_equal(fwts_framework *fw, uint8_t type, uint8_t type > return true; > } > > +static void platform_interrupt_flags(fwts_framework *fw, uint8_t flags, bool *passed) > +{ > + fwts_log_info_verbatim(fw, " Platform Interrupt Flags: 0x%2.2" PRIx8, flags); > + > + if (flags & ~0x3) { > + *passed = false; > + fwts_failed(fw, LOG_LEVEL_HIGH, > + "PCCTBadSubtypePlatformbInterruptlags", > + "PCCT Subspace Platform Interrupt Flags's bit [7:2] be zero, got " > + "0x%2.2" PRIx8 " instead", flags); > + } > +} > + > +static void gas_messages(fwts_framework *fw, uint8_t type, fwts_acpi_gas *gas, bool *passed) > +{ > + fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas->address_space_id); > + fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas->register_bit_width); > + fwts_log_info_verbatim(fw, " Register Bit Offset 0x%2.2" PRIx8, gas->register_bit_offset); > + fwts_log_info_verbatim(fw, " Access Size 0x%2.2" PRIx8, gas->access_width); > + fwts_log_info_verbatim(fw, " Address 0x%16.16" PRIx64, gas->address); > + > + if ((gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_IO) && > + (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_MEMORY) && > + (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_FFH)) { > + *passed = false; > + fwts_failed(fw, LOG_LEVEL_HIGH, > + "PCCTSubspaceInvalidAddrSpaceID", > + "PCCT Subspace Type %" PRId8 " has space ID = %" PRId8 > + " which is not System I/O, Memory or FFH", type, gas->address_space_id); > + } > +} > + > +static void memory_length(fwts_framework *fw, uint8_t type, uint64_t memory_range, uint64_t min_length, bool *passed) > +{ > + switch (type) { > + case 0 ... 2: > + fwts_log_info_verbatim(fw, " Length: 0x%16.16" PRIx64, memory_range); > + if (memory_range <= min_length) { > + *passed = false; > + fwts_failed(fw, LOG_LEVEL_HIGH, > + "PCCTBadSubtypeMemoryLength", > + "PCCT Subspace Type %" PRId8 " must have memory length > 0x%16.16" PRIx64 > + ", got 0x%16.16" PRIx64 " instead", type, min_length, memory_range); > + } > + break; > + case 3 ... 4: > + fwts_log_info_verbatim(fw, " Length: 0x%8.8" PRIx32, (uint32_t)memory_range); > + if (memory_range <= min_length) { > + *passed = false; > + fwts_failed(fw, LOG_LEVEL_HIGH, > + "PCCTBadSubtypeMemoryLength", > + "PCCT Subspace Type %" PRId8 " must have memory length > 0x%8.8" PRIx32 > + ", got 0x%8.8" PRIx32 " instead", type, (uint32_t)min_length, (uint32_t)memory_range); > + } > + break; > + } > +} > + > static void generic_comm_test(fwts_framework *fw, fwts_acpi_table_pcct_subspace_type_0 *entry, bool *passed) > { > fwts_acpi_gas *gas = &entry->doorbell_register; > @@ -63,7 +121,7 @@ static void generic_comm_test(fwts_framework *fw, fwts_acpi_table_pcct_subspace_ > > fwts_log_info_verbatim(fw, " Reserved: 0x%16.16" PRIx64, reserved); > fwts_log_info_verbatim(fw, " Base Address: 0x%16.16" PRIx64, entry->base_address); > - fwts_log_info_verbatim(fw, " Length: 0x%16.16" PRIx64, entry->length); > + memory_length(fw, entry->header.type, entry->length, 8, passed); > fwts_log_info_verbatim(fw, " Doorbell Register:"); > fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas->address_space_id); > fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas->register_bit_width); > @@ -82,113 +140,76 @@ static void generic_comm_test(fwts_framework *fw, fwts_acpi_table_pcct_subspace_ > fwts_failed(fw, LOG_LEVEL_HIGH, > "PCCTSubspaceInvalidAddrSpaceID", > "PCCT Subspace Type 0 has space ID = 0x%2.2" PRIx8 > - " which is not System I/O Space or System Memory Space", > + " which is not System I/O or Memory", > gas->address_space_id); > } > } > > static void hw_reduced_comm_test_type1(fwts_framework *fw, fwts_acpi_table_pcct_subspace_type_1 *entry, bool *passed) > { > - fwts_acpi_gas *gas = &entry->doorbell_register; > - uint8_t doorbell_int_flags = entry->doorbell_interrupt_flags; > - > - fwts_log_info_verbatim(fw, " Doorbell Interrupt: 0x%8.8" PRIx32, entry->doorbell_interrupt); > - fwts_log_info_verbatim(fw, " Doorbell Interrupt Flags: 0x%2.2" PRIx8, entry->doorbell_interrupt_flags); > + fwts_log_info_verbatim(fw, " Platform Interrupt: 0x%8.8" PRIx32, entry->platform_interrupt); > + platform_interrupt_flags(fw, entry->platform_interrupt_flags, passed); > fwts_log_info_verbatim(fw, " Reserved: 0x%2.2" PRIx8, entry->reserved); > fwts_log_info_verbatim(fw, " Base Address: 0x%16.16" PRIx64, entry->base_address); > - fwts_log_info_verbatim(fw, " Length: 0x%16.16" PRIx64, entry->length); > + memory_length(fw, entry->header.type, entry->length, 8, passed); > fwts_log_info_verbatim(fw, " Doorbell Register:"); > - fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas->address_space_id); > - fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas->register_bit_width); > - fwts_log_info_verbatim(fw, " Register Bit Offset 0x%2.2" PRIx8, gas->register_bit_offset); > - fwts_log_info_verbatim(fw, " Access Size 0x%2.2" PRIx8, gas->access_width); > - fwts_log_info_verbatim(fw, " Address 0x%16.16" PRIx64, gas->address); > + gas_messages(fw, entry->header.type, &entry->doorbell_register, passed); > fwts_log_info_verbatim(fw, " Doorbell Preserve: 0x%16.16" PRIx64, entry->doorbell_preserve); > fwts_log_info_verbatim(fw, " Doorbell Write: 0x%16.16" PRIx64, entry->doorbell_write); > fwts_log_info_verbatim(fw, " Nominal Latency: 0x%8.8" PRIx32, entry->nominal_latency); > fwts_log_info_verbatim(fw, " Max Periodic Access Rate: 0x%8.8" PRIx32, entry->max_periodic_access_rate); > fwts_log_info_verbatim(fw, " Min Request Turnaround Time: 0x%8.8" PRIx32, entry->min_request_turnaround_time); > - > - if ((gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_IO) && > - (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_MEMORY) && > - (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_FFH)) { > - *passed = false; > - fwts_failed(fw, LOG_LEVEL_HIGH, > - "PCCTSubspaceInvalidAddrSpaceID", > - "PCCT Subspace Type 1 has space ID = 0x%2.2" PRIx8 > - " which is not System I/O Space or System Memory Space", > - gas->address_space_id); > - } > - > - if (doorbell_int_flags & ~0x3) { > - *passed = false; > - fwts_failed(fw, LOG_LEVEL_HIGH, > - "PCCTBadSubtypeDoorbellFlags", > - "PCCT Subspace Doorbell Interrupt's bit 2..7 be zero, got " > - "0x%2.2" PRIx8 " instead", doorbell_int_flags); > - } > } > > static void hw_reduced_comm_test_type2(fwts_framework *fw, fwts_acpi_table_pcct_subspace_type_2 *entry, bool *passed) > { > - fwts_acpi_gas *gas = &entry->doorbell_register; > - fwts_acpi_gas *gas2 = &entry->doorbell_ack_register; > - uint8_t doorbell_int_flags = entry->doorbell_interrupt_flags; > - > - fwts_log_info_verbatim(fw, " Doorbell Interrupt: 0x%8.8" PRIx32, entry->doorbell_interrupt); > - fwts_log_info_verbatim(fw, " Doorbell Interrupt Flags: 0x%2.2" PRIx8, entry->doorbell_interrupt_flags); > + fwts_log_info_verbatim(fw, " Platform Interrupt: 0x%8.8" PRIx32, entry->platform_interrupt); > + platform_interrupt_flags(fw, entry->platform_interrupt_flags, passed); > fwts_log_info_verbatim(fw, " Reserved: 0x%2.2" PRIx8, entry->reserved); > fwts_log_info_verbatim(fw, " Base Address: 0x%16.16" PRIx64, entry->base_address); > - fwts_log_info_verbatim(fw, " Length: 0x%16.16" PRIx64, entry->length); > + memory_length(fw, entry->header.type, entry->length, 8, passed); > fwts_log_info_verbatim(fw, " Doorbell Register:"); > - fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas->address_space_id); > - fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas->register_bit_width); > - fwts_log_info_verbatim(fw, " Register Bit Offset 0x%2.2" PRIx8, gas->register_bit_offset); > - fwts_log_info_verbatim(fw, " Access Size 0x%2.2" PRIx8, gas->access_width); > - fwts_log_info_verbatim(fw, " Address 0x%16.16" PRIx64, gas->address); > + gas_messages(fw, entry->header.type, &entry->doorbell_register, passed); > fwts_log_info_verbatim(fw, " Doorbell Preserve: 0x%16.16" PRIx64, entry->doorbell_preserve); > fwts_log_info_verbatim(fw, " Doorbell Write: 0x%16.16" PRIx64, entry->doorbell_write); > fwts_log_info_verbatim(fw, " Nominal Latency: 0x%8.8" PRIx32, entry->nominal_latency); > fwts_log_info_verbatim(fw, " Max Periodic Access Rate: 0x%8.8" PRIx32, entry->max_periodic_access_rate); > fwts_log_info_verbatim(fw, " Min Request Turnaround Time: 0x%8.8" PRIx32, entry->min_request_turnaround_time); > - fwts_log_info_verbatim(fw, " Doorbell Ack Register:"); > - fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas2->address_space_id); > - fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas2->register_bit_width); > - fwts_log_info_verbatim(fw, " Register Bit Offset 0x%2.2" PRIx8, gas2->register_bit_offset); > - fwts_log_info_verbatim(fw, " Access Size 0x%2.2" PRIx8, gas2->access_width); > - fwts_log_info_verbatim(fw, " Address 0x%16.16" PRIx64, gas2->address); > - fwts_log_info_verbatim(fw, " Doorbell Ack Preserve: 0x%16.16" PRIx64, entry->doorbell_ack_preserve); > - fwts_log_info_verbatim(fw, " Doorbell Ack Write: 0x%16.16" PRIx64, entry->doorbell_ack_write); > - > - if ((gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_IO) && > - (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_MEMORY) && > - (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_FFH)) { > - *passed = false; > - fwts_failed(fw, LOG_LEVEL_HIGH, > - "PCCTSubspaceInvalidAddrSpaceID", > - "PCCT Subspace Type 2 has space ID = 0x%2.2" PRIx8 > - " which is not System I/O Space or System Memory Space", > - gas->address_space_id); > - } > - > - if ((gas2->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_IO) && > - (gas2->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_MEMORY) && > - (gas2->address_space_id != FWTS_GAS_ADDR_SPACE_ID_FFH)) { > - *passed = false; > - fwts_failed(fw, LOG_LEVEL_HIGH, > - "PCCTSubspaceInvalidAddrSpaceID", > - "PCCT Subspace Type 2 has space ID = 0x%2.2" PRIx8 > - " which is not System I/O Space or System Memory Space", > - gas->address_space_id); > - } > + fwts_log_info_verbatim(fw, " Platform Interrupt Ack Register:"); > + gas_messages(fw, entry->header.type, &entry->platform_ack_register, passed); > + fwts_log_info_verbatim(fw, " Platform Ack Preserve: 0x%16.16" PRIx64, entry->platform_ack_preserve); > + fwts_log_info_verbatim(fw, " Platform Ack Write: 0x%16.16" PRIx64, entry->platform_ack_write); > +} > > - if (doorbell_int_flags & ~0x3) { > - *passed = false; > - fwts_failed(fw, LOG_LEVEL_HIGH, > - "PCCTBadSubtypeDoorbellFlags", > - "PCCT Subspace Doorbell Interrupt's bit 2..7 be zero, got " > - "0x%2.2" PRIx8 " instead", doorbell_int_flags); > - } > +static void extended_pcc_test(fwts_framework *fw, fwts_acpi_table_pcct_subspace_type_3_4 *entry, bool *passed) > +{ > + fwts_log_info_verbatim(fw, " Platform Interrupt: 0x%8.8" PRIx32, entry->platform_interrupt); > + platform_interrupt_flags(fw, entry->platform_interrupt_flags, passed); > + fwts_log_info_verbatim(fw, " Reserved: 0x%2.2" PRIx8, entry->reserved1); > + fwts_log_info_verbatim(fw, " Base Address: 0x%16.16" PRIx64, entry->base_address); > + memory_length(fw, entry->header.type, entry->length, 16, passed); > + fwts_log_info_verbatim(fw, " Doorbell Register:"); > + gas_messages(fw, entry->header.type, &entry->doorbell_register, passed); > + fwts_log_info_verbatim(fw, " Doorbell Preserve: 0x%16.16" PRIx64, entry->doorbell_preserve); > + fwts_log_info_verbatim(fw, " Doorbell Write: 0x%16.16" PRIx64, entry->doorbell_write); > + fwts_log_info_verbatim(fw, " Nominal Latency: 0x%8.8" PRIx32, entry->nominal_latency); > + fwts_log_info_verbatim(fw, " Max Periodic Access Rate: 0x%8.8" PRIx32, entry->max_periodic_access_rate); > + fwts_log_info_verbatim(fw, " Min Request Turnaround Time: 0x%8.8" PRIx32, entry->min_request_turnaround_time); > + fwts_log_info_verbatim(fw, " Command Complete Check Register:"); > + gas_messages(fw, entry->header.type, &entry->platform_ack_register, passed); > + fwts_log_info_verbatim(fw, " Doorbell Ack Preserve: 0x%16.16" PRIx64, entry->platform_ack_preserve); > + fwts_log_info_verbatim(fw, " Doorbell Ack Write: 0x%16.16" PRIx64, entry->platform_ack_write); > + fwts_log_info_verbatim(fw, " Reserved: 0x%16.16" PRIx64, entry->reserved2); > + fwts_log_info_verbatim(fw, " Cmd Complete Check Register:"); > + gas_messages(fw, entry->header.type, &entry->cmd_complete_register, passed); > + fwts_log_info_verbatim(fw, " Cmd Complete Check Mask: 0x%16.16" PRIx64, entry->cmd_complete_mask); > + fwts_log_info_verbatim(fw, " Cmd Complete Update Register:"); > + gas_messages(fw, entry->header.type, &entry->cmd_update_register, passed); > + fwts_log_info_verbatim(fw, " Cmd Complete Update Mask: 0x%16.16" PRIx64, entry->cmd_update_preserve_mask); > + fwts_log_info_verbatim(fw, " Cmd Complete Set Mask: 0x%16.16" PRIx64, entry->cmd_update_preserve_mask); > + fwts_log_info_verbatim(fw, " Error Status Register:"); > + gas_messages(fw, entry->header.type, &entry->error_status_register, passed); > + fwts_log_info_verbatim(fw, " Error Status Mask: 0x%16.16" PRIx64, entry->error_status_mask); > } > > static int pcct_test1(fwts_framework *fw) > @@ -206,10 +227,10 @@ static int pcct_test1(fwts_framework *fw) > if ((pcct->flags & ~0x01) != 0) { > passed = false; > fwts_failed(fw, LOG_LEVEL_HIGH, > - "PCCTReservedNonZero", > + "PCCTBadFlags", > "PCCT flags field's bit 1..31 be zero, got " > "0x%8.8" PRIx32 " instead", pcct->flags); > - } > + } > > if (pcct->reserved != 0) { > passed = false; > @@ -223,7 +244,6 @@ static int pcct_test1(fwts_framework *fw) > pcct_sub = (fwts_acpi_table_pcct_subspace_header *) (table->data + offset); > > while (offset < table->length) { > - uint64_t addr_length = 8; > > fwts_log_info_verbatim(fw, " PCC Subspace Structure:"); > fwts_log_info_verbatim(fw, " Type: 0x%2.2" PRIx8, pcct_sub->type); > @@ -238,7 +258,6 @@ static int pcct_test1(fwts_framework *fw) > } > > generic_comm_test(fw, subspace, &passed); > - addr_length = subspace->length; > > } else if (pcct_sub->type == 1) { > fwts_acpi_table_pcct_subspace_type_1 *subspace = (fwts_acpi_table_pcct_subspace_type_1 *) pcct_sub; > @@ -249,7 +268,6 @@ static int pcct_test1(fwts_framework *fw) > } > > hw_reduced_comm_test_type1(fw, subspace, &passed); > - addr_length = subspace->length; > > } else if (pcct_sub->type == 2) { > fwts_acpi_table_pcct_subspace_type_2 *subspace = (fwts_acpi_table_pcct_subspace_type_2 *) pcct_sub; > @@ -260,26 +278,44 @@ static int pcct_test1(fwts_framework *fw) > } > > hw_reduced_comm_test_type2(fw, subspace, &passed); > - addr_length = subspace->length; > + > + } 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 Plaform 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..2, got " > + "PCCT Subspace Structure supports type 0..4, got " > "0x%2.2" PRIx8 " instead", pcct_sub->type); > + break; > } > > - if (addr_length <= 8) { > - passed = false; > - fwts_failed(fw, LOG_LEVEL_HIGH, > - "PCCTBadSubtypeMemoryLength", > - "PCCT Subspace Structure must have memory length > 8, got " > - "0x%16.16" PRIx64 " instead", addr_length); > - } > - > - > - > fwts_log_nl(fw); > > offset += pcct_sub->length; > diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h > index 12d63aa..5484cf3 100644 > --- a/src/lib/include/fwts_acpi.h > +++ b/src/lib/include/fwts_acpi.h > @@ -1380,8 +1380,8 @@ typedef struct { > > typedef struct { > fwts_acpi_table_pcct_subspace_header header; > - uint32_t doorbell_interrupt; > - uint8_t doorbell_interrupt_flags; > + uint32_t platform_interrupt; > + uint8_t platform_interrupt_flags; > uint8_t reserved; > uint64_t base_address; > uint64_t length; > @@ -1395,8 +1395,8 @@ typedef struct { > > typedef struct { > fwts_acpi_table_pcct_subspace_header header; > - uint32_t doorbell_interrupt; > - uint8_t doorbell_interrupt_flags; > + uint32_t platform_interrupt; > + uint8_t platform_interrupt_flags; > uint8_t reserved; > uint64_t base_address; > uint64_t length; > @@ -1406,11 +1406,37 @@ typedef struct { > uint32_t nominal_latency; > uint32_t max_periodic_access_rate; > uint16_t min_request_turnaround_time; > - fwts_acpi_gas doorbell_ack_register; > - uint64_t doorbell_ack_preserve; > - uint64_t doorbell_ack_write; > + fwts_acpi_gas platform_ack_register; > + uint64_t platform_ack_preserve; > + uint64_t platform_ack_write; > } __attribute__ ((packed)) fwts_acpi_table_pcct_subspace_type_2; > > +typedef struct { > + fwts_acpi_table_pcct_subspace_header header; > + uint32_t platform_interrupt; > + uint8_t platform_interrupt_flags; > + uint8_t reserved1; > + uint64_t base_address; > + uint32_t length; > + fwts_acpi_gas doorbell_register; > + uint64_t doorbell_preserve; > + uint64_t doorbell_write; > + uint32_t nominal_latency; > + uint32_t max_periodic_access_rate; > + uint32_t min_request_turnaround_time; > + fwts_acpi_gas platform_ack_register; > + uint64_t platform_ack_preserve; > + uint64_t platform_ack_write; > + uint64_t reserved2; > + fwts_acpi_gas cmd_complete_register; > + uint64_t cmd_complete_mask; > + fwts_acpi_gas cmd_update_register; > + uint64_t cmd_update_preserve_mask; > + uint64_t cmd_update_set_mask; > + fwts_acpi_gas error_status_register; > + uint64_t error_status_mask; > +} __attribute__ ((packed)) fwts_acpi_table_pcct_subspace_type_3_4; > + > /* > * ACPI SPCR (Serial Port Console Redirection Table) > * http://msdn.microsoft.com/en-us/library/windows/hardware/dn639132(v=vs.85).aspx > Acked-by: Ivan Hu <ivan.hu@canonical.com>
diff --git a/src/acpi/pcct/pcct.c b/src/acpi/pcct/pcct.c index 9d79dc5..5753325 100644 --- a/src/acpi/pcct/pcct.c +++ b/src/acpi/pcct/pcct.c @@ -52,6 +52,64 @@ static bool subspace_length_equal(fwts_framework *fw, uint8_t type, uint8_t type return true; } +static void platform_interrupt_flags(fwts_framework *fw, uint8_t flags, bool *passed) +{ + fwts_log_info_verbatim(fw, " Platform Interrupt Flags: 0x%2.2" PRIx8, flags); + + if (flags & ~0x3) { + *passed = false; + fwts_failed(fw, LOG_LEVEL_HIGH, + "PCCTBadSubtypePlatformbInterruptlags", + "PCCT Subspace Platform Interrupt Flags's bit [7:2] be zero, got " + "0x%2.2" PRIx8 " instead", flags); + } +} + +static void gas_messages(fwts_framework *fw, uint8_t type, fwts_acpi_gas *gas, bool *passed) +{ + fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas->address_space_id); + fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas->register_bit_width); + fwts_log_info_verbatim(fw, " Register Bit Offset 0x%2.2" PRIx8, gas->register_bit_offset); + fwts_log_info_verbatim(fw, " Access Size 0x%2.2" PRIx8, gas->access_width); + fwts_log_info_verbatim(fw, " Address 0x%16.16" PRIx64, gas->address); + + if ((gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_IO) && + (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_MEMORY) && + (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_FFH)) { + *passed = false; + fwts_failed(fw, LOG_LEVEL_HIGH, + "PCCTSubspaceInvalidAddrSpaceID", + "PCCT Subspace Type %" PRId8 " has space ID = %" PRId8 + " which is not System I/O, Memory or FFH", type, gas->address_space_id); + } +} + +static void memory_length(fwts_framework *fw, uint8_t type, uint64_t memory_range, uint64_t min_length, bool *passed) +{ + switch (type) { + case 0 ... 2: + fwts_log_info_verbatim(fw, " Length: 0x%16.16" PRIx64, memory_range); + if (memory_range <= min_length) { + *passed = false; + fwts_failed(fw, LOG_LEVEL_HIGH, + "PCCTBadSubtypeMemoryLength", + "PCCT Subspace Type %" PRId8 " must have memory length > 0x%16.16" PRIx64 + ", got 0x%16.16" PRIx64 " instead", type, min_length, memory_range); + } + break; + case 3 ... 4: + fwts_log_info_verbatim(fw, " Length: 0x%8.8" PRIx32, (uint32_t)memory_range); + if (memory_range <= min_length) { + *passed = false; + fwts_failed(fw, LOG_LEVEL_HIGH, + "PCCTBadSubtypeMemoryLength", + "PCCT Subspace Type %" PRId8 " must have memory length > 0x%8.8" PRIx32 + ", got 0x%8.8" PRIx32 " instead", type, (uint32_t)min_length, (uint32_t)memory_range); + } + break; + } +} + static void generic_comm_test(fwts_framework *fw, fwts_acpi_table_pcct_subspace_type_0 *entry, bool *passed) { fwts_acpi_gas *gas = &entry->doorbell_register; @@ -63,7 +121,7 @@ static void generic_comm_test(fwts_framework *fw, fwts_acpi_table_pcct_subspace_ fwts_log_info_verbatim(fw, " Reserved: 0x%16.16" PRIx64, reserved); fwts_log_info_verbatim(fw, " Base Address: 0x%16.16" PRIx64, entry->base_address); - fwts_log_info_verbatim(fw, " Length: 0x%16.16" PRIx64, entry->length); + memory_length(fw, entry->header.type, entry->length, 8, passed); fwts_log_info_verbatim(fw, " Doorbell Register:"); fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas->address_space_id); fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas->register_bit_width); @@ -82,113 +140,76 @@ static void generic_comm_test(fwts_framework *fw, fwts_acpi_table_pcct_subspace_ fwts_failed(fw, LOG_LEVEL_HIGH, "PCCTSubspaceInvalidAddrSpaceID", "PCCT Subspace Type 0 has space ID = 0x%2.2" PRIx8 - " which is not System I/O Space or System Memory Space", + " which is not System I/O or Memory", gas->address_space_id); } } static void hw_reduced_comm_test_type1(fwts_framework *fw, fwts_acpi_table_pcct_subspace_type_1 *entry, bool *passed) { - fwts_acpi_gas *gas = &entry->doorbell_register; - uint8_t doorbell_int_flags = entry->doorbell_interrupt_flags; - - fwts_log_info_verbatim(fw, " Doorbell Interrupt: 0x%8.8" PRIx32, entry->doorbell_interrupt); - fwts_log_info_verbatim(fw, " Doorbell Interrupt Flags: 0x%2.2" PRIx8, entry->doorbell_interrupt_flags); + fwts_log_info_verbatim(fw, " Platform Interrupt: 0x%8.8" PRIx32, entry->platform_interrupt); + platform_interrupt_flags(fw, entry->platform_interrupt_flags, passed); fwts_log_info_verbatim(fw, " Reserved: 0x%2.2" PRIx8, entry->reserved); fwts_log_info_verbatim(fw, " Base Address: 0x%16.16" PRIx64, entry->base_address); - fwts_log_info_verbatim(fw, " Length: 0x%16.16" PRIx64, entry->length); + memory_length(fw, entry->header.type, entry->length, 8, passed); fwts_log_info_verbatim(fw, " Doorbell Register:"); - fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas->address_space_id); - fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas->register_bit_width); - fwts_log_info_verbatim(fw, " Register Bit Offset 0x%2.2" PRIx8, gas->register_bit_offset); - fwts_log_info_verbatim(fw, " Access Size 0x%2.2" PRIx8, gas->access_width); - fwts_log_info_verbatim(fw, " Address 0x%16.16" PRIx64, gas->address); + gas_messages(fw, entry->header.type, &entry->doorbell_register, passed); fwts_log_info_verbatim(fw, " Doorbell Preserve: 0x%16.16" PRIx64, entry->doorbell_preserve); fwts_log_info_verbatim(fw, " Doorbell Write: 0x%16.16" PRIx64, entry->doorbell_write); fwts_log_info_verbatim(fw, " Nominal Latency: 0x%8.8" PRIx32, entry->nominal_latency); fwts_log_info_verbatim(fw, " Max Periodic Access Rate: 0x%8.8" PRIx32, entry->max_periodic_access_rate); fwts_log_info_verbatim(fw, " Min Request Turnaround Time: 0x%8.8" PRIx32, entry->min_request_turnaround_time); - - if ((gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_IO) && - (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_MEMORY) && - (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_FFH)) { - *passed = false; - fwts_failed(fw, LOG_LEVEL_HIGH, - "PCCTSubspaceInvalidAddrSpaceID", - "PCCT Subspace Type 1 has space ID = 0x%2.2" PRIx8 - " which is not System I/O Space or System Memory Space", - gas->address_space_id); - } - - if (doorbell_int_flags & ~0x3) { - *passed = false; - fwts_failed(fw, LOG_LEVEL_HIGH, - "PCCTBadSubtypeDoorbellFlags", - "PCCT Subspace Doorbell Interrupt's bit 2..7 be zero, got " - "0x%2.2" PRIx8 " instead", doorbell_int_flags); - } } static void hw_reduced_comm_test_type2(fwts_framework *fw, fwts_acpi_table_pcct_subspace_type_2 *entry, bool *passed) { - fwts_acpi_gas *gas = &entry->doorbell_register; - fwts_acpi_gas *gas2 = &entry->doorbell_ack_register; - uint8_t doorbell_int_flags = entry->doorbell_interrupt_flags; - - fwts_log_info_verbatim(fw, " Doorbell Interrupt: 0x%8.8" PRIx32, entry->doorbell_interrupt); - fwts_log_info_verbatim(fw, " Doorbell Interrupt Flags: 0x%2.2" PRIx8, entry->doorbell_interrupt_flags); + fwts_log_info_verbatim(fw, " Platform Interrupt: 0x%8.8" PRIx32, entry->platform_interrupt); + platform_interrupt_flags(fw, entry->platform_interrupt_flags, passed); fwts_log_info_verbatim(fw, " Reserved: 0x%2.2" PRIx8, entry->reserved); fwts_log_info_verbatim(fw, " Base Address: 0x%16.16" PRIx64, entry->base_address); - fwts_log_info_verbatim(fw, " Length: 0x%16.16" PRIx64, entry->length); + memory_length(fw, entry->header.type, entry->length, 8, passed); fwts_log_info_verbatim(fw, " Doorbell Register:"); - fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas->address_space_id); - fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas->register_bit_width); - fwts_log_info_verbatim(fw, " Register Bit Offset 0x%2.2" PRIx8, gas->register_bit_offset); - fwts_log_info_verbatim(fw, " Access Size 0x%2.2" PRIx8, gas->access_width); - fwts_log_info_verbatim(fw, " Address 0x%16.16" PRIx64, gas->address); + gas_messages(fw, entry->header.type, &entry->doorbell_register, passed); fwts_log_info_verbatim(fw, " Doorbell Preserve: 0x%16.16" PRIx64, entry->doorbell_preserve); fwts_log_info_verbatim(fw, " Doorbell Write: 0x%16.16" PRIx64, entry->doorbell_write); fwts_log_info_verbatim(fw, " Nominal Latency: 0x%8.8" PRIx32, entry->nominal_latency); fwts_log_info_verbatim(fw, " Max Periodic Access Rate: 0x%8.8" PRIx32, entry->max_periodic_access_rate); fwts_log_info_verbatim(fw, " Min Request Turnaround Time: 0x%8.8" PRIx32, entry->min_request_turnaround_time); - fwts_log_info_verbatim(fw, " Doorbell Ack Register:"); - fwts_log_info_verbatim(fw, " Address Space ID 0x%2.2" PRIx8, gas2->address_space_id); - fwts_log_info_verbatim(fw, " Register Bit Width 0x%2.2" PRIx8, gas2->register_bit_width); - fwts_log_info_verbatim(fw, " Register Bit Offset 0x%2.2" PRIx8, gas2->register_bit_offset); - fwts_log_info_verbatim(fw, " Access Size 0x%2.2" PRIx8, gas2->access_width); - fwts_log_info_verbatim(fw, " Address 0x%16.16" PRIx64, gas2->address); - fwts_log_info_verbatim(fw, " Doorbell Ack Preserve: 0x%16.16" PRIx64, entry->doorbell_ack_preserve); - fwts_log_info_verbatim(fw, " Doorbell Ack Write: 0x%16.16" PRIx64, entry->doorbell_ack_write); - - if ((gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_IO) && - (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_MEMORY) && - (gas->address_space_id != FWTS_GAS_ADDR_SPACE_ID_FFH)) { - *passed = false; - fwts_failed(fw, LOG_LEVEL_HIGH, - "PCCTSubspaceInvalidAddrSpaceID", - "PCCT Subspace Type 2 has space ID = 0x%2.2" PRIx8 - " which is not System I/O Space or System Memory Space", - gas->address_space_id); - } - - if ((gas2->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_IO) && - (gas2->address_space_id != FWTS_GAS_ADDR_SPACE_ID_SYSTEM_MEMORY) && - (gas2->address_space_id != FWTS_GAS_ADDR_SPACE_ID_FFH)) { - *passed = false; - fwts_failed(fw, LOG_LEVEL_HIGH, - "PCCTSubspaceInvalidAddrSpaceID", - "PCCT Subspace Type 2 has space ID = 0x%2.2" PRIx8 - " which is not System I/O Space or System Memory Space", - gas->address_space_id); - } + fwts_log_info_verbatim(fw, " Platform Interrupt Ack Register:"); + gas_messages(fw, entry->header.type, &entry->platform_ack_register, passed); + fwts_log_info_verbatim(fw, " Platform Ack Preserve: 0x%16.16" PRIx64, entry->platform_ack_preserve); + fwts_log_info_verbatim(fw, " Platform Ack Write: 0x%16.16" PRIx64, entry->platform_ack_write); +} - if (doorbell_int_flags & ~0x3) { - *passed = false; - fwts_failed(fw, LOG_LEVEL_HIGH, - "PCCTBadSubtypeDoorbellFlags", - "PCCT Subspace Doorbell Interrupt's bit 2..7 be zero, got " - "0x%2.2" PRIx8 " instead", doorbell_int_flags); - } +static void extended_pcc_test(fwts_framework *fw, fwts_acpi_table_pcct_subspace_type_3_4 *entry, bool *passed) +{ + fwts_log_info_verbatim(fw, " Platform Interrupt: 0x%8.8" PRIx32, entry->platform_interrupt); + platform_interrupt_flags(fw, entry->platform_interrupt_flags, passed); + fwts_log_info_verbatim(fw, " Reserved: 0x%2.2" PRIx8, entry->reserved1); + fwts_log_info_verbatim(fw, " Base Address: 0x%16.16" PRIx64, entry->base_address); + memory_length(fw, entry->header.type, entry->length, 16, passed); + fwts_log_info_verbatim(fw, " Doorbell Register:"); + gas_messages(fw, entry->header.type, &entry->doorbell_register, passed); + fwts_log_info_verbatim(fw, " Doorbell Preserve: 0x%16.16" PRIx64, entry->doorbell_preserve); + fwts_log_info_verbatim(fw, " Doorbell Write: 0x%16.16" PRIx64, entry->doorbell_write); + fwts_log_info_verbatim(fw, " Nominal Latency: 0x%8.8" PRIx32, entry->nominal_latency); + fwts_log_info_verbatim(fw, " Max Periodic Access Rate: 0x%8.8" PRIx32, entry->max_periodic_access_rate); + fwts_log_info_verbatim(fw, " Min Request Turnaround Time: 0x%8.8" PRIx32, entry->min_request_turnaround_time); + fwts_log_info_verbatim(fw, " Command Complete Check Register:"); + gas_messages(fw, entry->header.type, &entry->platform_ack_register, passed); + fwts_log_info_verbatim(fw, " Doorbell Ack Preserve: 0x%16.16" PRIx64, entry->platform_ack_preserve); + fwts_log_info_verbatim(fw, " Doorbell Ack Write: 0x%16.16" PRIx64, entry->platform_ack_write); + fwts_log_info_verbatim(fw, " Reserved: 0x%16.16" PRIx64, entry->reserved2); + fwts_log_info_verbatim(fw, " Cmd Complete Check Register:"); + gas_messages(fw, entry->header.type, &entry->cmd_complete_register, passed); + fwts_log_info_verbatim(fw, " Cmd Complete Check Mask: 0x%16.16" PRIx64, entry->cmd_complete_mask); + fwts_log_info_verbatim(fw, " Cmd Complete Update Register:"); + gas_messages(fw, entry->header.type, &entry->cmd_update_register, passed); + fwts_log_info_verbatim(fw, " Cmd Complete Update Mask: 0x%16.16" PRIx64, entry->cmd_update_preserve_mask); + fwts_log_info_verbatim(fw, " Cmd Complete Set Mask: 0x%16.16" PRIx64, entry->cmd_update_preserve_mask); + fwts_log_info_verbatim(fw, " Error Status Register:"); + gas_messages(fw, entry->header.type, &entry->error_status_register, passed); + fwts_log_info_verbatim(fw, " Error Status Mask: 0x%16.16" PRIx64, entry->error_status_mask); } static int pcct_test1(fwts_framework *fw) @@ -206,10 +227,10 @@ static int pcct_test1(fwts_framework *fw) if ((pcct->flags & ~0x01) != 0) { passed = false; fwts_failed(fw, LOG_LEVEL_HIGH, - "PCCTReservedNonZero", + "PCCTBadFlags", "PCCT flags field's bit 1..31 be zero, got " "0x%8.8" PRIx32 " instead", pcct->flags); - } + } if (pcct->reserved != 0) { passed = false; @@ -223,7 +244,6 @@ static int pcct_test1(fwts_framework *fw) pcct_sub = (fwts_acpi_table_pcct_subspace_header *) (table->data + offset); while (offset < table->length) { - uint64_t addr_length = 8; fwts_log_info_verbatim(fw, " PCC Subspace Structure:"); fwts_log_info_verbatim(fw, " Type: 0x%2.2" PRIx8, pcct_sub->type); @@ -238,7 +258,6 @@ static int pcct_test1(fwts_framework *fw) } generic_comm_test(fw, subspace, &passed); - addr_length = subspace->length; } else if (pcct_sub->type == 1) { fwts_acpi_table_pcct_subspace_type_1 *subspace = (fwts_acpi_table_pcct_subspace_type_1 *) pcct_sub; @@ -249,7 +268,6 @@ static int pcct_test1(fwts_framework *fw) } hw_reduced_comm_test_type1(fw, subspace, &passed); - addr_length = subspace->length; } else if (pcct_sub->type == 2) { fwts_acpi_table_pcct_subspace_type_2 *subspace = (fwts_acpi_table_pcct_subspace_type_2 *) pcct_sub; @@ -260,26 +278,44 @@ static int pcct_test1(fwts_framework *fw) } hw_reduced_comm_test_type2(fw, subspace, &passed); - addr_length = subspace->length; + + } 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 Plaform 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..2, got " + "PCCT Subspace Structure supports type 0..4, got " "0x%2.2" PRIx8 " instead", pcct_sub->type); + break; } - if (addr_length <= 8) { - passed = false; - fwts_failed(fw, LOG_LEVEL_HIGH, - "PCCTBadSubtypeMemoryLength", - "PCCT Subspace Structure must have memory length > 8, got " - "0x%16.16" PRIx64 " instead", addr_length); - } - - - fwts_log_nl(fw); offset += pcct_sub->length; diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h index 12d63aa..5484cf3 100644 --- a/src/lib/include/fwts_acpi.h +++ b/src/lib/include/fwts_acpi.h @@ -1380,8 +1380,8 @@ typedef struct { typedef struct { fwts_acpi_table_pcct_subspace_header header; - uint32_t doorbell_interrupt; - uint8_t doorbell_interrupt_flags; + uint32_t platform_interrupt; + uint8_t platform_interrupt_flags; uint8_t reserved; uint64_t base_address; uint64_t length; @@ -1395,8 +1395,8 @@ typedef struct { typedef struct { fwts_acpi_table_pcct_subspace_header header; - uint32_t doorbell_interrupt; - uint8_t doorbell_interrupt_flags; + uint32_t platform_interrupt; + uint8_t platform_interrupt_flags; uint8_t reserved; uint64_t base_address; uint64_t length; @@ -1406,11 +1406,37 @@ typedef struct { uint32_t nominal_latency; uint32_t max_periodic_access_rate; uint16_t min_request_turnaround_time; - fwts_acpi_gas doorbell_ack_register; - uint64_t doorbell_ack_preserve; - uint64_t doorbell_ack_write; + fwts_acpi_gas platform_ack_register; + uint64_t platform_ack_preserve; + uint64_t platform_ack_write; } __attribute__ ((packed)) fwts_acpi_table_pcct_subspace_type_2; +typedef struct { + fwts_acpi_table_pcct_subspace_header header; + uint32_t platform_interrupt; + uint8_t platform_interrupt_flags; + uint8_t reserved1; + uint64_t base_address; + uint32_t length; + fwts_acpi_gas doorbell_register; + uint64_t doorbell_preserve; + uint64_t doorbell_write; + uint32_t nominal_latency; + uint32_t max_periodic_access_rate; + uint32_t min_request_turnaround_time; + fwts_acpi_gas platform_ack_register; + uint64_t platform_ack_preserve; + uint64_t platform_ack_write; + uint64_t reserved2; + fwts_acpi_gas cmd_complete_register; + uint64_t cmd_complete_mask; + fwts_acpi_gas cmd_update_register; + uint64_t cmd_update_preserve_mask; + uint64_t cmd_update_set_mask; + fwts_acpi_gas error_status_register; + uint64_t error_status_mask; +} __attribute__ ((packed)) fwts_acpi_table_pcct_subspace_type_3_4; + /* * ACPI SPCR (Serial Port Console Redirection Table) * http://msdn.microsoft.com/en-us/library/windows/hardware/dn639132(v=vs.85).aspx
1. Added type 3 & type 4 2. Updated doorbell to platform in some cases 3. Fixed typos Signed-off-by: Alex Hung <alex.hung@canonical.com> --- src/acpi/pcct/pcct.c | 232 +++++++++++++++++++++++++------------------- src/lib/include/fwts_acpi.h | 40 ++++++-- 2 files changed, 167 insertions(+), 105 deletions(-)