diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-22 20:10:44 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-22 20:10:44 -0400 |
| commit | cfe3eceb7a2eb91284d5605c5315249bb165e9d3 (patch) | |
| tree | a18d2440ae8dac55119ef13b8b434431408ddc1b | |
| parent | 5ef6ca4f24b59af7f7c2c19502a3923a4bc10e0a (diff) | |
| parent | d4f7743542f20c2b20b68bba856c281ba9c84e42 (diff) | |
Merge branch 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 EFI updates from Ingo Molnar:
"EFI changes:
- 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)"
* 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
efi: Work around ia64 build problem with ESRT driver
efi: Add 'systab' information to Documentation/ABI
efi: dmi: List SMBIOS3 table before SMBIOS table
efi/esrt: Fix some compiler warnings
x86, doc: Remove cmdline_size from list of fields to be filled in for EFI handover
efi: Add esrt support
efi: efivar_create_sysfs_entry() should return negative error codes
| -rw-r--r-- | Documentation/ABI/testing/sysfs-firmware-efi | 10 | ||||
| -rw-r--r-- | Documentation/ABI/testing/sysfs-firmware-efi-esrt | 81 | ||||
| -rw-r--r-- | Documentation/x86/boot.txt | 1 | ||||
| -rw-r--r-- | arch/x86/platform/efi/efi.c | 2 | ||||
| -rw-r--r-- | drivers/firmware/efi/Kconfig | 5 | ||||
| -rw-r--r-- | drivers/firmware/efi/Makefile | 1 | ||||
| -rw-r--r-- | drivers/firmware/efi/efi.c | 91 | ||||
| -rw-r--r-- | drivers/firmware/efi/efivars.c | 11 | ||||
| -rw-r--r-- | drivers/firmware/efi/esrt.c | 471 | ||||
| -rw-r--r-- | include/linux/efi.h | 12 |
10 files changed, 676 insertions, 9 deletions
diff --git a/Documentation/ABI/testing/sysfs-firmware-efi b/Documentation/ABI/testing/sysfs-firmware-efi index 05874da7ce80..e794eac32a90 100644 --- a/Documentation/ABI/testing/sysfs-firmware-efi +++ b/Documentation/ABI/testing/sysfs-firmware-efi | |||
| @@ -18,3 +18,13 @@ Contact: Dave Young <dyoung@redhat.com> | |||
| 18 | Description: It shows the physical address of config table entry in the EFI | 18 | Description: It shows the physical address of config table entry in the EFI |
| 19 | system table. | 19 | system table. |
| 20 | Users: Kexec | 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 | ||
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 @@ | |||
| 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 | |||
diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt index 88b85899d309..7c1f9fad6674 100644 --- a/Documentation/x86/boot.txt +++ b/Documentation/x86/boot.txt | |||
| @@ -1124,7 +1124,6 @@ The boot loader *must* fill out the following fields in bp, | |||
| 1124 | 1124 | ||
| 1125 | o hdr.code32_start | 1125 | o hdr.code32_start |
| 1126 | o hdr.cmd_line_ptr | 1126 | o hdr.cmd_line_ptr |
| 1127 | o hdr.cmdline_size | ||
| 1128 | o hdr.ramdisk_image (if applicable) | 1127 | o hdr.ramdisk_image (if applicable) |
| 1129 | o hdr.ramdisk_size (if applicable) | 1128 | o hdr.ramdisk_size (if applicable) |
| 1130 | 1129 | ||
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) | |||
| 501 | 501 | ||
| 502 | if (efi_enabled(EFI_DBG)) | 502 | if (efi_enabled(EFI_DBG)) |
| 503 | print_efi_memmap(); | 503 | print_efi_memmap(); |
| 504 | |||
| 505 | efi_esrt_init(); | ||
| 504 | } | 506 | } |
| 505 | 507 | ||
| 506 | void __init efi_late_init(void) | 508 | void __init efi_late_init(void) |
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 8de4da5c9ab6..54071c148340 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig | |||
| @@ -18,6 +18,11 @@ config EFI_VARS | |||
| 18 | Subsequent efibootmgr releases may be found at: | 18 | Subsequent efibootmgr releases may be found at: |
| 19 | <http://github.com/vathpela/efibootmgr> | 19 | <http://github.com/vathpela/efibootmgr> |
| 20 | 20 | ||
| 21 | config EFI_ESRT | ||
| 22 | bool | ||
| 23 | depends on EFI && !IA64 | ||
| 24 | default y | ||
| 25 | |||
| 21 | config EFI_VARS_PSTORE | 26 | config EFI_VARS_PSTORE |
| 22 | tristate "Register efivars backend for pstore" | 27 | tristate "Register efivars backend for pstore" |
| 23 | depends on EFI_VARS && PSTORE | 28 | depends on EFI_VARS && PSTORE |
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index d8be608a9f3b..6fd3da938717 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | # | 3 | # |
| 4 | obj-$(CONFIG_EFI) += efi.o vars.o reboot.o | 4 | obj-$(CONFIG_EFI) += efi.o vars.o reboot.o |
| 5 | obj-$(CONFIG_EFI_VARS) += efivars.o | 5 | obj-$(CONFIG_EFI_VARS) += efivars.o |
| 6 | obj-$(CONFIG_EFI_ESRT) += esrt.o | ||
| 6 | obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o | 7 | obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o |
| 7 | obj-$(CONFIG_UEFI_CPER) += cper.o | 8 | obj-$(CONFIG_UEFI_CPER) += cper.o |
| 8 | obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o | 9 | obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o |
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 3061bb8629dc..ca617f40574a 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c | |||
| @@ -39,6 +39,7 @@ struct efi __read_mostly efi = { | |||
| 39 | .fw_vendor = EFI_INVALID_TABLE_ADDR, | 39 | .fw_vendor = EFI_INVALID_TABLE_ADDR, |
| 40 | .runtime = EFI_INVALID_TABLE_ADDR, | 40 | .runtime = EFI_INVALID_TABLE_ADDR, |
| 41 | .config_table = EFI_INVALID_TABLE_ADDR, | 41 | .config_table = EFI_INVALID_TABLE_ADDR, |
| 42 | .esrt = EFI_INVALID_TABLE_ADDR, | ||
| 42 | }; | 43 | }; |
| 43 | EXPORT_SYMBOL(efi); | 44 | EXPORT_SYMBOL(efi); |
| 44 | 45 | ||
| @@ -64,7 +65,7 @@ static int __init parse_efi_cmdline(char *str) | |||
| 64 | } | 65 | } |
| 65 | early_param("efi", parse_efi_cmdline); | 66 | early_param("efi", parse_efi_cmdline); |
| 66 | 67 | ||
| 67 | static struct kobject *efi_kobj; | 68 | struct kobject *efi_kobj; |
| 68 | static struct kobject *efivars_kobj; | 69 | static struct kobject *efivars_kobj; |
| 69 | 70 | ||
| 70 | /* | 71 | /* |
| @@ -85,10 +86,15 @@ static ssize_t systab_show(struct kobject *kobj, | |||
| 85 | str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20); | 86 | str += sprintf(str, "ACPI20=0x%lx\n", efi.acpi20); |
| 86 | if (efi.acpi != EFI_INVALID_TABLE_ADDR) | 87 | if (efi.acpi != EFI_INVALID_TABLE_ADDR) |
| 87 | str += sprintf(str, "ACPI=0x%lx\n", efi.acpi); | 88 | str += sprintf(str, "ACPI=0x%lx\n", efi.acpi); |
| 88 | if (efi.smbios != EFI_INVALID_TABLE_ADDR) | 89 | /* |
| 89 | str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); | 90 | * If both SMBIOS and SMBIOS3 entry points are implemented, the |
| 91 | * SMBIOS3 entry point shall be preferred, so we list it first to | ||
| 92 | * let applications stop parsing after the first match. | ||
| 93 | */ | ||
| 90 | if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) | 94 | if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) |
| 91 | str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3); | 95 | str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3); |
| 96 | if (efi.smbios != EFI_INVALID_TABLE_ADDR) | ||
| 97 | str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios); | ||
| 92 | if (efi.hcdp != EFI_INVALID_TABLE_ADDR) | 98 | if (efi.hcdp != EFI_INVALID_TABLE_ADDR) |
| 93 | str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp); | 99 | str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp); |
| 94 | if (efi.boot_info != EFI_INVALID_TABLE_ADDR) | 100 | if (efi.boot_info != EFI_INVALID_TABLE_ADDR) |
| @@ -232,6 +238,84 @@ err_put: | |||
| 232 | 238 | ||
| 233 | subsys_initcall(efisubsys_init); | 239 | subsys_initcall(efisubsys_init); |
| 234 | 240 | ||
| 241 | /* | ||
| 242 | * Find the efi memory descriptor for a given physical address. Given a | ||
| 243 | * physicall address, determine if it exists within an EFI Memory Map entry, | ||
| 244 | * and if so, populate the supplied memory descriptor with the appropriate | ||
| 245 | * data. | ||
| 246 | */ | ||
| 247 | int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md) | ||
| 248 | { | ||
| 249 | struct efi_memory_map *map = efi.memmap; | ||
| 250 | void *p, *e; | ||
| 251 | |||
| 252 | if (!efi_enabled(EFI_MEMMAP)) { | ||
| 253 | pr_err_once("EFI_MEMMAP is not enabled.\n"); | ||
| 254 | return -EINVAL; | ||
| 255 | } | ||
| 256 | |||
| 257 | if (!map) { | ||
| 258 | pr_err_once("efi.memmap is not set.\n"); | ||
| 259 | return -EINVAL; | ||
| 260 | } | ||
| 261 | if (!out_md) { | ||
| 262 | pr_err_once("out_md is null.\n"); | ||
| 263 | return -EINVAL; | ||
| 264 | } | ||
| 265 | if (WARN_ON_ONCE(!map->phys_map)) | ||
| 266 | return -EINVAL; | ||
| 267 | if (WARN_ON_ONCE(map->nr_map == 0) || WARN_ON_ONCE(map->desc_size == 0)) | ||
| 268 | return -EINVAL; | ||
| 269 | |||
| 270 | e = map->phys_map + map->nr_map * map->desc_size; | ||
| 271 | for (p = map->phys_map; p < e; p += map->desc_size) { | ||
| 272 | efi_memory_desc_t *md; | ||
| 273 | u64 size; | ||
| 274 | u64 end; | ||
| 275 | |||
| 276 | /* | ||
| 277 | * If a driver calls this after efi_free_boot_services, | ||
| 278 | * ->map will be NULL, and the target may also not be mapped. | ||
| 279 | * So just always get our own virtual map on the CPU. | ||
| 280 | * | ||
| 281 | */ | ||
| 282 | md = early_memremap((phys_addr_t)p, sizeof (*md)); | ||
| 283 | if (!md) { | ||
| 284 | pr_err_once("early_memremap(%p, %zu) failed.\n", | ||
| 285 | p, sizeof (*md)); | ||
| 286 | return -ENOMEM; | ||
| 287 | } | ||
| 288 | |||
| 289 | if (!(md->attribute & EFI_MEMORY_RUNTIME) && | ||
| 290 | md->type != EFI_BOOT_SERVICES_DATA && | ||
| 291 | md->type != EFI_RUNTIME_SERVICES_DATA) { | ||
| 292 | early_memunmap(md, sizeof (*md)); | ||
| 293 | continue; | ||
| 294 | } | ||
| 295 | |||
| 296 | size = md->num_pages << EFI_PAGE_SHIFT; | ||
| 297 | end = md->phys_addr + size; | ||
| 298 | if (phys_addr >= md->phys_addr && phys_addr < end) { | ||
| 299 | memcpy(out_md, md, sizeof(*out_md)); | ||
| 300 | early_memunmap(md, sizeof (*md)); | ||
| 301 | return 0; | ||
| 302 | } | ||
| 303 | |||
| 304 | early_memunmap(md, sizeof (*md)); | ||
| 305 | } | ||
| 306 | pr_err_once("requested map not found.\n"); | ||
| 307 | return -ENOENT; | ||
| 308 | } | ||
| 309 | |||
| 310 | /* | ||
| 311 | * Calculate the highest address of an efi memory descriptor. | ||
| 312 | */ | ||
| 313 | u64 __init efi_mem_desc_end(efi_memory_desc_t *md) | ||
| 314 | { | ||
| 315 | u64 size = md->num_pages << EFI_PAGE_SHIFT; | ||
| 316 | u64 end = md->phys_addr + size; | ||
| 317 | return end; | ||
| 318 | } | ||
| 235 | 319 | ||
| 236 | /* | 320 | /* |
| 237 | * We can't ioremap data in EFI boot services RAM, because we've already mapped | 321 | * We can't ioremap data in EFI boot services RAM, because we've already mapped |
| @@ -274,6 +358,7 @@ static __initdata efi_config_table_type_t common_tables[] = { | |||
| 274 | {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios}, | 358 | {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios}, |
| 275 | {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3}, | 359 | {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3}, |
| 276 | {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, | 360 | {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, |
| 361 | {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt}, | ||
| 277 | {NULL_GUID, NULL, NULL}, | 362 | {NULL_GUID, NULL, NULL}, |
| 278 | }; | 363 | }; |
| 279 | 364 | ||
diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index 7b2e0496e0c0..756eca8c4cf8 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c | |||
| @@ -535,7 +535,7 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, | |||
| 535 | * efivar_create_sysfs_entry - create a new entry in sysfs | 535 | * efivar_create_sysfs_entry - create a new entry in sysfs |
| 536 | * @new_var: efivar entry to create | 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 | static int | 540 | static int |
| 541 | efivar_create_sysfs_entry(struct efivar_entry *new_var) | 541 | efivar_create_sysfs_entry(struct efivar_entry *new_var) |
| @@ -544,6 +544,7 @@ efivar_create_sysfs_entry(struct efivar_entry *new_var) | |||
| 544 | char *short_name; | 544 | char *short_name; |
| 545 | unsigned long variable_name_size; | 545 | unsigned long variable_name_size; |
| 546 | efi_char16_t *variable_name; | 546 | efi_char16_t *variable_name; |
| 547 | int ret; | ||
| 547 | 548 | ||
| 548 | variable_name = new_var->var.VariableName; | 549 | variable_name = new_var->var.VariableName; |
| 549 | variable_name_size = ucs2_strlen(variable_name) * sizeof(efi_char16_t); | 550 | variable_name_size = ucs2_strlen(variable_name) * sizeof(efi_char16_t); |
| @@ -558,7 +559,7 @@ efivar_create_sysfs_entry(struct efivar_entry *new_var) | |||
| 558 | short_name = kzalloc(short_name_size, GFP_KERNEL); | 559 | short_name = kzalloc(short_name_size, GFP_KERNEL); |
| 559 | 560 | ||
| 560 | if (!short_name) | 561 | if (!short_name) |
| 561 | return 1; | 562 | return -ENOMEM; |
| 562 | 563 | ||
| 563 | /* Convert Unicode to normal chars (assume top bits are 0), | 564 | /* Convert Unicode to normal chars (assume top bits are 0), |
| 564 | ala UTF-8 */ | 565 | ala UTF-8 */ |
| @@ -574,11 +575,11 @@ efivar_create_sysfs_entry(struct efivar_entry *new_var) | |||
| 574 | 575 | ||
| 575 | new_var->kobj.kset = efivars_kset; | 576 | new_var->kobj.kset = efivars_kset; |
| 576 | 577 | ||
| 577 | i = kobject_init_and_add(&new_var->kobj, &efivar_ktype, | 578 | ret = kobject_init_and_add(&new_var->kobj, &efivar_ktype, |
| 578 | NULL, "%s", short_name); | 579 | NULL, "%s", short_name); |
| 579 | kfree(short_name); | 580 | kfree(short_name); |
| 580 | if (i) | 581 | if (ret) |
| 581 | return 1; | 582 | return ret; |
| 582 | 583 | ||
| 583 | kobject_uevent(&new_var->kobj, KOBJ_ADD); | 584 | kobject_uevent(&new_var->kobj, KOBJ_ADD); |
| 584 | efivar_entry_add(new_var, &efivar_sysfs_list); | 585 | efivar_entry_add(new_var, &efivar_sysfs_list); |
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c new file mode 100644 index 000000000000..a5b95d61ae71 --- /dev/null +++ b/drivers/firmware/efi/esrt.c | |||
| @@ -0,0 +1,471 @@ | |||
| 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"); | ||
diff --git a/include/linux/efi.h b/include/linux/efi.h index af5be0368dec..2092965afca3 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
| @@ -583,6 +583,9 @@ void efi_native_runtime_setup(void); | |||
| 583 | #define EFI_FILE_INFO_ID \ | 583 | #define EFI_FILE_INFO_ID \ |
| 584 | EFI_GUID( 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) | 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 | #define EFI_FILE_SYSTEM_GUID \ | 589 | #define EFI_FILE_SYSTEM_GUID \ |
| 587 | EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) | 590 | EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) |
| 588 | 591 | ||
| @@ -823,6 +826,7 @@ extern struct efi { | |||
| 823 | unsigned long fw_vendor; /* fw_vendor */ | 826 | unsigned long fw_vendor; /* fw_vendor */ |
| 824 | unsigned long runtime; /* runtime table */ | 827 | unsigned long runtime; /* runtime table */ |
| 825 | unsigned long config_table; /* config tables */ | 828 | unsigned long config_table; /* config tables */ |
| 829 | unsigned long esrt; /* ESRT table */ | ||
| 826 | efi_get_time_t *get_time; | 830 | efi_get_time_t *get_time; |
| 827 | efi_set_time_t *set_time; | 831 | efi_set_time_t *set_time; |
| 828 | efi_get_wakeup_time_t *get_wakeup_time; | 832 | efi_get_wakeup_time_t *get_wakeup_time; |
| @@ -875,6 +879,11 @@ static inline efi_status_t efi_query_variable_store(u32 attributes, unsigned lon | |||
| 875 | #endif | 879 | #endif |
| 876 | extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); | 880 | extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); |
| 877 | extern int efi_config_init(efi_config_table_type_t *arch_tables); | 881 | extern int efi_config_init(efi_config_table_type_t *arch_tables); |
| 882 | #ifdef CONFIG_EFI_ESRT | ||
| 883 | extern void __init efi_esrt_init(void); | ||
| 884 | #else | ||
| 885 | static inline void efi_esrt_init(void) { } | ||
| 886 | #endif | ||
| 878 | extern int efi_config_parse_tables(void *config_tables, int count, int sz, | 887 | extern int efi_config_parse_tables(void *config_tables, int count, int sz, |
| 879 | efi_config_table_type_t *arch_tables); | 888 | efi_config_table_type_t *arch_tables); |
| 880 | extern u64 efi_get_iobase (void); | 889 | extern u64 efi_get_iobase (void); |
| @@ -882,12 +891,15 @@ extern u32 efi_mem_type (unsigned long phys_addr); | |||
| 882 | extern u64 efi_mem_attributes (unsigned long phys_addr); | 891 | extern u64 efi_mem_attributes (unsigned long phys_addr); |
| 883 | extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); | 892 | extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); |
| 884 | extern int __init efi_uart_console_only (void); | 893 | extern int __init efi_uart_console_only (void); |
| 894 | extern u64 efi_mem_desc_end(efi_memory_desc_t *md); | ||
| 895 | extern int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md); | ||
| 885 | extern void efi_initialize_iomem_resources(struct resource *code_resource, | 896 | extern void efi_initialize_iomem_resources(struct resource *code_resource, |
| 886 | struct resource *data_resource, struct resource *bss_resource); | 897 | struct resource *data_resource, struct resource *bss_resource); |
| 887 | extern void efi_get_time(struct timespec *now); | 898 | extern void efi_get_time(struct timespec *now); |
| 888 | extern void efi_reserve_boot_services(void); | 899 | extern void efi_reserve_boot_services(void); |
| 889 | extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose); | 900 | extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose); |
| 890 | extern struct efi_memory_map memmap; | 901 | extern struct efi_memory_map memmap; |
| 902 | extern struct kobject *efi_kobj; | ||
| 891 | 903 | ||
| 892 | extern int efi_reboot_quirk_mode; | 904 | extern int efi_reboot_quirk_mode; |
| 893 | extern bool efi_poweroff_required(void); | 905 | extern bool efi_poweroff_required(void); |
