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

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

 



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.

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;
 
 	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;
+
 	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));
+
 	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.)
+	 */
+
+	major = (revision & 0xffff0000) >> 16;
+	minor = bcd2bin((revision & 0x0000ff00) >> 8);
+	tiny = bcd2bin(revision & 0x000000ff);
+
+	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;
+}
+
+#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);
+
 #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