diff options
Diffstat (limited to 'efi-Add-esrt-support.patch')
-rw-r--r-- | efi-Add-esrt-support.patch | 780 |
1 files changed, 0 insertions, 780 deletions
diff --git a/efi-Add-esrt-support.patch b/efi-Add-esrt-support.patch deleted file mode 100644 index 78126f2ef..000000000 --- a/efi-Add-esrt-support.patch +++ /dev/null @@ -1,780 +0,0 @@ -From: Peter Jones <pjones@redhat.com> -Date: Tue, 18 Nov 2014 10:18:22 -0500 -Subject: [PATCH] efi: Add esrt support. - -Add sysfs files for the EFI System Resource Table (ESRT) under -/sys/firmware/efi/esrt and for each EFI System Resource Entry under -entries/ as a subdir. - -The EFI System Resource Table (ESRT) provides a read-only catalog of -system components for which the system accepts firmware upgrades via -UEFI's "Capsule Update" feature. This module allows userland utilities -to evaluate what firmware updates can be applied to this system, and -potentially arrange for those updates to occur. - -The ESRT is described as part of the UEFI specification, in version 2.5 -which should be available from http://uefi.org/specifications in early -2015. If you're a member of the UEFI Forum, information about its -addition to the standard is available as UEFI Mantis 1090. - -For some hardware platforms, additional restrictions may be found at -http://msdn.microsoft.com/en-us/library/windows/hardware/jj128256.aspx , -and additional documentation may be found at -http://download.microsoft.com/download/5/F/5/5F5D16CD-2530-4289-8019-94C6A20BED3C/windows-uefi-firmware-update-platform.docx -. - -Signed-off-by: Peter Jones <pjones@redhat.com> ---- - Documentation/ABI/testing/sysfs-firmware-efi-esrt | 81 ++++ - arch/x86/platform/efi/efi.c | 2 + - drivers/firmware/efi/Makefile | 2 +- - drivers/firmware/efi/efi.c | 82 +++- - drivers/firmware/efi/esrt.c | 464 ++++++++++++++++++++++ - include/linux/efi.h | 8 + - 6 files changed, 637 insertions(+), 2 deletions(-) - create mode 100644 Documentation/ABI/testing/sysfs-firmware-efi-esrt - create mode 100644 drivers/firmware/efi/esrt.c - -diff --git a/Documentation/ABI/testing/sysfs-firmware-efi-esrt b/Documentation/ABI/testing/sysfs-firmware-efi-esrt -new file mode 100644 -index 000000000000..6e431d1a4e79 ---- /dev/null -+++ b/Documentation/ABI/testing/sysfs-firmware-efi-esrt -@@ -0,0 +1,81 @@ -+What: /sys/firmware/efi/esrt/ -+Date: February 2015 -+Contact: Peter Jones <pjones@redhat.com> -+Description: Provides userland access to read the EFI System Resource Table -+ (ESRT), a catalog of firmware for which can be updated with -+ the UEFI UpdateCapsule mechanism described in section 7.5 of -+ the UEFI Standard. -+Users: fwupdate - https://github.com/rhinstaller/fwupdate -+ -+What: /sys/firmware/efi/esrt/fw_resource_count -+Date: February 2015 -+Contact: Peter Jones <pjones@redhat.com> -+Description: The number of entries in the ESRT -+ -+What: /sys/firmware/efi/esrt/fw_resource_count_max -+Date: February 2015 -+Contact: Peter Jones <pjones@redhat.com> -+Description: The maximum number of entries that /could/ be registered -+ in the allocation the table is currently in. This is -+ really only useful to the system firmware itself. -+ -+What: /sys/firmware/efi/esrt/fw_resource_version -+Date: February 2015 -+Contact: Peter Jones <pjones@redhat.com> -+Description: The version of the ESRT structure provided by the firmware. -+ -+What: /sys/firmware/efi/esrt/entries/entry$N/ -+Date: February 2015 -+Contact: Peter Jones <pjones@redhat.com> -+Description: Each ESRT entry is identified by a GUID, and each gets a -+ subdirectory under entries/ . -+ example: /sys/firmware/efi/esrt/entries/entry0/ -+ -+What: /sys/firmware/efi/esrt/entries/entry$N/fw_type -+Date: February 2015 -+Contact: Peter Jones <pjones@redhat.com> -+Description: What kind of firmware entry this is: -+ 0 - Unknown -+ 1 - System Firmware -+ 2 - Device Firmware -+ 3 - UEFI Driver -+ -+What: /sys/firmware/efi/esrt/entries/entry$N/fw_class -+Date: February 2015 -+Contact: Peter Jones <pjones@redhat.com> -+Description: This is the entry's guid, and will match the directory name. -+ -+What: /sys/firmware/efi/esrt/entries/entry$N/fw_version -+Date: February 2015 -+Contact: Peter Jones <pjones@redhat.com> -+Description: The version of the firmware currently installed. This is a -+ 32-bit unsigned integer. -+ -+What: /sys/firmware/efi/esrt/entries/entry$N/lowest_supported_fw_version -+Date: February 2015 -+Contact: Peter Jones <pjones@redhat.com> -+Description: The lowest version of the firmware that can be installed. -+ -+What: /sys/firmware/efi/esrt/entries/entry$N/capsule_flags -+Date: February 2015 -+Contact: Peter Jones <pjones@redhat.com> -+Description: Flags that must be passed to UpdateCapsule() -+ -+What: /sys/firmware/efi/esrt/entries/entry$N/last_attempt_version -+Date: February 2015 -+Contact: Peter Jones <pjones@redhat.com> -+Description: The last firmware version for which an update was attempted. -+ -+What: /sys/firmware/efi/esrt/entries/entry$N/last_attempt_status -+Date: February 2015 -+Contact: Peter Jones <pjones@redhat.com> -+Description: The result of the last firmware update attempt for the -+ firmware resource entry. -+ 0 - Success -+ 1 - Insufficient resources -+ 2 - Incorrect version -+ 3 - Invalid format -+ 4 - Authentication error -+ 5 - AC power event -+ 6 - Battery power event -+ -diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c -index 02744df576d5..3b984c3aa1b0 100644 ---- a/arch/x86/platform/efi/efi.c -+++ b/arch/x86/platform/efi/efi.c -@@ -501,6 +501,8 @@ void __init efi_init(void) - - if (efi_enabled(EFI_DBG)) - print_efi_memmap(); -+ -+ efi_esrt_init(); - } - - void __init efi_late_init(void) -diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile -index d8be608a9f3b..26eabbc55341 100644 ---- a/drivers/firmware/efi/Makefile -+++ b/drivers/firmware/efi/Makefile -@@ -1,7 +1,7 @@ - # - # Makefile for linux kernel - # --obj-$(CONFIG_EFI) += efi.o vars.o reboot.o -+obj-$(CONFIG_EFI) += efi.o esrt.o vars.o reboot.o - obj-$(CONFIG_EFI_VARS) += efivars.o - obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o - obj-$(CONFIG_UEFI_CPER) += cper.o -diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c -index 3061bb8629dc..48b4c356740f 100644 ---- a/drivers/firmware/efi/efi.c -+++ b/drivers/firmware/efi/efi.c -@@ -39,6 +39,7 @@ struct efi __read_mostly efi = { - .fw_vendor = EFI_INVALID_TABLE_ADDR, - .runtime = EFI_INVALID_TABLE_ADDR, - .config_table = EFI_INVALID_TABLE_ADDR, -+ .esrt = EFI_INVALID_TABLE_ADDR, - }; - EXPORT_SYMBOL(efi); - -@@ -64,7 +65,7 @@ static int __init parse_efi_cmdline(char *str) - } - early_param("efi", parse_efi_cmdline); - --static struct kobject *efi_kobj; -+struct kobject *efi_kobj; - static struct kobject *efivars_kobj; - - /* -@@ -232,6 +233,84 @@ err_put: - - subsys_initcall(efisubsys_init); - -+/* -+ * Find the efi memory descriptor for a given physical address. Given a -+ * physicall address, determine if it exists within an EFI Memory Map entry, -+ * and if so, populate the supplied memory descriptor with the appropriate -+ * data. -+ */ -+int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) -+{ -+ struct efi_memory_map *map = efi.memmap; -+ void *p, *e; -+ -+ if (!efi_enabled(EFI_MEMMAP)) { -+ pr_err_once("EFI_MEMMAP is not enabled.\n"); -+ return -EINVAL; -+ } -+ -+ if (!map) { -+ pr_err_once("efi.memmap is not set.\n"); -+ return -EINVAL; -+ } -+ if (!out_md) { -+ pr_err_once("out_md is null.\n"); -+ return -EINVAL; -+ } -+ if (WARN_ON_ONCE(!map->phys_map)) -+ return -EINVAL; -+ if (WARN_ON_ONCE(map->nr_map == 0) || WARN_ON_ONCE(map->desc_size == 0)) -+ return -EINVAL; -+ -+ e = map->phys_map + map->nr_map * map->desc_size; -+ for (p = map->phys_map; p < e; p += map->desc_size) { -+ efi_memory_desc_t *md; -+ u64 size; -+ u64 end; -+ -+ /* -+ * If a driver calls this after efi_free_boot_services, -+ * ->map will be NULL, and the target may also not be mapped. -+ * So just always get our own virtual map on the CPU. -+ * -+ */ -+ md = early_memremap((phys_addr_t)p, sizeof (*md)); -+ if (!md) { -+ pr_err_once("early_memremap(%p, %zu) failed.\n", -+ p, sizeof (*md)); -+ return -ENOMEM; -+ } -+ -+ if (!(md->attribute & EFI_MEMORY_RUNTIME) && -+ md->type != EFI_BOOT_SERVICES_DATA && -+ md->type != EFI_RUNTIME_SERVICES_DATA) { -+ early_memunmap(md, sizeof (*md)); -+ continue; -+ } -+ -+ size = md->num_pages << EFI_PAGE_SHIFT; -+ end = md->phys_addr + size; -+ if (phys_addr >= md->phys_addr && phys_addr < end) { -+ memcpy(out_md, md, sizeof(*out_md)); -+ early_memunmap(md, sizeof (*md)); -+ return 0; -+ } -+ -+ early_memunmap(md, sizeof (*md)); -+ } -+ pr_err_once("requested map not found.\n"); -+ return -ENOENT; -+} -+ -+/* -+ * Calculate the highest address of an efi memory descriptor. -+ */ -+u64 __init efi_mem_desc_end(efi_memory_desc_t *md) -+{ -+ u64 size = md->num_pages << EFI_PAGE_SHIFT; -+ u64 end = md->phys_addr + size; -+ return end; -+} - - /* - * We can't ioremap data in EFI boot services RAM, because we've already mapped -@@ -274,6 +353,7 @@ static __initdata efi_config_table_type_t common_tables[] = { - {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios}, - {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3}, - {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, -+ {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt}, - {NULL_GUID, NULL, NULL}, - }; - -diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c -new file mode 100644 -index 000000000000..20c0cbdb1c60 ---- /dev/null -+++ b/drivers/firmware/efi/esrt.c -@@ -0,0 +1,464 @@ -+/* -+ * esrt.c -+ * -+ * This module exports EFI System Resource Table (ESRT) entries into userspace -+ * through the sysfs file system. The ESRT provides a read-only catalog of -+ * system components for which the system accepts firmware upgrades via UEFI's -+ * "Capsule Update" feature. This module allows userland utilities to evaluate -+ * what firmware updates can be applied to this system, and potentially arrange -+ * for those updates to occur. -+ * -+ * Data is currently found below /sys/firmware/efi/esrt/... -+ */ -+#define pr_fmt(fmt) "esrt: " fmt -+ -+#include <linux/capability.h> -+#include <linux/device.h> -+#include <linux/efi.h> -+#include <linux/init.h> -+#include <linux/kernel.h> -+#include <linux/kobject.h> -+#include <linux/list.h> -+#include <linux/memblock.h> -+#include <linux/module.h> -+#include <linux/slab.h> -+#include <linux/types.h> -+ -+#include <asm/io.h> -+#include <asm/early_ioremap.h> -+ -+struct efi_system_resource_entry_v1 { -+ efi_guid_t fw_class; -+ u32 fw_type; -+ u32 fw_version; -+ u32 lowest_supported_fw_version; -+ u32 capsule_flags; -+ u32 last_attempt_version; -+ u32 last_attempt_status; -+}; -+ -+/* -+ * _count and _version are what they seem like. _max is actually just -+ * accounting info for the firmware when creating the table; it should never -+ * have been exposed to us. To wit, the spec says: -+ * The maximum number of resource array entries that can be within the -+ * table without reallocating the table, must not be zero. -+ * Since there's no guidance about what that means in terms of memory layout, -+ * it means nothing to us. -+ */ -+struct efi_system_resource_table { -+ u32 fw_resource_count; -+ u32 fw_resource_count_max; -+ u64 fw_resource_version; -+ u8 entries[]; -+}; -+ -+static phys_addr_t esrt_data; -+static size_t esrt_data_size; -+ -+static struct efi_system_resource_table *esrt; -+ -+struct esre_entry { -+ union { -+ struct efi_system_resource_entry_v1 *esre1; -+ } esre; -+ -+ struct kobject kobj; -+ struct list_head list; -+}; -+ -+/* global list of esre_entry. */ -+static LIST_HEAD(entry_list); -+ -+/* entry attribute */ -+struct esre_attribute { -+ struct attribute attr; -+ ssize_t (*show)(struct esre_entry *entry, char *buf); -+ ssize_t (*store)(struct esre_entry *entry, -+ const char *buf, size_t count); -+}; -+ -+static struct esre_entry *to_entry(struct kobject *kobj) -+{ -+ return container_of(kobj, struct esre_entry, kobj); -+} -+ -+static struct esre_attribute *to_attr(struct attribute *attr) -+{ -+ return container_of(attr, struct esre_attribute, attr); -+} -+ -+static ssize_t esre_attr_show(struct kobject *kobj, -+ struct attribute *_attr, char *buf) -+{ -+ struct esre_entry *entry = to_entry(kobj); -+ struct esre_attribute *attr = to_attr(_attr); -+ -+ /* Don't tell normal users what firmware versions we've got... */ -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EACCES; -+ -+ return attr->show(entry, buf); -+} -+ -+static const struct sysfs_ops esre_attr_ops = { -+ .show = esre_attr_show, -+}; -+ -+/* Generic ESRT Entry ("ESRE") support. */ -+static ssize_t esre_fw_class_show(struct esre_entry *entry, char *buf) -+{ -+ char *str = buf; -+ -+ efi_guid_to_str(&entry->esre.esre1->fw_class, str); -+ str += strlen(str); -+ str += sprintf(str, "\n"); -+ -+ return str - buf; -+} -+ -+static struct esre_attribute esre_fw_class = __ATTR(fw_class, 0400, -+ esre_fw_class_show, NULL); -+ -+#define esre_attr_decl(name, size, fmt) \ -+static ssize_t esre_##name##_show(struct esre_entry *entry, char *buf) \ -+{ \ -+ return sprintf(buf, fmt "\n", \ -+ le##size##_to_cpu(entry->esre.esre1->name)); \ -+} \ -+\ -+static struct esre_attribute esre_##name = __ATTR(name, 0400, \ -+ esre_##name##_show, NULL) -+ -+esre_attr_decl(fw_type, 32, "%u"); -+esre_attr_decl(fw_version, 32, "%u"); -+esre_attr_decl(lowest_supported_fw_version, 32, "%u"); -+esre_attr_decl(capsule_flags, 32, "0x%x"); -+esre_attr_decl(last_attempt_version, 32, "%u"); -+esre_attr_decl(last_attempt_status, 32, "%u"); -+ -+static struct attribute *esre1_attrs[] = { -+ &esre_fw_class.attr, -+ &esre_fw_type.attr, -+ &esre_fw_version.attr, -+ &esre_lowest_supported_fw_version.attr, -+ &esre_capsule_flags.attr, -+ &esre_last_attempt_version.attr, -+ &esre_last_attempt_status.attr, -+ NULL -+}; -+static void esre_release(struct kobject *kobj) -+{ -+ struct esre_entry *entry = to_entry(kobj); -+ -+ list_del(&entry->list); -+ kfree(entry); -+} -+ -+static struct kobj_type esre1_ktype = { -+ .release = esre_release, -+ .sysfs_ops = &esre_attr_ops, -+ .default_attrs = esre1_attrs, -+}; -+ -+ -+static struct kobject *esrt_kobj; -+static struct kset *esrt_kset; -+ -+static int esre_create_sysfs_entry(void *esre, int entry_num) -+{ -+ int rc = 0; -+ struct esre_entry *entry; -+ char name[20]; -+ -+ entry = kzalloc(sizeof(*entry), GFP_KERNEL); -+ if (!entry) -+ return -ENOMEM; -+ -+ sprintf(name, "entry%d", entry_num); -+ -+ entry->kobj.kset = esrt_kset; -+ -+ if (esrt->fw_resource_version == 1) { -+ entry->esre.esre1 = esre; -+ rc = kobject_init_and_add(&entry->kobj, &esre1_ktype, NULL, -+ "%s", name); -+ } -+ if (rc) { -+ kfree(entry); -+ return rc; -+ } -+ -+ list_add_tail(&entry->list, &entry_list); -+ return 0; -+} -+ -+/* support for displaying ESRT fields at the top level */ -+#define esrt_attr_decl(name, size, fmt) \ -+static ssize_t esrt_##name##_show(struct kobject *kobj, \ -+ struct kobj_attribute *attr, char *buf)\ -+{ \ -+ return sprintf(buf, fmt "\n", le##size##_to_cpu(esrt->name)); \ -+} \ -+\ -+static struct kobj_attribute esrt_##name = __ATTR(name, 0400, \ -+ esrt_##name##_show, NULL) -+ -+esrt_attr_decl(fw_resource_count, 32, "%u"); -+esrt_attr_decl(fw_resource_count_max, 32, "%u"); -+esrt_attr_decl(fw_resource_version, 64, "%llu"); -+ -+static struct attribute *esrt_attrs[] = { -+ &esrt_fw_resource_count.attr, -+ &esrt_fw_resource_count_max.attr, -+ &esrt_fw_resource_version.attr, -+ NULL, -+}; -+ -+static inline int esrt_table_exists(void) -+{ -+ if (!efi_enabled(EFI_CONFIG_TABLES)) -+ return 0; -+ if (efi.esrt == EFI_INVALID_TABLE_ADDR) -+ return 0; -+ return 1; -+} -+ -+static umode_t esrt_attr_is_visible(struct kobject *kobj, -+ struct attribute *attr, int n) -+{ -+ if (!esrt_table_exists()) -+ return 0; -+ return attr->mode; -+} -+ -+static struct attribute_group esrt_attr_group = { -+ .attrs = esrt_attrs, -+ .is_visible = esrt_attr_is_visible, -+}; -+ -+/* -+ * remap the table, copy it to kmalloced pages, and unmap it. -+ */ -+void __init efi_esrt_init(void) -+{ -+ void *va; -+ struct efi_system_resource_table tmpesrt; -+ struct efi_system_resource_entry_v1 *v1_entries; -+ size_t size, max, entry_size, entries_size; -+ efi_memory_desc_t md; -+ int rc; -+ -+ pr_debug("esrt-init: loading.\n"); -+ if (!esrt_table_exists()) -+ return; -+ -+ rc = efi_mem_desc_lookup(efi.esrt, &md); -+ if (rc < 0) { -+ pr_err("ESRT header is not in the memory map.\n"); -+ return; -+ } -+ -+ max = efi_mem_desc_end(&md); -+ if (max < efi.esrt) { -+ pr_err("EFI memory descriptor is invalid. (esrt: %p max: %p)\n", -+ (void *)efi.esrt, (void *)max); -+ return; -+ } -+ -+ size = sizeof(*esrt); -+ max -= efi.esrt; -+ -+ if (max < size) { -+ pr_err("ESRT header doen't fit on single memory map entry. (size: %zu max: %zu)\n", -+ size, max); -+ return; -+ } -+ -+ va = early_memremap(efi.esrt, size); -+ if (!va) { -+ pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt, -+ size); -+ return; -+ } -+ -+ memcpy(&tmpesrt, va, sizeof(tmpesrt)); -+ -+ if (tmpesrt.fw_resource_version == 1) { -+ entry_size = sizeof (*v1_entries); -+ } else { -+ pr_err("Unsupported ESRT version %lld.\n", -+ tmpesrt.fw_resource_version); -+ return; -+ } -+ -+ if (tmpesrt.fw_resource_count > 0 && max - size < entry_size) { -+ pr_err("ESRT memory map entry can only hold the header. (max: %zu size: %zu)\n", -+ max - size, entry_size); -+ goto err_memunmap; -+ } -+ -+ /* -+ * The format doesn't really give us any boundary to test here, -+ * so I'm making up 128 as the max number of individually updatable -+ * components we support. -+ * 128 should be pretty excessive, but there's still some chance -+ * somebody will do that someday and we'll need to raise this. -+ */ -+ if (tmpesrt.fw_resource_count > 128) { -+ pr_err("ESRT says fw_resource_count has very large value %d.\n", -+ tmpesrt.fw_resource_count); -+ goto err_memunmap; -+ } -+ -+ /* -+ * We know it can't be larger than N * sizeof() here, and N is limited -+ * by the previous test to a small number, so there's no overflow. -+ */ -+ entries_size = tmpesrt.fw_resource_count * entry_size; -+ if (max < size + entries_size) { -+ pr_err("ESRT does not fit on single memory map entry (size: %zu max: %zu)\n", -+ size, max); -+ goto err_memunmap; -+ } -+ -+ /* remap it with our (plausible) new pages */ -+ early_memunmap(va, size); -+ size += entries_size; -+ va = early_memremap(efi.esrt, size); -+ if (!va) { -+ pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt, -+ size); -+ return; -+ } -+ -+ esrt_data = (phys_addr_t)efi.esrt; -+ esrt_data_size = size; -+ -+ pr_info("Reserving ESRT space from %p to %p.\n", (void *)esrt_data, -+ (char *)esrt_data + size); -+ memblock_reserve(esrt_data, esrt_data_size); -+ -+ pr_debug("esrt-init: loaded.\n"); -+err_memunmap: -+ early_memunmap(va, size); -+} -+ -+static int __init register_entries(void) -+{ -+ struct efi_system_resource_entry_v1 *v1_entries = (void *)esrt->entries; -+ int i, rc; -+ -+ if (!esrt_table_exists()) -+ return 0; -+ -+ for (i = 0; i < le32_to_cpu(esrt->fw_resource_count); i++) { -+ void *entry; -+ if (esrt->fw_resource_version == 1) { -+ entry = &v1_entries[i]; -+ } -+ rc = esre_create_sysfs_entry(entry, i); -+ if (rc < 0) { -+ pr_err("ESRT entry creation failed with error %d.\n", -+ rc); -+ return rc; -+ } -+ } -+ return 0; -+} -+ -+static void cleanup_entry_list(void) -+{ -+ struct esre_entry *entry, *next; -+ -+ list_for_each_entry_safe(entry, next, &entry_list, list) { -+ kobject_put(&entry->kobj); -+ } -+} -+ -+static int __init esrt_sysfs_init(void) -+{ -+ int error; -+ struct efi_system_resource_table __iomem *ioesrt; -+ -+ pr_debug("esrt-sysfs: loading.\n"); -+ if (!esrt_data || !esrt_data_size) -+ return -ENOSYS; -+ -+ ioesrt = ioremap(esrt_data, esrt_data_size); -+ if (!ioesrt) { -+ pr_err("ioremap(%p, %zu) failed.\n", (void *)esrt_data, -+ esrt_data_size); -+ return -ENOMEM; -+ } -+ -+ esrt = kmalloc(esrt_data_size, GFP_KERNEL); -+ if (!esrt) { -+ pr_err("kmalloc failed. (wanted %zu bytes)\n", esrt_data_size); -+ iounmap(ioesrt); -+ return -ENOMEM; -+ } -+ -+ memcpy_fromio(esrt, ioesrt, esrt_data_size); -+ -+ esrt_kobj = kobject_create_and_add("esrt", efi_kobj); -+ if (!esrt_kobj) { -+ pr_err("Firmware table registration failed.\n"); -+ error = -ENOMEM; -+ goto err; -+ } -+ -+ error = sysfs_create_group(esrt_kobj, &esrt_attr_group); -+ if (error) { -+ pr_err("Sysfs attribute export failed with error %d.\n", -+ error); -+ goto err_remove_esrt; -+ } -+ -+ esrt_kset = kset_create_and_add("entries", NULL, esrt_kobj); -+ if (!esrt_kset) { -+ pr_err("kset creation failed.\n"); -+ error = -ENOMEM; -+ goto err_remove_group; -+ } -+ -+ error = register_entries(); -+ if (error) -+ goto err_cleanup_list; -+ -+ memblock_remove(esrt_data, esrt_data_size); -+ -+ pr_debug("esrt-sysfs: loaded.\n"); -+ -+ return 0; -+err_cleanup_list: -+ cleanup_entry_list(); -+ kset_unregister(esrt_kset); -+err_remove_group: -+ sysfs_remove_group(esrt_kobj, &esrt_attr_group); -+err_remove_esrt: -+ kobject_put(esrt_kobj); -+err: -+ kfree(esrt); -+ esrt = NULL; -+ return error; -+} -+ -+static void __exit esrt_sysfs_exit(void) -+{ -+ pr_debug("esrt-sysfs: unloading.\n"); -+ cleanup_entry_list(); -+ kset_unregister(esrt_kset); -+ sysfs_remove_group(esrt_kobj, &esrt_attr_group); -+ kfree(esrt); -+ esrt = NULL; -+ kobject_del(esrt_kobj); -+ kobject_put(esrt_kobj); -+} -+ -+module_init(esrt_sysfs_init); -+module_exit(esrt_sysfs_exit); -+ -+MODULE_AUTHOR("Peter Jones <pjones@redhat.com>"); -+MODULE_DESCRIPTION("EFI System Resource Table support"); -+MODULE_LICENSE("GPL"); -diff --git a/include/linux/efi.h b/include/linux/efi.h -index 9cc069579351..fa3546989ab0 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -583,6 +583,9 @@ void efi_native_runtime_setup(void); - #define EFI_FILE_INFO_ID \ - EFI_GUID( 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) - -+#define EFI_SYSTEM_RESOURCE_TABLE_GUID \ -+ EFI_GUID( 0xb122a263, 0x3661, 0x4f68, 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80 ) -+ - #define EFI_FILE_SYSTEM_GUID \ - EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) - -@@ -849,6 +852,7 @@ extern struct efi { - unsigned long fw_vendor; /* fw_vendor */ - unsigned long runtime; /* runtime table */ - unsigned long config_table; /* config tables */ -+ unsigned long esrt; /* ESRT table */ - efi_get_time_t *get_time; - efi_set_time_t *set_time; - efi_get_wakeup_time_t *get_wakeup_time; -@@ -901,6 +905,7 @@ static inline efi_status_t efi_query_variable_store(u32 attributes, unsigned lon - #endif - extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); - extern int efi_config_init(efi_config_table_type_t *arch_tables); -+extern void __init efi_esrt_init(void); - extern int efi_config_parse_tables(void *config_tables, int count, int sz, - efi_config_table_type_t *arch_tables); - extern u64 efi_get_iobase (void); -@@ -908,12 +913,15 @@ extern u32 efi_mem_type (unsigned long phys_addr); - extern u64 efi_mem_attributes (unsigned long phys_addr); - extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); - extern int __init efi_uart_console_only (void); -+extern u64 efi_mem_desc_end(efi_memory_desc_t *md); -+extern int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md); - extern void efi_initialize_iomem_resources(struct resource *code_resource, - struct resource *data_resource, struct resource *bss_resource); - extern void efi_get_time(struct timespec *now); - extern void efi_reserve_boot_services(void); - extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose); - extern struct efi_memory_map memmap; -+extern struct kobject *efi_kobj; - - extern int efi_reboot_quirk_mode; - extern bool efi_poweroff_required(void); |