From bbf3f54706912de331ed2b7642263b58a18e0d6e Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Mar 13 2015 12:31:07 +0000 Subject: Add ESRT patch here. Signed-off-by: Peter Jones --- diff --git a/efi-Add-esrt-support.patch b/efi-Add-esrt-support.patch new file mode 100644 index 0000000..2b15752 --- /dev/null +++ b/efi-Add-esrt-support.patch @@ -0,0 +1,764 @@ +From: Peter Jones +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 +--- + 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 | 66 +++- + drivers/firmware/efi/esrt.c | 461 ++++++++++++++++++++++ + include/linux/efi.h | 8 + + 6 files changed, 618 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 ++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 ++Description: The number of entries in the ESRT ++ ++What: /sys/firmware/efi/esrt/fw_resource_count_max ++Date: February 2015 ++Contact: Peter Jones ++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 ++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 ++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 ++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 ++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 ++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 ++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 ++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 ++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 ++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 dbc8627a5cdf..b4c9fbbc9270 100644 +--- a/arch/x86/platform/efi/efi.c ++++ b/arch/x86/platform/efi/efi.c +@@ -492,6 +492,8 @@ void __init efi_init(void) + return; + + 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..e54ea20dfb42 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,68 @@ 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) { ++ /* ++ * If a driver calls this after efi_free_boot_services, ++ * ->map will be NULL. ++ * So just always get our own virtual map on the CPU. ++ */ ++ efi_memory_desc_t *md = phys_to_virt((phys_addr_t)p); ++ u64 size = md->num_pages << EFI_PAGE_SHIFT; ++ u64 end = md->phys_addr + size; ++ ++ if (!(md->attribute & EFI_MEMORY_RUNTIME) && ++ md->type != EFI_BOOT_SERVICES_DATA && ++ md->type != EFI_RUNTIME_SERVICES_DATA) ++ continue; ++ if (phys_addr >= md->phys_addr && phys_addr < end) { ++ memcpy(out_md, md, sizeof(*out_md)); ++ return 0; ++ } ++ } ++ 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 +337,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..1053b38f7e46 +--- /dev/null ++++ b/drivers/firmware/efi/esrt.c +@@ -0,0 +1,461 @@ ++/* ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 "); ++MODULE_DESCRIPTION("EFI System Resource Table support"); ++MODULE_LICENSE("GPL"); +diff --git a/include/linux/efi.h b/include/linux/efi.h +index 470e8dfcb517..ed0d0c09d45c 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -589,6 +589,9 @@ void efi_native_runtime_setup(void); + #define DEVICE_TREE_GUID \ + EFI_GUID( 0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 ) + ++#define EFI_SYSTEM_RESOURCE_TABLE_GUID \ ++ EFI_GUID( 0xb122a263, 0x3661, 0x4f68, 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80 ) ++ + #define EFI_CERT_SHA256_GUID \ + EFI_GUID( 0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 ) + +@@ -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); +-- +2.1.0 + diff --git a/kernel.spec b/kernel.spec index 20cf22c..106bcd9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -554,6 +554,9 @@ Patch1018: MODSIGN-Support-not-importing-certs-from-db.patch Patch1019: Add-sysrq-option-to-disable-secure-boot-mode.patch +# esrt +Patch1020: efi-Add-esrt-support.patch + # virt + ksm patches # DRM @@ -1329,6 +1332,8 @@ ApplyPatch MODSIGN-Support-not-importing-certs-from-db.patch ApplyPatch Add-sysrq-option-to-disable-secure-boot-mode.patch +ApplyPatch efi-Add-esrt-support.patch + # Assorted Virt Fixes # DRM core