Re: [PATCH 2/2] efi: add firmware version information to sysfs

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

 



On Tue, Aug 23, 2016 at 12:13:52PM -0400, Peter Jones wrote:
> This adds the EFI Spec version from the system table to sysfs as
> /sys/firmware/efi/spec_version .
> 
> Userland tools need this information in order to work around
> specification deficiencies in 2.4 and earlier firmwares.

Some details or examples on the nature of those specification
deficiencies would help an uninitiated reader understand the
necessity of this patch.

> 
> Signed-off-by: Peter Jones <pjones@xxxxxxxxxx>
> ---
>  Documentation/ABI/testing/sysfs-firmware-efi |  6 +++
>  arch/ia64/kernel/efi.c                       |  3 ++
>  drivers/firmware/efi/arm-init.c              |  2 +
>  drivers/firmware/efi/efi.c                   | 71 ++++++++++++++++++++++++++++
>  4 files changed, 82 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/sysfs-firmware-efi b/Documentation/ABI/testing/sysfs-firmware-efi
> index e794eac..4eec7c2 100644
> --- a/Documentation/ABI/testing/sysfs-firmware-efi
> +++ b/Documentation/ABI/testing/sysfs-firmware-efi
> @@ -28,3 +28,9 @@ Description:	Displays the physical addresses of all EFI Configuration
>  		versions are always printed first, i.e. ACPI20 comes
>  		before ACPI.
>  Users:		dmidecode
> +
> +What:		/sys/firmware/efi/spec_version
> +Date:		August 2016
> +Contact:	linux-efi@xxxxxxxxxxxxxxx
> +Description:	Displays the UEFI Specification revision the firmware claims to
> +		be based upon.
> diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
> index 1212956..a48377f 100644
> --- a/arch/ia64/kernel/efi.c
> +++ b/arch/ia64/kernel/efi.c
> @@ -475,6 +475,7 @@ efi_init (void)
>  	u64 efi_desc_size;
>  	char *cp, vendor[100] = "unknown";
>  	int i;
> +	efi_table_hdr_t *hdr;

Unused new variable?

>  
>  	set_bit(EFI_BOOT, &efi.flags);
>  	set_bit(EFI_64BIT, &efi.flags);
> @@ -531,6 +532,8 @@ efi_init (void)
>  	       efi.systab->hdr.revision >> 16,
>  	       efi.systab->hdr.revision & 0xffff, vendor);
>  
> +	efi.spec_version = efi.systab->hdr.version;
> +

I think this deserves a mention in the commit message that the
spec_version struct field was previously not filled for ia64 arch
and that you're fixing that while you're at it. Alternatively,
move this to a separate commit.

>  	palo_phys      = EFI_INVALID_TABLE_ADDR;
>  
>  	if (efi_config_init(arch_tables) != 0)
> diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
> index b89fc23..8e8cb8c 100644
> --- a/drivers/firmware/efi/arm-init.c
> +++ b/drivers/firmware/efi/arm-init.c
> @@ -133,6 +133,8 @@ static int __init uefi_init(void)
>  
>  	efi.spec_version = (u32)efi.systab->hdr.revision;
>  
> +	early_memunmap(tmp, sizeof(efi_table_hdr_t));
> +

What is the connection of this change to exposing the spec_version
in sysfs? Seems like a fix that should be moved to a separate commit.

