ACK: [PATCH 11/21] FADT: add compliance tests for reserved fields, PM profile, reduced hardware

Alex Hung alex.hung at canonical.com
Wed Feb 17 06:08:14 UTC 2016


On 2016-02-09 09:32 AM, Al Stone wrote:
> Add three new compliance tests that verify that the FADT reserved fields
> are zero as they should be, that the PM (Power Management) profile is a
> legal value, and that all of the fields and flags that are to be ignored
> when the OSPM is in reduced hardware mode are zero.
>
> Note that the spec says to ignore many FADT fields when in reduced hardware
> mode.  As of 6.1, it does not explicitly state that they must be zero.  But,
> zero seems to be a reasonable value -- or at least not destructive -- on the
> OSPMs that use them when they should be ignored.  The case can also be made
> that the fields should be zero; section 5.2.1.4 indicates ignored fields
> should be treated the same as reserved fields, which _are_ required to be
> zero.  As a practical matter, some vendors may have chosen to sidestep the
> spec here and set reduced hardware mode but used the ignored field anyway.
>
> Signed-off-by: Al Stone <al.stone at linaro.org>
> ---
>   src/acpi/fadt/fadt.c | 303 +++++++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 303 insertions(+)
>
> diff --git a/src/acpi/fadt/fadt.c b/src/acpi/fadt/fadt.c
> index b21653d..fd430ec 100644
> --- a/src/acpi/fadt/fadt.c
> +++ b/src/acpi/fadt/fadt.c
> @@ -359,6 +359,306 @@ static void acpi_table_check_fadt_dsdt(fwts_framework *fw)
>   	}
>   }
>
> +static void acpi_table_check_fadt_reserved(fwts_framework *fw)
> +{
> +	if (fadt->reserved == (uint8_t)0)
> +		fwts_passed(fw, "FADT first reserved field is zero.");
> +	else
> +		fwts_failed(fw, LOG_LEVEL_MEDIUM, "FADTReservedZero",
> +			    "FADT first reserved field is not zero: 0x%02x",
> +			    fadt->reserved);
> +
> +	if (fadt->reserved1 == (uint8_t)0)
> +		fwts_passed(fw, "FADT second reserved field is zero.");
> +	else
> +		fwts_failed(fw, LOG_LEVEL_MEDIUM, "FADTReservedZero",
> +			    "FADT second reserved field is not zero: 0x%02x",
> +			    fadt->reserved1);
> +}
> +
> +static void acpi_table_check_fadt_pm_profile(fwts_framework *fw)
> +{
> +	fwts_log_info(fw, "FADT Preferred PM Profile: %hhu (%s)\n",
> +		fadt->preferred_pm_profile,
> +		FWTS_ACPI_FADT_PREFERRED_PM_PROFILE(fadt->preferred_pm_profile));
> +
> +	if (fadt->preferred_pm_profile <= 8)
> +		fwts_passed(fw, "FADT has a valid preferred PM profile.");
> +	else
> +		fwts_failed(fw, LOG_LEVEL_MEDIUM, "FADTPMProfile",
> +			    "FADT preferred PM profile is invalid.");
> +}
> +
> +static void acpi_table_check_fadt_reduced_hardware(fwts_framework *fw)
> +{
> +	const char *IS = "IS";
> +	const char *IS_NOT = "IS NOT";
> +	bool rhw;
> +	bool passed;
> +	const fwts_acpi_gas null_gas = { 0 };
> +	uint32_t flag_mask;
> +
> +	rhw = fwts_acpi_is_reduced_hardware(fadt);
> +	fwts_log_info(fw, "FADT indicates ACPI %s in reduced hardware mode.",
> +		      rhw ? IS : IS_NOT);
> +
> +	if (!rhw)
> +		return;
> +
> +	passed = true;
> +
> +	/* check all the fields that will be ignored */
> +	if (fadt->smi_cmd != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "SMI_CMD is non-zero: 0x%x",
> +			      fadt->smi_cmd);
> +	}
> +	if (fadt->acpi_enable != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "ACPI_ENABLE is non-zero: 0x%x",
> +			      fadt->acpi_enable);
> +	}
> +	if (fadt->acpi_disable != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "ACPI_DISABLE is non-zero: 0x%x",
> +			      fadt->acpi_disable);
> +	}
> +	if (fadt->s4bios_req != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "S4BIOS_REQ is non-zero: 0x%x",
> +			      fadt->s4bios_req);
> +	}
> +	if (fadt->pstate_cnt != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "PSTATE_CNT is non-zero: 0x%x",
> +			      fadt->pstate_cnt);
> +	}
> +	if (fadt->pm1a_evt_blk != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "PM1A_EVT_BLK is non-zero: 0x%x",
> +			      fadt->pm1a_evt_blk);
> +	}
> +	if (fadt->pm1b_evt_blk != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "PM1B_EVT_BLK is non-zero: 0x%x",
> +			      fadt->pm1b_evt_blk);
> +	}
> +	if (fadt->pm1a_cnt_blk != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "PM1A_CNT_BLK is non-zero: 0x%x",
> +			      fadt->pm1a_cnt_blk);
> +	}
> +	if (fadt->pm1b_cnt_blk != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "PM1B_CNT_BLK is non-zero: 0x%x",
> +			      fadt->pm1b_cnt_blk);
> +	}
> +	if (fadt->pm2_cnt_blk != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "PM2_CNT_BLK is non-zero: 0x%x",
> +			      fadt->pm2_cnt_blk);
> +	}
> +	if (fadt->pm_tmr_blk != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "PM_TMR_BLK is non-zero: 0x%x",
> +			      fadt->pm_tmr_blk);
> +	}
> +	if (fadt->gpe0_blk != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "GPE0_BLK is non-zero: 0x%x",
> +			      fadt->gpe0_blk);
> +	}
> +	if (fadt->gpe1_blk != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "GPE1_BLK is non-zero: 0x%x",
> +			      fadt->gpe1_blk);
> +	}
> +	if (fadt->pm1_evt_len != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "PM1_EVT_LEN is non-zero: 0x%x",
> +			      fadt->pm1_evt_len);
> +	}
> +	if (fadt->pm1_cnt_len != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "PM1_CNT_LEN is non-zero: 0x%x",
> +			      fadt->pm1_cnt_len);
> +	}
> +	if (fadt->pm2_cnt_len != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "PM2_CNT_LEN is non-zero: 0x%x",
> +			      fadt->pm2_cnt_len);
> +	}
> +	if (fadt->pm_tmr_len != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "PM_TMR_LEN is non-zero: 0x%x",
> +			      fadt->pm_tmr_len);
> +	}
> +	if (fadt->gpe0_blk_len != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "GPE0_BLK_LEN is non-zero: 0x%x",
> +			      fadt->gpe0_blk_len);
> +	}
> +	if (fadt->gpe1_blk_len != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "GPE1_BLK_LEN is non-zero: 0x%x",
> +			      fadt->gpe1_blk_len);
> +	}
> +	if (fadt->gpe1_base != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "GPE1_BASE is non-zero: 0x%x",
> +			      fadt->gpe1_base);
> +	}
> +	if (fadt->cst_cnt != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "CST_CNT is non-zero: 0x%x",
> +			      fadt->cst_cnt);
> +	}
> +	if (fadt->p_lvl2_lat != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "P_LVL2_LAT is non-zero: 0x%x",
> +			      fadt->p_lvl2_lat);
> +	}
> +	if (fadt->p_lvl3_lat != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "P_LVL3_LAT is non-zero: 0x%x",
> +			      fadt->p_lvl3_lat);
> +	}
> +	if (fadt->flush_size != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "FLUSH_SIZE is non-zero: 0x%x",
> +			      fadt->flush_size);
> +	}
> +	if (fadt->flush_stride != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "FLUSH_STRIDE is non-zero: 0x%x",
> +			      fadt->flush_stride);
> +	}
> +	if (fadt->duty_offset != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "DUTY_OFFSET is non-zero: 0x%x",
> +			      fadt->duty_offset);
> +	}
> +	if (fadt->duty_width != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "DUTY_WIDTH is non-zero: 0x%x",
> +			      fadt->duty_width);
> +	}
> +	if (fadt->day_alrm != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "DAY_ALRM is non-zero: 0x%x",
> +			      fadt->day_alrm);
> +	}
> +	if (fadt->mon_alrm != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "MON_ALRM is non-zero: 0x%x",
> +			      fadt->mon_alrm);
> +	}
> +	if (fadt->century != 0) {
> +		passed = false;
> +		fwts_log_info(fw, "CENTURY is non-zero: 0x%x",
> +			      fadt->century);
> +	}
> +	if (memcmp((void *)&fadt->x_pm1a_evt_blk,
> +		   (void *)&null_gas,
> +		   sizeof(fwts_acpi_gas))) {
> +		passed = false;
> +		fwts_log_info(fw,
> +			      "X_PM1A_EVT_BLK is a non-zero general "
> +			      "address structure.");
> +	}
> +	if (memcmp((void *)&fadt->x_pm1b_evt_blk,
> +		   (void *)&null_gas,
> +		   sizeof(fwts_acpi_gas))) {
> +		passed = false;
> +		fwts_log_info(fw,
> +			      "X_PM1B_EVT_BLK is a non-zero general "
> +			      "address structure.");
> +	}
> +	if (memcmp((void *)&fadt->x_pm1a_cnt_blk,
> +		   (void *)&null_gas,
> +		   sizeof(fwts_acpi_gas))) {
> +		passed = false;
> +		fwts_log_info(fw,
> +			      "X_PM1A_CNT_BLK is a non-zero general "
> +			      "address structure.");
> +	}
> +	if (memcmp((void *)&fadt->x_pm1b_cnt_blk,
> +		   (void *)&null_gas,
> +		   sizeof(fwts_acpi_gas))) {
> +		passed = false;
> +		fwts_log_info(fw,
> +			      "X_PM1B_CNT_BLK is a non-zero general "
> +			      "address structure.");
> +	}
> +	if (memcmp((void *)&fadt->x_pm2_cnt_blk,
> +		   (void *)&null_gas,
> +		   sizeof(fwts_acpi_gas))) {
> +		passed = false;
> +		fwts_log_info(fw,
> +			      "X_PM2_CNT_BLK is a non-zero general "
> +			      "address structure.");
> +	}
> +	if (memcmp((void *)&fadt->x_pm_tmr_blk,
> +		   (void *)&null_gas,
> +		   sizeof(fwts_acpi_gas))) {
> +		passed = false;
> +		fwts_log_info(fw,
> +			      "X_PM_TMR_BLK is a non-zero general "
> +			      "address structure.");
> +	}
> +	if (memcmp((void *)&fadt->x_gpe0_blk,
> +		   (void *)&null_gas,
> +		   sizeof(fwts_acpi_gas))) {
> +		passed = false;
> +		fwts_log_info(fw,
> +			      "X_GPE0_BLK is a non-zero general "
> +			      "address structure.");
> +	}
> +	if (memcmp((void *)&fadt->x_gpe1_blk,
> +		   (void *)&null_gas,
> +		   sizeof(fwts_acpi_gas))) {
> +		passed = false;
> +		fwts_log_info(fw,
> +			      "X_GPE1_BLK is a non-zero general "
> +			      "address structure.");
> +	}
> +
> +	if (passed)
> +		fwts_passed(fw, "All FADT reduced hardware fields are zero.");
> +	else
> +		fwts_failed(fw, LOG_LEVEL_MEDIUM, "FADTRHWNonZero",
> +			    "Some FADT reduced hardware fields are non-zero.");
> +
> +	/* now check all the reserved flags */
> +	flag_mask = FWTS_FACP_FLAG_WBINVD_FLUSH		|
> +		    FWTS_FACP_FLAG_PROC_C1		|
> +		    FWTS_FACP_FLAG_P_LVL2_UP		|
> +		    FWTS_FACP_FLAG_RTC_S4		|
> +		    FWTS_FACP_FLAG_TMR_VAL_EXT		|
> +		    FWTS_FACP_FLAG_HEADLESS		|
> +		    FWTS_FACP_FLAG_CPU_SW_SLP		|
> +		    FWTS_FACP_FLAG_PCI_EXP_WAK		|
> +		    FWTS_FACP_FLAG_S4_RTC_STS_VALID	|
> +		    FWTS_FACP_FLAG_REMOTE_POWER_ON_CAPABLE;
> +
> +	if (fadt->flags & flag_mask)
> +		fwts_failed(fw, LOG_LEVEL_MEDIUM, "FADTRHWFlagsNonZero",
> +			    "Some FADT reduced hardware flags are set.");
> +	else
> +		fwts_passed(fw, "All FADT reduced hardware flags are not set.");
> +
> +
> +	if ((fadt->flags & FWTS_FACP_FLAG_FORCE_APIC_CLUSTER_MODEL) ||
> +	    (fadt->flags & FWTS_FACP_FLAG_FORCE_APIC_PHYSICAL_DESTINATION_MODE))
> +		fwts_failed(fw, LOG_LEVEL_MEDIUM,
> +			    "FADTRHWAPICFlags",
> +			    "FADT APIC flags are set for reduced hardware "
> +			    "mode but may be irrelevant.");
> +	else
> +		fwts_passed(fw,
> +			    "FADT APIC flags are not set in reduced "
> +			    "hardware mode.");
> +}
>
>   static void acpi_table_check_fadt_smi(
>   	fwts_framework *fw,
> @@ -545,6 +845,9 @@ static int fadt_test1(fwts_framework *fw)
>
>   	acpi_table_check_fadt_firmware_ctrl(fw);
>   	acpi_table_check_fadt_dsdt(fw);
> +	acpi_table_check_fadt_reserved(fw);
> +	acpi_table_check_fadt_pm_profile(fw);
> +	acpi_table_check_fadt_reduced_hardware(fw);
>   	acpi_table_check_fadt_smi(fw, fadt, &passed);
>   	acpi_table_check_fadt_pm_tmr(fw, fadt, &passed);
>   	acpi_table_check_fadt_gpe(fw, fadt, &passed);
>


Acked-by: Alex Hung <alex.hung at canonical.com>



More information about the fwts-devel mailing list