Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'efi-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi into x86/efi

Pull EFI changes from Matt Fleming:

- Use idiomatic negative error values in efivar_create_sysfs_entry()
instead of returning '1' to indicate error. (Dan Carpenter)

- Implement new support to expose the EFI System Resource Tables in sysfs,
which provides information for performing firmware updates. (Peter Jones)

- Documentation cleanup in the EFI handover protocol section which
falsely claimed that 'cmdline_size' needed to be filled out by the
boot loader. (Alex Smith)

- Align the order of SMBIOS tables in /sys/firmware/efi/systab to match
the way that we do things for ACPI and add documentation to
Documentation/ABI. (Jean Delvare)

Signed-off-by: Ingo Molnar <mingo@kernel.org>

+667 -10
+10
Documentation/ABI/testing/sysfs-firmware-efi
··· 18 18 Description: It shows the physical address of config table entry in the EFI 19 19 system table. 20 20 Users: Kexec 21 + 22 + What: /sys/firmware/efi/systab 23 + Date: April 2005 24 + Contact: linux-efi@vger.kernel.org 25 + Description: Displays the physical addresses of all EFI Configuration 26 + Tables found via the EFI System Table. The order in 27 + which the tables are printed forms an ABI and newer 28 + versions are always printed first, i.e. ACPI20 comes 29 + before ACPI. 30 + Users: dmidecode
+81
Documentation/ABI/testing/sysfs-firmware-efi-esrt
··· 1 + What: /sys/firmware/efi/esrt/ 2 + Date: February 2015 3 + Contact: Peter Jones <pjones@redhat.com> 4 + Description: Provides userland access to read the EFI System Resource Table 5 + (ESRT), a catalog of firmware for which can be updated with 6 + the UEFI UpdateCapsule mechanism described in section 7.5 of 7 + the UEFI Standard. 8 + Users: fwupdate - https://github.com/rhinstaller/fwupdate 9 + 10 + What: /sys/firmware/efi/esrt/fw_resource_count 11 + Date: February 2015 12 + Contact: Peter Jones <pjones@redhat.com> 13 + Description: The number of entries in the ESRT 14 + 15 + What: /sys/firmware/efi/esrt/fw_resource_count_max 16 + Date: February 2015 17 + Contact: Peter Jones <pjones@redhat.com> 18 + Description: The maximum number of entries that /could/ be registered 19 + in the allocation the table is currently in. This is 20 + really only useful to the system firmware itself. 21 + 22 + What: /sys/firmware/efi/esrt/fw_resource_version 23 + Date: February 2015 24 + Contact: Peter Jones <pjones@redhat.com> 25 + Description: The version of the ESRT structure provided by the firmware. 26 + 27 + What: /sys/firmware/efi/esrt/entries/entry$N/ 28 + Date: February 2015 29 + Contact: Peter Jones <pjones@redhat.com> 30 + Description: Each ESRT entry is identified by a GUID, and each gets a 31 + subdirectory under entries/ . 32 + example: /sys/firmware/efi/esrt/entries/entry0/ 33 + 34 + What: /sys/firmware/efi/esrt/entries/entry$N/fw_type 35 + Date: February 2015 36 + Contact: Peter Jones <pjones@redhat.com> 37 + Description: What kind of firmware entry this is: 38 + 0 - Unknown 39 + 1 - System Firmware 40 + 2 - Device Firmware 41 + 3 - UEFI Driver 42 + 43 + What: /sys/firmware/efi/esrt/entries/entry$N/fw_class 44 + Date: February 2015 45 + Contact: Peter Jones <pjones@redhat.com> 46 + Description: This is the entry's guid, and will match the directory name. 47 + 48 + What: /sys/firmware/efi/esrt/entries/entry$N/fw_version 49 + Date: February 2015 50 + Contact: Peter Jones <pjones@redhat.com> 51 + Description: The version of the firmware currently installed. This is a 52 + 32-bit unsigned integer. 53 + 54 + What: /sys/firmware/efi/esrt/entries/entry$N/lowest_supported_fw_version 55 + Date: February 2015 56 + Contact: Peter Jones <pjones@redhat.com> 57 + Description: The lowest version of the firmware that can be installed. 58 + 59 + What: /sys/firmware/efi/esrt/entries/entry$N/capsule_flags 60 + Date: February 2015 61 + Contact: Peter Jones <pjones@redhat.com> 62 + Description: Flags that must be passed to UpdateCapsule() 63 + 64 + What: /sys/firmware/efi/esrt/entries/entry$N/last_attempt_version 65 + Date: February 2015 66 + Contact: Peter Jones <pjones@redhat.com> 67 + Description: The last firmware version for which an update was attempted. 68 + 69 + What: /sys/firmware/efi/esrt/entries/entry$N/last_attempt_status 70 + Date: February 2015 71 + Contact: Peter Jones <pjones@redhat.com> 72 + Description: The result of the last firmware update attempt for the 73 + firmware resource entry. 74 + 0 - Success 75 + 1 - Insufficient resources 76 + 2 - Incorrect version 77 + 3 - Invalid format 78 + 4 - Authentication error 79 + 5 - AC power event 80 + 6 - Battery power event 81 +
-1
Documentation/x86/boot.txt
··· 1124 1124 1125 1125 o hdr.code32_start 1126 1126 o hdr.cmd_line_ptr 1127 - o hdr.cmdline_size 1128 1127 o hdr.ramdisk_image (if applicable) 1129 1128 o hdr.ramdisk_size (if applicable) 1130 1129
+2
arch/x86/platform/efi/efi.c
··· 501 501 502 502 if (efi_enabled(EFI_DBG)) 503 503 print_efi_memmap(); 504 + 505 + efi_esrt_init(); 504 506 } 505 507 506 508 void __init efi_late_init(void)
+1 -1
drivers/firmware/efi/Makefile
··· 1 1 # 2 2 # Makefile for linux kernel 3 3 # 4 - obj-$(CONFIG_EFI) += efi.o vars.o reboot.o 4 + obj-$(CONFIG_EFI) += efi.o esrt.o vars.o reboot.o 5 5 obj-$(CONFIG_EFI_VARS) += efivars.o 6 6 obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o 7 7 obj-$(CONFIG_UEFI_CPER) += cper.o
+88 -3
drivers/firmware/efi/efi.c
··· 39 39 .fw_vendor = EFI_INVALID_TABLE_ADDR, 40 40 .runtime = EFI_INVALID_TABLE_ADDR, 41 41 .config_table = EFI_INVALID_TABLE_ADDR, 42 + .esrt = EFI_INVALID_TABLE_ADDR, 42 43 }; 43 44 EXPORT_SYMBOL(efi); 44 45 ··· 65 64 } 66 65 early_param("efi", parse_efi_cmdline); 67 66 68 - static struct kobject *efi_kobj; 67 + struct kobject *efi_kobj; 69 68 static struct kobject *efivars_kobj; 70 69 71 70 /* ··· 86 85 str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20); 87 86 if (efi.acpi != EFI_INVALID_TABLE_ADDR) 88 87 str += sprintf(str, "ACPI=0x%lx\n", efi.acpi); 89 - if (efi.smbios != EFI_INVALID_TABLE_ADDR) 90 - str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); 88 + /* 89 + * If both SMBIOS and SMBIOS3 entry points are implemented, the 90 + * SMBIOS3 entry point shall be preferred, so we list it first to 91 + * let applications stop parsing after the first match. 92 + */ 91 93 if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) 92 94 str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3); 95 + if (efi.smbios != EFI_INVALID_TABLE_ADDR) 96 + str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); 93 97 if (efi.hcdp != EFI_INVALID_TABLE_ADDR) 94 98 str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp); 95 99 if (efi.boot_info != EFI_INVALID_TABLE_ADDR) ··· 238 232 239 233 subsys_initcall(efisubsys_init); 240 234 235 + /* 236 + * Find the efi memory descriptor for a given physical address. Given a 237 + * physicall address, determine if it exists within an EFI Memory Map entry, 238 + * and if so, populate the supplied memory descriptor with the appropriate 239 + * data. 240 + */ 241 + int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) 242 + { 243 + struct efi_memory_map *map = efi.memmap; 244 + void *p, *e; 245 + 246 + if (!efi_enabled(EFI_MEMMAP)) { 247 + pr_err_once("EFI_MEMMAP is not enabled.\n"); 248 + return -EINVAL; 249 + } 250 + 251 + if (!map) { 252 + pr_err_once("efi.memmap is not set.\n"); 253 + return -EINVAL; 254 + } 255 + if (!out_md) { 256 + pr_err_once("out_md is null.\n"); 257 + return -EINVAL; 258 + } 259 + if (WARN_ON_ONCE(!map->phys_map)) 260 + return -EINVAL; 261 + if (WARN_ON_ONCE(map->nr_map == 0) || WARN_ON_ONCE(map->desc_size == 0)) 262 + return -EINVAL; 263 + 264 + e = map->phys_map + map->nr_map * map->desc_size; 265 + for (p = map->phys_map; p < e; p += map->desc_size) { 266 + efi_memory_desc_t *md; 267 + u64 size; 268 + u64 end; 269 + 270 + /* 271 + * If a driver calls this after efi_free_boot_services, 272 + * ->map will be NULL, and the target may also not be mapped. 273 + * So just always get our own virtual map on the CPU. 274 + * 275 + */ 276 + md = early_memremap((phys_addr_t)p, sizeof (*md)); 277 + if (!md) { 278 + pr_err_once("early_memremap(%p, %zu) failed.\n", 279 + p, sizeof (*md)); 280 + return -ENOMEM; 281 + } 282 + 283 + if (!(md->attribute & EFI_MEMORY_RUNTIME) && 284 + md->type != EFI_BOOT_SERVICES_DATA && 285 + md->type != EFI_RUNTIME_SERVICES_DATA) { 286 + early_memunmap(md, sizeof (*md)); 287 + continue; 288 + } 289 + 290 + size = md->num_pages << EFI_PAGE_SHIFT; 291 + end = md->phys_addr + size; 292 + if (phys_addr >= md->phys_addr && phys_addr < end) { 293 + memcpy(out_md, md, sizeof(*out_md)); 294 + early_memunmap(md, sizeof (*md)); 295 + return 0; 296 + } 297 + 298 + early_memunmap(md, sizeof (*md)); 299 + } 300 + pr_err_once("requested map not found.\n"); 301 + return -ENOENT; 302 + } 303 + 304 + /* 305 + * Calculate the highest address of an efi memory descriptor. 306 + */ 307 + u64 __init efi_mem_desc_end(efi_memory_desc_t *md) 308 + { 309 + u64 size = md->num_pages << EFI_PAGE_SHIFT; 310 + u64 end = md->phys_addr + size; 311 + return end; 312 + } 241 313 242 314 /* 243 315 * We can't ioremap data in EFI boot services RAM, because we've already mapped ··· 358 274 {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios}, 359 275 {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3}, 360 276 {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, 277 + {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt}, 361 278 {NULL_GUID, NULL, NULL}, 362 279 }; 363 280
+6 -5
drivers/firmware/efi/efivars.c
··· 535 535 * efivar_create_sysfs_entry - create a new entry in sysfs 536 536 * @new_var: efivar entry to create 537 537 * 538 - * Returns 1 on failure, 0 on success 538 + * Returns 0 on success, negative error code on failure 539 539 */ 540 540 static int 541 541 efivar_create_sysfs_entry(struct efivar_entry *new_var) ··· 544 544 char *short_name; 545 545 unsigned long variable_name_size; 546 546 efi_char16_t *variable_name; 547 + int ret; 547 548 548 549 variable_name = new_var->var.VariableName; 549 550 variable_name_size = ucs2_strlen(variable_name) * sizeof(efi_char16_t); ··· 559 558 short_name = kzalloc(short_name_size, GFP_KERNEL); 560 559 561 560 if (!short_name) 562 - return 1; 561 + return -ENOMEM; 563 562 564 563 /* Convert Unicode to normal chars (assume top bits are 0), 565 564 ala UTF-8 */ ··· 575 574 576 575 new_var->kobj.kset = efivars_kset; 577 576 578 - i = kobject_init_and_add(&new_var->kobj, &efivar_ktype, 577 + ret = kobject_init_and_add(&new_var->kobj, &efivar_ktype, 579 578 NULL, "%s", short_name); 580 579 kfree(short_name); 581 - if (i) 582 - return 1; 580 + if (ret) 581 + return ret; 583 582 584 583 kobject_uevent(&new_var->kobj, KOBJ_ADD); 585 584 efivar_entry_add(new_var, &efivar_sysfs_list);
+471
drivers/firmware/efi/esrt.c
··· 1 + /* 2 + * esrt.c 3 + * 4 + * This module exports EFI System Resource Table (ESRT) entries into userspace 5 + * through the sysfs file system. The ESRT provides a read-only catalog of 6 + * system components for which the system accepts firmware upgrades via UEFI's 7 + * "Capsule Update" feature. This module allows userland utilities to evaluate 8 + * what firmware updates can be applied to this system, and potentially arrange 9 + * for those updates to occur. 10 + * 11 + * Data is currently found below /sys/firmware/efi/esrt/... 12 + */ 13 + #define pr_fmt(fmt) "esrt: " fmt 14 + 15 + #include <linux/capability.h> 16 + #include <linux/device.h> 17 + #include <linux/efi.h> 18 + #include <linux/init.h> 19 + #include <linux/kernel.h> 20 + #include <linux/kobject.h> 21 + #include <linux/list.h> 22 + #include <linux/memblock.h> 23 + #include <linux/module.h> 24 + #include <linux/slab.h> 25 + #include <linux/types.h> 26 + 27 + #include <asm/io.h> 28 + #include <asm/early_ioremap.h> 29 + 30 + struct efi_system_resource_entry_v1 { 31 + efi_guid_t fw_class; 32 + u32 fw_type; 33 + u32 fw_version; 34 + u32 lowest_supported_fw_version; 35 + u32 capsule_flags; 36 + u32 last_attempt_version; 37 + u32 last_attempt_status; 38 + }; 39 + 40 + /* 41 + * _count and _version are what they seem like. _max is actually just 42 + * accounting info for the firmware when creating the table; it should never 43 + * have been exposed to us. To wit, the spec says: 44 + * The maximum number of resource array entries that can be within the 45 + * table without reallocating the table, must not be zero. 46 + * Since there's no guidance about what that means in terms of memory layout, 47 + * it means nothing to us. 48 + */ 49 + struct efi_system_resource_table { 50 + u32 fw_resource_count; 51 + u32 fw_resource_count_max; 52 + u64 fw_resource_version; 53 + u8 entries[]; 54 + }; 55 + 56 + static phys_addr_t esrt_data; 57 + static size_t esrt_data_size; 58 + 59 + static struct efi_system_resource_table *esrt; 60 + 61 + struct esre_entry { 62 + union { 63 + struct efi_system_resource_entry_v1 *esre1; 64 + } esre; 65 + 66 + struct kobject kobj; 67 + struct list_head list; 68 + }; 69 + 70 + /* global list of esre_entry. */ 71 + static LIST_HEAD(entry_list); 72 + 73 + /* entry attribute */ 74 + struct esre_attribute { 75 + struct attribute attr; 76 + ssize_t (*show)(struct esre_entry *entry, char *buf); 77 + ssize_t (*store)(struct esre_entry *entry, 78 + const char *buf, size_t count); 79 + }; 80 + 81 + static struct esre_entry *to_entry(struct kobject *kobj) 82 + { 83 + return container_of(kobj, struct esre_entry, kobj); 84 + } 85 + 86 + static struct esre_attribute *to_attr(struct attribute *attr) 87 + { 88 + return container_of(attr, struct esre_attribute, attr); 89 + } 90 + 91 + static ssize_t esre_attr_show(struct kobject *kobj, 92 + struct attribute *_attr, char *buf) 93 + { 94 + struct esre_entry *entry = to_entry(kobj); 95 + struct esre_attribute *attr = to_attr(_attr); 96 + 97 + /* Don't tell normal users what firmware versions we've got... */ 98 + if (!capable(CAP_SYS_ADMIN)) 99 + return -EACCES; 100 + 101 + return attr->show(entry, buf); 102 + } 103 + 104 + static const struct sysfs_ops esre_attr_ops = { 105 + .show = esre_attr_show, 106 + }; 107 + 108 + /* Generic ESRT Entry ("ESRE") support. */ 109 + static ssize_t esre_fw_class_show(struct esre_entry *entry, char *buf) 110 + { 111 + char *str = buf; 112 + 113 + efi_guid_to_str(&entry->esre.esre1->fw_class, str); 114 + str += strlen(str); 115 + str += sprintf(str, "\n"); 116 + 117 + return str - buf; 118 + } 119 + 120 + static struct esre_attribute esre_fw_class = __ATTR(fw_class, 0400, 121 + esre_fw_class_show, NULL); 122 + 123 + #define esre_attr_decl(name, size, fmt) \ 124 + static ssize_t esre_##name##_show(struct esre_entry *entry, char *buf) \ 125 + { \ 126 + return sprintf(buf, fmt "\n", \ 127 + le##size##_to_cpu(entry->esre.esre1->name)); \ 128 + } \ 129 + \ 130 + static struct esre_attribute esre_##name = __ATTR(name, 0400, \ 131 + esre_##name##_show, NULL) 132 + 133 + esre_attr_decl(fw_type, 32, "%u"); 134 + esre_attr_decl(fw_version, 32, "%u"); 135 + esre_attr_decl(lowest_supported_fw_version, 32, "%u"); 136 + esre_attr_decl(capsule_flags, 32, "0x%x"); 137 + esre_attr_decl(last_attempt_version, 32, "%u"); 138 + esre_attr_decl(last_attempt_status, 32, "%u"); 139 + 140 + static struct attribute *esre1_attrs[] = { 141 + &esre_fw_class.attr, 142 + &esre_fw_type.attr, 143 + &esre_fw_version.attr, 144 + &esre_lowest_supported_fw_version.attr, 145 + &esre_capsule_flags.attr, 146 + &esre_last_attempt_version.attr, 147 + &esre_last_attempt_status.attr, 148 + NULL 149 + }; 150 + static void esre_release(struct kobject *kobj) 151 + { 152 + struct esre_entry *entry = to_entry(kobj); 153 + 154 + list_del(&entry->list); 155 + kfree(entry); 156 + } 157 + 158 + static struct kobj_type esre1_ktype = { 159 + .release = esre_release, 160 + .sysfs_ops = &esre_attr_ops, 161 + .default_attrs = esre1_attrs, 162 + }; 163 + 164 + 165 + static struct kobject *esrt_kobj; 166 + static struct kset *esrt_kset; 167 + 168 + static int esre_create_sysfs_entry(void *esre, int entry_num) 169 + { 170 + struct esre_entry *entry; 171 + char name[20]; 172 + 173 + entry = kzalloc(sizeof(*entry), GFP_KERNEL); 174 + if (!entry) 175 + return -ENOMEM; 176 + 177 + sprintf(name, "entry%d", entry_num); 178 + 179 + entry->kobj.kset = esrt_kset; 180 + 181 + if (esrt->fw_resource_version == 1) { 182 + int rc = 0; 183 + 184 + entry->esre.esre1 = esre; 185 + rc = kobject_init_and_add(&entry->kobj, &esre1_ktype, NULL, 186 + "%s", name); 187 + if (rc) { 188 + kfree(entry); 189 + return rc; 190 + } 191 + } 192 + 193 + list_add_tail(&entry->list, &entry_list); 194 + return 0; 195 + } 196 + 197 + /* support for displaying ESRT fields at the top level */ 198 + #define esrt_attr_decl(name, size, fmt) \ 199 + static ssize_t esrt_##name##_show(struct kobject *kobj, \ 200 + struct kobj_attribute *attr, char *buf)\ 201 + { \ 202 + return sprintf(buf, fmt "\n", le##size##_to_cpu(esrt->name)); \ 203 + } \ 204 + \ 205 + static struct kobj_attribute esrt_##name = __ATTR(name, 0400, \ 206 + esrt_##name##_show, NULL) 207 + 208 + esrt_attr_decl(fw_resource_count, 32, "%u"); 209 + esrt_attr_decl(fw_resource_count_max, 32, "%u"); 210 + esrt_attr_decl(fw_resource_version, 64, "%llu"); 211 + 212 + static struct attribute *esrt_attrs[] = { 213 + &esrt_fw_resource_count.attr, 214 + &esrt_fw_resource_count_max.attr, 215 + &esrt_fw_resource_version.attr, 216 + NULL, 217 + }; 218 + 219 + static inline int esrt_table_exists(void) 220 + { 221 + if (!efi_enabled(EFI_CONFIG_TABLES)) 222 + return 0; 223 + if (efi.esrt == EFI_INVALID_TABLE_ADDR) 224 + return 0; 225 + return 1; 226 + } 227 + 228 + static umode_t esrt_attr_is_visible(struct kobject *kobj, 229 + struct attribute *attr, int n) 230 + { 231 + if (!esrt_table_exists()) 232 + return 0; 233 + return attr->mode; 234 + } 235 + 236 + static struct attribute_group esrt_attr_group = { 237 + .attrs = esrt_attrs, 238 + .is_visible = esrt_attr_is_visible, 239 + }; 240 + 241 + /* 242 + * remap the table, copy it to kmalloced pages, and unmap it. 243 + */ 244 + void __init efi_esrt_init(void) 245 + { 246 + void *va; 247 + struct efi_system_resource_table tmpesrt; 248 + struct efi_system_resource_entry_v1 *v1_entries; 249 + size_t size, max, entry_size, entries_size; 250 + efi_memory_desc_t md; 251 + int rc; 252 + phys_addr_t end; 253 + 254 + pr_debug("esrt-init: loading.\n"); 255 + if (!esrt_table_exists()) 256 + return; 257 + 258 + rc = efi_mem_desc_lookup(efi.esrt, &md); 259 + if (rc < 0) { 260 + pr_err("ESRT header is not in the memory map.\n"); 261 + return; 262 + } 263 + 264 + max = efi_mem_desc_end(&md); 265 + if (max < efi.esrt) { 266 + pr_err("EFI memory descriptor is invalid. (esrt: %p max: %p)\n", 267 + (void *)efi.esrt, (void *)max); 268 + return; 269 + } 270 + 271 + size = sizeof(*esrt); 272 + max -= efi.esrt; 273 + 274 + if (max < size) { 275 + pr_err("ESRT header doen't fit on single memory map entry. (size: %zu max: %zu)\n", 276 + size, max); 277 + return; 278 + } 279 + 280 + va = early_memremap(efi.esrt, size); 281 + if (!va) { 282 + pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt, 283 + size); 284 + return; 285 + } 286 + 287 + memcpy(&tmpesrt, va, sizeof(tmpesrt)); 288 + 289 + if (tmpesrt.fw_resource_version == 1) { 290 + entry_size = sizeof (*v1_entries); 291 + } else { 292 + pr_err("Unsupported ESRT version %lld.\n", 293 + tmpesrt.fw_resource_version); 294 + return; 295 + } 296 + 297 + if (tmpesrt.fw_resource_count > 0 && max - size < entry_size) { 298 + pr_err("ESRT memory map entry can only hold the header. (max: %zu size: %zu)\n", 299 + max - size, entry_size); 300 + goto err_memunmap; 301 + } 302 + 303 + /* 304 + * The format doesn't really give us any boundary to test here, 305 + * so I'm making up 128 as the max number of individually updatable 306 + * components we support. 307 + * 128 should be pretty excessive, but there's still some chance 308 + * somebody will do that someday and we'll need to raise this. 309 + */ 310 + if (tmpesrt.fw_resource_count > 128) { 311 + pr_err("ESRT says fw_resource_count has very large value %d.\n", 312 + tmpesrt.fw_resource_count); 313 + goto err_memunmap; 314 + } 315 + 316 + /* 317 + * We know it can't be larger than N * sizeof() here, and N is limited 318 + * by the previous test to a small number, so there's no overflow. 319 + */ 320 + entries_size = tmpesrt.fw_resource_count * entry_size; 321 + if (max < size + entries_size) { 322 + pr_err("ESRT does not fit on single memory map entry (size: %zu max: %zu)\n", 323 + size, max); 324 + goto err_memunmap; 325 + } 326 + 327 + /* remap it with our (plausible) new pages */ 328 + early_memunmap(va, size); 329 + size += entries_size; 330 + va = early_memremap(efi.esrt, size); 331 + if (!va) { 332 + pr_err("early_memremap(%p, %zu) failed.\n", (void *)efi.esrt, 333 + size); 334 + return; 335 + } 336 + 337 + esrt_data = (phys_addr_t)efi.esrt; 338 + esrt_data_size = size; 339 + 340 + end = esrt_data + size; 341 + pr_info("Reserving ESRT space from %pa to %pa.\n", &esrt_data, &end); 342 + memblock_reserve(esrt_data, esrt_data_size); 343 + 344 + pr_debug("esrt-init: loaded.\n"); 345 + err_memunmap: 346 + early_memunmap(va, size); 347 + } 348 + 349 + static int __init register_entries(void) 350 + { 351 + struct efi_system_resource_entry_v1 *v1_entries = (void *)esrt->entries; 352 + int i, rc; 353 + 354 + if (!esrt_table_exists()) 355 + return 0; 356 + 357 + for (i = 0; i < le32_to_cpu(esrt->fw_resource_count); i++) { 358 + void *esre = NULL; 359 + if (esrt->fw_resource_version == 1) { 360 + esre = &v1_entries[i]; 361 + } else { 362 + pr_err("Unsupported ESRT version %lld.\n", 363 + esrt->fw_resource_version); 364 + return -EINVAL; 365 + } 366 + 367 + rc = esre_create_sysfs_entry(esre, i); 368 + if (rc < 0) { 369 + pr_err("ESRT entry creation failed with error %d.\n", 370 + rc); 371 + return rc; 372 + } 373 + } 374 + return 0; 375 + } 376 + 377 + static void cleanup_entry_list(void) 378 + { 379 + struct esre_entry *entry, *next; 380 + 381 + list_for_each_entry_safe(entry, next, &entry_list, list) { 382 + kobject_put(&entry->kobj); 383 + } 384 + } 385 + 386 + static int __init esrt_sysfs_init(void) 387 + { 388 + int error; 389 + struct efi_system_resource_table __iomem *ioesrt; 390 + 391 + pr_debug("esrt-sysfs: loading.\n"); 392 + if (!esrt_data || !esrt_data_size) 393 + return -ENOSYS; 394 + 395 + ioesrt = ioremap(esrt_data, esrt_data_size); 396 + if (!ioesrt) { 397 + pr_err("ioremap(%pa, %zu) failed.\n", &esrt_data, 398 + esrt_data_size); 399 + return -ENOMEM; 400 + } 401 + 402 + esrt = kmalloc(esrt_data_size, GFP_KERNEL); 403 + if (!esrt) { 404 + pr_err("kmalloc failed. (wanted %zu bytes)\n", esrt_data_size); 405 + iounmap(ioesrt); 406 + return -ENOMEM; 407 + } 408 + 409 + memcpy_fromio(esrt, ioesrt, esrt_data_size); 410 + 411 + esrt_kobj = kobject_create_and_add("esrt", efi_kobj); 412 + if (!esrt_kobj) { 413 + pr_err("Firmware table registration failed.\n"); 414 + error = -ENOMEM; 415 + goto err; 416 + } 417 + 418 + error = sysfs_create_group(esrt_kobj, &esrt_attr_group); 419 + if (error) { 420 + pr_err("Sysfs attribute export failed with error %d.\n", 421 + error); 422 + goto err_remove_esrt; 423 + } 424 + 425 + esrt_kset = kset_create_and_add("entries", NULL, esrt_kobj); 426 + if (!esrt_kset) { 427 + pr_err("kset creation failed.\n"); 428 + error = -ENOMEM; 429 + goto err_remove_group; 430 + } 431 + 432 + error = register_entries(); 433 + if (error) 434 + goto err_cleanup_list; 435 + 436 + memblock_remove(esrt_data, esrt_data_size); 437 + 438 + pr_debug("esrt-sysfs: loaded.\n"); 439 + 440 + return 0; 441 + err_cleanup_list: 442 + cleanup_entry_list(); 443 + kset_unregister(esrt_kset); 444 + err_remove_group: 445 + sysfs_remove_group(esrt_kobj, &esrt_attr_group); 446 + err_remove_esrt: 447 + kobject_put(esrt_kobj); 448 + err: 449 + kfree(esrt); 450 + esrt = NULL; 451 + return error; 452 + } 453 + 454 + static void __exit esrt_sysfs_exit(void) 455 + { 456 + pr_debug("esrt-sysfs: unloading.\n"); 457 + cleanup_entry_list(); 458 + kset_unregister(esrt_kset); 459 + sysfs_remove_group(esrt_kobj, &esrt_attr_group); 460 + kfree(esrt); 461 + esrt = NULL; 462 + kobject_del(esrt_kobj); 463 + kobject_put(esrt_kobj); 464 + } 465 + 466 + module_init(esrt_sysfs_init); 467 + module_exit(esrt_sysfs_exit); 468 + 469 + MODULE_AUTHOR("Peter Jones <pjones@redhat.com>"); 470 + MODULE_DESCRIPTION("EFI System Resource Table support"); 471 + MODULE_LICENSE("GPL");
+8
include/linux/efi.h
··· 583 583 #define EFI_FILE_INFO_ID \ 584 584 EFI_GUID( 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) 585 585 586 + #define EFI_SYSTEM_RESOURCE_TABLE_GUID \ 587 + EFI_GUID( 0xb122a263, 0x3661, 0x4f68, 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80 ) 588 + 586 589 #define EFI_FILE_SYSTEM_GUID \ 587 590 EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) 588 591 ··· 826 823 unsigned long fw_vendor; /* fw_vendor */ 827 824 unsigned long runtime; /* runtime table */ 828 825 unsigned long config_table; /* config tables */ 826 + unsigned long esrt; /* ESRT table */ 829 827 efi_get_time_t *get_time; 830 828 efi_set_time_t *set_time; 831 829 efi_get_wakeup_time_t *get_wakeup_time; ··· 879 875 #endif 880 876 extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); 881 877 extern int efi_config_init(efi_config_table_type_t *arch_tables); 878 + extern void __init efi_esrt_init(void); 882 879 extern int efi_config_parse_tables(void *config_tables, int count, int sz, 883 880 efi_config_table_type_t *arch_tables); 884 881 extern u64 efi_get_iobase (void); ··· 887 882 extern u64 efi_mem_attributes (unsigned long phys_addr); 888 883 extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); 889 884 extern int __init efi_uart_console_only (void); 885 + extern u64 efi_mem_desc_end(efi_memory_desc_t *md); 886 + extern int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md); 890 887 extern void efi_initialize_iomem_resources(struct resource *code_resource, 891 888 struct resource *data_resource, struct resource *bss_resource); 892 889 extern void efi_get_time(struct timespec *now); 893 890 extern void efi_reserve_boot_services(void); 894 891 extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose); 895 892 extern struct efi_memory_map memmap; 893 + extern struct kobject *efi_kobj; 896 894 897 895 extern int efi_reboot_quirk_mode; 898 896 extern bool efi_poweroff_required(void);