>  	table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
>  	config_tables = early_memremap_ro(efi_to_phys(efi.systab->tables),
>  					  table_size);
> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> index 5a2631a..5947d19 100644
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -27,6 +27,7 @@
>  #include <linux/slab.h>
>  #include <linux/acpi.h>
>  #include <linux/ucs2_string.h>
> +#include <linux/bcd.h>
>  
>  #include <asm/early_ioremap.h>
>  
> @@ -124,6 +125,74 @@ static struct kobj_attribute efi_attr_systab =
>  
>  #define EFI_FIELD(var) efi.var
>  
> +static ssize_t efi_version_show(struct kobject *kobj,
> +				struct kobj_attribute *attr,
> +				char *buf,
> +				u32 revision)
> +{
> +	char *str = buf;
> +	u16 major;
> +	u8 minor, tiny;
> +
> +	if (!kobj || !buf)
> +		return -EINVAL;
> +
> +	/* The spec says:
> +	 *  The revision of the EFI Specification to which this table
> +	 *  conforms. The upper 16 bits of this field contain the major
> +	 *  revision value, and the lower 16 bits contain the minor revision
> +	 *  value. The minor revision values are binary coded decimals and are
> +	 *  limited to the range of 00..99.
> +	 *
> +	 *  When printed or displayed UEFI spec revision is referred as (Major
> +	 *  revision).(Minor revision upper decimal).(Minor revision lower
> +	 *  decimal) or (Major revision).(Minor revision upper decimal) in
> +	 *  case Minor revision lower decimal is set to 0. For example:
> +	 *
> +	 *  A specification with the revision value ((2<<16) | (30)) would be
> +	 *  referred as 2.3;
> +	 *  A specification with the revision value ((2<<16) | (31)) would be
> +	 *  referred as 2.3.1
> +	 *
> +	 * Then later it says:
> +	 *  Related Definitions
> +	 *   #define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
> +	 *   #define EFI_2_40_SYSTEM_TABLE_REVISION ((2<<16) | (40))
> +	 *   #define EFI_2_31_SYSTEM_TABLE_REVISION ((2<<16) | (31))
> +	 *   #define EFI_2_30_SYSTEM_TABLE_REVISION ((2<<16) | (30))
> +	 *   #define EFI_2_20_SYSTEM_TABLE_REVISION ((2<<16) | (20))
> +	 *   #define EFI_2_10_SYSTEM_TABLE_REVISION ((2<<16) | (10))
> +	 *   #define EFI_2_00_SYSTEM_TABLE_REVISION ((2<<16) | (00))
> +	 *   #define EFI_1_10_SYSTEM_TABLE_REVISION ((1<<16) | (10))
> +	 *   #define EFI_1_02_SYSTEM_TABLE_REVISION ((1<<16) | (02))
> +	 *   #define EFI_SPECIFICATION_VERSION EFI_SYSTEM_TABLE_REVISION
> +	 *   #define EFI_SYSTEM_TABLE_REVISION EFI_2_40_SYSTEM_TABLE_REVISION
> +	 *
> +	 * (Apparently this bit of the spec failed to get updated for 2.5
> +	 * and 2.6; UefiSpec.h in Tiano has been updated, though.)
> +	 */

I'd only include a 2-3 line summary of the spec and move this documentation
to the commit message in order to keep the code concise.

> +
> +	major = (revision & 0xffff0000) >> 16;
> +	minor = bcd2bin((revision & 0x0000ff00) >> 8);
> +	tiny = bcd2bin(revision & 0x000000ff);

You can improve readability by inserting a few blanks like this:

	major =         (revision & 0xffff0000) >> 16;
	minor = bcd2bin((revision & 0x0000ff00) >> 8);
	tiny  = bcd2bin( revision & 0x000000ff);

I'd also use minor_u and minor_l or somesuch instead of "tiny"
but that's just my preferred bikeshed color.

> +
> +	if (tiny == 0)
> +		str += sprintf(str, "%d.%d\n", major, minor);
> +	else
> +		str += sprintf(str, "%d.%d.%d\n", major, minor, tiny);
> +
> +	return str - buf;

Hm, why not return the result of sprintf directly (cast to ssize_t),
or if you want to handle negative return values properly, store the
result in an int?

> +}
> +
> +#define EFI_VERSION_ATTR_SHOW(name) \
> +static ssize_t name##_show(struct kobject *kobj, \
> +				struct kobj_attribute *attr, char *buf) \
> +{ \
> +	return efi_version_show(kobj, attr, buf, EFI_FIELD(name)); \
> +}
> +
> +EFI_VERSION_ATTR_SHOW(spec_version);
> +

Unless you plan to expose other versions like this, you can save on
code by not using a macro here.

Best regards,

Lukas

>  #define EFI_ATTR_SHOW(name) \
>  static ssize_t name##_show(struct kobject *kobj, \
>  				struct kobj_attribute *attr, char *buf) \
> @@ -146,6 +215,7 @@ static struct kobj_attribute efi_attr_runtime = __ATTR_RO(runtime);
>  static struct kobj_attribute efi_attr_config_table = __ATTR_RO(config_table);
>  static struct kobj_attribute efi_attr_fw_platform_size =
>  	__ATTR_RO(fw_platform_size);
> +static struct kobj_attribute efi_attr_spec_version = __ATTR_RO(spec_version);
>  
>  static struct attribute *efi_subsys_attrs[] = {
>  	&efi_attr_systab.attr,
> @@ -153,6 +223,7 @@ static struct attribute *efi_subsys_attrs[] = {
>  	&efi_attr_runtime.attr,
>  	&efi_attr_config_table.attr,
>  	&efi_attr_fw_platform_size.attr,
> +	&efi_attr_spec_version.attr,
>  	NULL,
>  };
>  
> -- 
> 2.7.4
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux