summaryrefslogtreecommitdiffstats
path: root/efi-Add-esrt-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'efi-Add-esrt-support.patch')
-rw-r--r--efi-Add-esrt-support.patch780
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);