Re: [PATCH 6.1] arm64: efi: Use SMBIOS processor version to key off Ampere quirk

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Jun 07, 2023 at 05:26:12AM -0700, Ard Biesheuvel wrote:
> [ Upstream commit eb684408f3ea4856639675d6465f0024e498e4b1 ]
> 
> Instead of using the SMBIOS type 1 record 'family' field, which is often
> modified by OEMs, use the type 4 'processor ID' and 'processor version'
> fields, which are set to a small set of probe-able values on all known
> Ampere EFI systems in the field.
> 
> Fixes: 550b33cfd4452968 ("arm64: efi: Force the use of ...")
> Tested-by: Andrea Righi <andrea.righi@xxxxxxxxxxxxx>
> Signed-off-by: Ard Biesheuvel <ardb@xxxxxxxxxx>
> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

Where did Sasha sign off on this?

> Signed-off-by: Jeremi Piotrowski <jpiotrowski@xxxxxxxxxxxxxxxxxxx>
> ---
>  drivers/firmware/efi/libstub/arm64-stub.c | 39 ++++++++++++++++-----
>  drivers/firmware/efi/libstub/efistub.h    | 41 +++++++++++++++++++++--
>  drivers/firmware/efi/libstub/smbios.c     | 13 +++++--
>  3 files changed, 80 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
> index 42282c5c3fe6..e2f90566b291 100644
> --- a/drivers/firmware/efi/libstub/arm64-stub.c
> +++ b/drivers/firmware/efi/libstub/arm64-stub.c
> @@ -17,20 +17,43 @@
>  
>  static bool system_needs_vamap(void)
>  {
> -	const u8 *type1_family = efi_get_smbios_string(1, family);
> +	const struct efi_smbios_type4_record *record;
> +	const u32 __aligned(1) *socid;
> +	const u8 *version;
>  
>  	/*
>  	 * Ampere eMAG, Altra, and Altra Max machines crash in SetTime() if
> -	 * SetVirtualAddressMap() has not been called prior.
> +	 * SetVirtualAddressMap() has not been called prior. Most Altra systems
> +	 * can be identified by the SMCCC soc ID, which is conveniently exposed
> +	 * via the type 4 SMBIOS records. Otherwise, test the processor version
> +	 * field. eMAG systems all appear to have the processor version field
> +	 * set to "eMAG".
>  	 */
> -	if (!type1_family || (
> -	    strcmp(type1_family, "eMAG") &&
> -	    strcmp(type1_family, "Altra") &&
> -	    strcmp(type1_family, "Altra Max")))
> +	record = (struct efi_smbios_type4_record *)efi_get_smbios_record(4);
> +	if (!record)
>  		return false;
>  
> -	efi_warn("Working around broken SetVirtualAddressMap()\n");
> -	return true;
> +	socid = (u32 *)record->processor_id;
> +	switch (*socid & 0xffff000f) {
> +		static char const altra[] = "Ampere(TM) Altra(TM) Processor";
> +		static char const emag[] = "eMAG";
> +
> +	default:
> +		version = efi_get_smbios_string(&record->header, 4,
> +						processor_version);
> +		if (!version || (strncmp(version, altra, sizeof(altra) - 1) &&
> +				 strncmp(version, emag, sizeof(emag) - 1)))
> +			break;
> +
> +		fallthrough;
> +
> +	case 0x0a160001:	// Altra
> +	case 0x0a160002:	// Altra Max
> +		efi_warn("Working around broken SetVirtualAddressMap()\n");
> +		return true;
> +	}
> +
> +	return false;
>  }
>  
>  efi_status_t check_platform_features(void)
> diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
> index 900df67a2078..970e86e3aab0 100644
> --- a/drivers/firmware/efi/libstub/efistub.h
> +++ b/drivers/firmware/efi/libstub/efistub.h
> @@ -983,6 +983,8 @@ struct efi_smbios_record {
>  	u16	handle;
>  };
>  
> +const struct efi_smbios_record *efi_get_smbios_record(u8 type);
> +
>  struct efi_smbios_type1_record {
>  	struct efi_smbios_record	header;
>  
> @@ -996,13 +998,46 @@ struct efi_smbios_type1_record {
>  	u8				family;
>  };
>  
> -#define efi_get_smbios_string(__type, __name) ({			\
> +struct efi_smbios_type4_record {
> +	struct efi_smbios_record	header;
> +
> +	u8				socket;
> +	u8				processor_type;
> +	u8				processor_family;
> +	u8				processor_manufacturer;
> +	u8				processor_id[8];
> +	u8				processor_version;
> +	u8				voltage;
> +	u16				external_clock;
> +	u16				max_speed;
> +	u16				current_speed;
> +	u8				status;
> +	u8				processor_upgrade;
> +	u16				l1_cache_handle;
> +	u16				l2_cache_handle;
> +	u16				l3_cache_handle;
> +	u8				serial_number;
> +	u8				asset_tag;
> +	u8				part_number;
> +	u8				core_count;
> +	u8				enabled_core_count;
> +	u8				thread_count;
> +	u16				processor_characteristics;
> +	u16				processor_family2;
> +	u16				core_count2;
> +	u16				enabled_core_count2;
> +	u16				thread_count2;
> +	u16				thread_enabled;
> +};
> +
> +#define efi_get_smbios_string(__record, __type, __name) ({		\
>  	int size = sizeof(struct efi_smbios_type ## __type ## _record);	\
>  	int off = offsetof(struct efi_smbios_type ## __type ## _record,	\
>  			   __name);					\
> -	__efi_get_smbios_string(__type, off, size);			\
> +	__efi_get_smbios_string((__record), __type, off, size);		\
>  })
>  
> -const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize);
> +const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
> +				  u8 type, int offset, int recsize);
>  
>  #endif
> diff --git a/drivers/firmware/efi/libstub/smbios.c b/drivers/firmware/efi/libstub/smbios.c
> index aadb422b9637..f9c159c28f46 100644
> --- a/drivers/firmware/efi/libstub/smbios.c
> +++ b/drivers/firmware/efi/libstub/smbios.c
> @@ -22,19 +22,28 @@ struct efi_smbios_protocol {
>  	u8 minor_version;
>  };
>  
> -const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize)
> +const struct efi_smbios_record *efi_get_smbios_record(u8 type)
>  {
>  	struct efi_smbios_record *record;
>  	efi_smbios_protocol_t *smbios;
>  	efi_status_t status;
>  	u16 handle = 0xfffe;
> -	const u8 *strtable;
>  
>  	status = efi_bs_call(locate_protocol, &EFI_SMBIOS_PROTOCOL_GUID, NULL,
>  			     (void **)&smbios) ?:
>  		 efi_call_proto(smbios, get_next, &handle, &type, &record, NULL);
>  	if (status != EFI_SUCCESS)
>  		return NULL;
> +	return record;
> +}
> +
> +const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
> +				  u8 type, int offset, int recsize)
> +{
> +	const u8 *strtable;
> +
> +	if (!record)
> +		return NULL;
>  
>  	strtable = (u8 *)record + record->length;
>  	for (int i = 1; i < ((u8 *)record)[offset]; i++) {
> -- 
> 2.30.2
> 



[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux