diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-03 15:12:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-03 15:12:05 -0400 |
commit | 162b246eb420d2ca2002a50917c897b10c9aba09 (patch) | |
tree | bb4158555fafd21270446a9f7cb3f4b77d77912c | |
parent | 330e9e46253cbfab178450c976aa90ef0f3ae940 (diff) | |
parent | 6c64447ec58b0bac612732303f7ab04562124587 (diff) |
Merge branch 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI updates from Ingo Molnar:
"The main changes in this cycle were:
- Rework the EFI capsule loader to allow for workarounds for
non-compliant firmware (Ard Biesheuvel)
- Implement a capsule loader quirk for Quark X102x (Jan Kiszka)
- Enable SMBIOS/DMI support for the ARM architecture (Ard Biesheuvel)
- Add CONFIG_EFI_PGT_DUMP=y support for x86-32 and kexec (Sai
Praneeth)
- Fixes for EFI support for Xen dom0 guests running under x86-64
hosts (Daniel Kiper)"
* 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/xen/efi: Initialize only the EFI struct members used by Xen
efi: Process the MEMATTR table only if EFI_MEMMAP is enabled
efi/arm: Enable DMI/SMBIOS
x86/efi: Extend CONFIG_EFI_PGT_DUMP support to x86_32 and kexec as well
efi/efi_test: Use memdup_user() helper
efi/capsule: Add support for Quark security header
efi/capsule-loader: Use page addresses rather than struct page pointers
efi/capsule-loader: Redirect calls to efi_capsule_setup_info() via weak alias
efi/capsule: Remove NULL test on kmap()
efi/capsule-loader: Use a cached copy of the capsule header
efi/capsule: Adjust return type of efi_capsule_setup_info()
efi/capsule: Clean up pr_err/_info() messages
efi/capsule: Remove pr_debug() on ENOMEM or EFAULT
efi/capsule: Fix return code on failing kmap/vmap
-rw-r--r-- | arch/arm/Kconfig | 17 | ||||
-rw-r--r-- | arch/arm/include/asm/dmi.h | 19 | ||||
-rw-r--r-- | arch/arm64/kernel/efi.c | 15 | ||||
-rw-r--r-- | arch/x86/platform/efi/efi.c | 3 | ||||
-rw-r--r-- | arch/x86/platform/efi/efi_32.c | 9 | ||||
-rw-r--r-- | arch/x86/platform/efi/efi_64.c | 5 | ||||
-rw-r--r-- | arch/x86/platform/efi/quirks.c | 137 | ||||
-rw-r--r-- | arch/x86/xen/efi.c | 45 | ||||
-rw-r--r-- | drivers/firmware/efi/Kconfig | 9 | ||||
-rw-r--r-- | drivers/firmware/efi/arm-runtime.c | 16 | ||||
-rw-r--r-- | drivers/firmware/efi/capsule-loader.c | 117 | ||||
-rw-r--r-- | drivers/firmware/efi/capsule.c | 11 | ||||
-rw-r--r-- | drivers/firmware/efi/efi.c | 3 | ||||
-rw-r--r-- | drivers/firmware/efi/test/efi_test.c | 11 | ||||
-rw-r--r-- | include/linux/efi.h | 14 |
15 files changed, 295 insertions, 136 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c0fcab6a5504..bf3285b7532a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -2062,6 +2062,23 @@ config EFI | |||
2062 | is only useful for kernels that may run on systems that have | 2062 | is only useful for kernels that may run on systems that have |
2063 | UEFI firmware. | 2063 | UEFI firmware. |
2064 | 2064 | ||
2065 | config DMI | ||
2066 | bool "Enable support for SMBIOS (DMI) tables" | ||
2067 | depends on EFI | ||
2068 | default y | ||
2069 | help | ||
2070 | This enables SMBIOS/DMI feature for systems. | ||
2071 | |||
2072 | This option is only useful on systems that have UEFI firmware. | ||
2073 | However, even with this option, the resultant kernel should | ||
2074 | continue to boot on existing non-UEFI platforms. | ||
2075 | |||
2076 | NOTE: This does *NOT* enable or encourage the use of DMI quirks, | ||
2077 | i.e., the the practice of identifying the platform via DMI to | ||
2078 | decide whether certain workarounds for buggy hardware and/or | ||
2079 | firmware need to be enabled. This would require the DMI subsystem | ||
2080 | to be enabled much earlier than we do on ARM, which is non-trivial. | ||
2081 | |||
2065 | endmenu | 2082 | endmenu |
2066 | 2083 | ||
2067 | menu "CPU Power Management" | 2084 | menu "CPU Power Management" |
diff --git a/arch/arm/include/asm/dmi.h b/arch/arm/include/asm/dmi.h new file mode 100644 index 000000000000..df2d2ff06f5b --- /dev/null +++ b/arch/arm/include/asm/dmi.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License version 2 as | ||
4 | * published by the Free Software Foundation. | ||
5 | */ | ||
6 | |||
7 | #ifndef __ASM_DMI_H | ||
8 | #define __ASM_DMI_H | ||
9 | |||
10 | #include <linux/io.h> | ||
11 | #include <linux/slab.h> | ||
12 | |||
13 | #define dmi_early_remap(x, l) memremap(x, l, MEMREMAP_WB) | ||
14 | #define dmi_early_unmap(x, l) memunmap(x) | ||
15 | #define dmi_remap(x, l) memremap(x, l, MEMREMAP_WB) | ||
16 | #define dmi_unmap(x) memunmap(x) | ||
17 | #define dmi_alloc(l) kzalloc(l, GFP_KERNEL) | ||
18 | |||
19 | #endif | ||
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 5d17f377d905..82cd07592519 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c | |||
@@ -11,7 +11,6 @@ | |||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/dmi.h> | ||
15 | #include <linux/efi.h> | 14 | #include <linux/efi.h> |
16 | #include <linux/init.h> | 15 | #include <linux/init.h> |
17 | 16 | ||
@@ -117,20 +116,6 @@ int __init efi_set_mapping_permissions(struct mm_struct *mm, | |||
117 | set_permissions, md); | 116 | set_permissions, md); |
118 | } | 117 | } |
119 | 118 | ||
120 | static int __init arm64_dmi_init(void) | ||
121 | { | ||
122 | /* | ||
123 | * On arm64, DMI depends on UEFI, and dmi_scan_machine() needs to | ||
124 | * be called early because dmi_id_init(), which is an arch_initcall | ||
125 | * itself, depends on dmi_scan_machine() having been called already. | ||
126 | */ | ||
127 | dmi_scan_machine(); | ||
128 | if (dmi_available) | ||
129 | dmi_set_dump_stack_arch_desc(); | ||
130 | return 0; | ||
131 | } | ||
132 | core_initcall(arm64_dmi_init); | ||
133 | |||
134 | /* | 119 | /* |
135 | * UpdateCapsule() depends on the system being shutdown via | 120 | * UpdateCapsule() depends on the system being shutdown via |
136 | * ResetSystem(). | 121 | * ResetSystem(). |
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 43b96f5f78ba..f084d8718ac4 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
@@ -1014,7 +1014,6 @@ static void __init __efi_enter_virtual_mode(void) | |||
1014 | * necessary relocation fixups for the new virtual addresses. | 1014 | * necessary relocation fixups for the new virtual addresses. |
1015 | */ | 1015 | */ |
1016 | efi_runtime_update_mappings(); | 1016 | efi_runtime_update_mappings(); |
1017 | efi_dump_pagetable(); | ||
1018 | 1017 | ||
1019 | /* clean DUMMY object */ | 1018 | /* clean DUMMY object */ |
1020 | efi_delete_dummy_variable(); | 1019 | efi_delete_dummy_variable(); |
@@ -1029,6 +1028,8 @@ void __init efi_enter_virtual_mode(void) | |||
1029 | kexec_enter_virtual_mode(); | 1028 | kexec_enter_virtual_mode(); |
1030 | else | 1029 | else |
1031 | __efi_enter_virtual_mode(); | 1030 | __efi_enter_virtual_mode(); |
1031 | |||
1032 | efi_dump_pagetable(); | ||
1032 | } | 1033 | } |
1033 | 1034 | ||
1034 | /* | 1035 | /* |
diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c index 3481268da3d0..52f7faa1538f 100644 --- a/arch/x86/platform/efi/efi_32.c +++ b/arch/x86/platform/efi/efi_32.c | |||
@@ -44,7 +44,14 @@ int __init efi_alloc_page_tables(void) | |||
44 | } | 44 | } |
45 | 45 | ||
46 | void efi_sync_low_kernel_mappings(void) {} | 46 | void efi_sync_low_kernel_mappings(void) {} |
47 | void __init efi_dump_pagetable(void) {} | 47 | |
48 | void __init efi_dump_pagetable(void) | ||
49 | { | ||
50 | #ifdef CONFIG_EFI_PGT_DUMP | ||
51 | ptdump_walk_pgd_level(NULL, swapper_pg_dir); | ||
52 | #endif | ||
53 | } | ||
54 | |||
48 | int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) | 55 | int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) |
49 | { | 56 | { |
50 | return 0; | 57 | return 0; |
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index eb8dff15a7f6..8ff1f95627f9 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c | |||
@@ -589,7 +589,10 @@ void __init efi_runtime_update_mappings(void) | |||
589 | void __init efi_dump_pagetable(void) | 589 | void __init efi_dump_pagetable(void) |
590 | { | 590 | { |
591 | #ifdef CONFIG_EFI_PGT_DUMP | 591 | #ifdef CONFIG_EFI_PGT_DUMP |
592 | ptdump_walk_pgd_level(NULL, efi_pgd); | 592 | if (efi_enabled(EFI_OLD_MEMMAP)) |
593 | ptdump_walk_pgd_level(NULL, swapper_pg_dir); | ||
594 | else | ||
595 | ptdump_walk_pgd_level(NULL, efi_pgd); | ||
593 | #endif | 596 | #endif |
594 | } | 597 | } |
595 | 598 | ||
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index e0cf95a83f3f..8a99a2e96537 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c | |||
@@ -15,12 +15,66 @@ | |||
15 | #include <asm/e820/api.h> | 15 | #include <asm/e820/api.h> |
16 | #include <asm/efi.h> | 16 | #include <asm/efi.h> |
17 | #include <asm/uv/uv.h> | 17 | #include <asm/uv/uv.h> |
18 | #include <asm/cpu_device_id.h> | ||
18 | 19 | ||
19 | #define EFI_MIN_RESERVE 5120 | 20 | #define EFI_MIN_RESERVE 5120 |
20 | 21 | ||
21 | #define EFI_DUMMY_GUID \ | 22 | #define EFI_DUMMY_GUID \ |
22 | EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, 0xa9) | 23 | EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, 0xa9) |
23 | 24 | ||
25 | #define QUARK_CSH_SIGNATURE 0x5f435348 /* _CSH */ | ||
26 | #define QUARK_SECURITY_HEADER_SIZE 0x400 | ||
27 | |||
28 | /* | ||
29 | * Header prepended to the standard EFI capsule on Quark systems the are based | ||
30 | * on Intel firmware BSP. | ||
31 | * @csh_signature: Unique identifier to sanity check signed module | ||
32 | * presence ("_CSH"). | ||
33 | * @version: Current version of CSH used. Should be one for Quark A0. | ||
34 | * @modulesize: Size of the entire module including the module header | ||
35 | * and payload. | ||
36 | * @security_version_number_index: Index of SVN to use for validation of signed | ||
37 | * module. | ||
38 | * @security_version_number: Used to prevent against roll back of modules. | ||
39 | * @rsvd_module_id: Currently unused for Clanton (Quark). | ||
40 | * @rsvd_module_vendor: Vendor Identifier. For Intel products value is | ||
41 | * 0x00008086. | ||
42 | * @rsvd_date: BCD representation of build date as yyyymmdd, where | ||
43 | * yyyy=4 digit year, mm=1-12, dd=1-31. | ||
44 | * @headersize: Total length of the header including including any | ||
45 | * padding optionally added by the signing tool. | ||
46 | * @hash_algo: What Hash is used in the module signing. | ||
47 | * @cryp_algo: What Crypto is used in the module signing. | ||
48 | * @keysize: Total length of the key data including including any | ||
49 | * padding optionally added by the signing tool. | ||
50 | * @signaturesize: Total length of the signature including including any | ||
51 | * padding optionally added by the signing tool. | ||
52 | * @rsvd_next_header: 32-bit pointer to the next Secure Boot Module in the | ||
53 | * chain, if there is a next header. | ||
54 | * @rsvd: Reserved, padding structure to required size. | ||
55 | * | ||
56 | * See also QuartSecurityHeader_t in | ||
57 | * Quark_EDKII_v1.2.1.1/QuarkPlatformPkg/Include/QuarkBootRom.h | ||
58 | * from https://downloadcenter.intel.com/download/23197/Intel-Quark-SoC-X1000-Board-Support-Package-BSP | ||
59 | */ | ||
60 | struct quark_security_header { | ||
61 | u32 csh_signature; | ||
62 | u32 version; | ||
63 | u32 modulesize; | ||
64 | u32 security_version_number_index; | ||
65 | u32 security_version_number; | ||
66 | u32 rsvd_module_id; | ||
67 | u32 rsvd_module_vendor; | ||
68 | u32 rsvd_date; | ||
69 | u32 headersize; | ||
70 | u32 hash_algo; | ||
71 | u32 cryp_algo; | ||
72 | u32 keysize; | ||
73 | u32 signaturesize; | ||
74 | u32 rsvd_next_header; | ||
75 | u32 rsvd[2]; | ||
76 | }; | ||
77 | |||
24 | static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; | 78 | static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; |
25 | 79 | ||
26 | static bool efi_no_storage_paranoia; | 80 | static bool efi_no_storage_paranoia; |
@@ -504,3 +558,86 @@ bool efi_poweroff_required(void) | |||
504 | { | 558 | { |
505 | return acpi_gbl_reduced_hardware || acpi_no_s5; | 559 | return acpi_gbl_reduced_hardware || acpi_no_s5; |
506 | } | 560 | } |
561 | |||
562 | #ifdef CONFIG_EFI_CAPSULE_QUIRK_QUARK_CSH | ||
563 | |||
564 | static int qrk_capsule_setup_info(struct capsule_info *cap_info, void **pkbuff, | ||
565 | size_t hdr_bytes) | ||
566 | { | ||
567 | struct quark_security_header *csh = *pkbuff; | ||
568 | |||
569 | /* Only process data block that is larger than the security header */ | ||
570 | if (hdr_bytes < sizeof(struct quark_security_header)) | ||
571 | return 0; | ||
572 | |||
573 | if (csh->csh_signature != QUARK_CSH_SIGNATURE || | ||
574 | csh->headersize != QUARK_SECURITY_HEADER_SIZE) | ||
575 | return 1; | ||
576 | |||
577 | /* Only process data block if EFI header is included */ | ||
578 | if (hdr_bytes < QUARK_SECURITY_HEADER_SIZE + | ||
579 | sizeof(efi_capsule_header_t)) | ||
580 | return 0; | ||
581 | |||
582 | pr_debug("Quark security header detected\n"); | ||
583 | |||
584 | if (csh->rsvd_next_header != 0) { | ||
585 | pr_err("multiple Quark security headers not supported\n"); | ||
586 | return -EINVAL; | ||
587 | } | ||
588 | |||
589 | *pkbuff += csh->headersize; | ||
590 | cap_info->total_size = csh->headersize; | ||
591 | |||
592 | /* | ||
593 | * Update the first page pointer to skip over the CSH header. | ||
594 | */ | ||
595 | cap_info->pages[0] += csh->headersize; | ||
596 | |||
597 | return 1; | ||
598 | } | ||
599 | |||
600 | #define ICPU(family, model, quirk_handler) \ | ||
601 | { X86_VENDOR_INTEL, family, model, X86_FEATURE_ANY, \ | ||
602 | (unsigned long)&quirk_handler } | ||
603 | |||
604 | static const struct x86_cpu_id efi_capsule_quirk_ids[] = { | ||
605 | ICPU(5, 9, qrk_capsule_setup_info), /* Intel Quark X1000 */ | ||
606 | { } | ||
607 | }; | ||
608 | |||
609 | int efi_capsule_setup_info(struct capsule_info *cap_info, void *kbuff, | ||
610 | size_t hdr_bytes) | ||
611 | { | ||
612 | int (*quirk_handler)(struct capsule_info *, void **, size_t); | ||
613 | const struct x86_cpu_id *id; | ||
614 | int ret; | ||
615 | |||
616 | if (hdr_bytes < sizeof(efi_capsule_header_t)) | ||
617 | return 0; | ||
618 | |||
619 | cap_info->total_size = 0; | ||
620 | |||
621 | id = x86_match_cpu(efi_capsule_quirk_ids); | ||
622 | if (id) { | ||
623 | /* | ||
624 | * The quirk handler is supposed to return | ||
625 | * - a value > 0 if the setup should continue, after advancing | ||
626 | * kbuff as needed | ||
627 | * - 0 if not enough hdr_bytes are available yet | ||
628 | * - a negative error code otherwise | ||
629 | */ | ||
630 | quirk_handler = (typeof(quirk_handler))id->driver_data; | ||
631 | ret = quirk_handler(cap_info, &kbuff, hdr_bytes); | ||
632 | if (ret <= 0) | ||
633 | return ret; | ||
634 | } | ||
635 | |||
636 | memcpy(&cap_info->header, kbuff, sizeof(cap_info->header)); | ||
637 | |||
638 | cap_info->total_size += cap_info->header.imagesize; | ||
639 | |||
640 | return __efi_capsule_setup_info(cap_info); | ||
641 | } | ||
642 | |||
643 | #endif | ||
diff --git a/arch/x86/xen/efi.c b/arch/x86/xen/efi.c index 30bb2e80cfe7..a18703be9ead 100644 --- a/arch/x86/xen/efi.c +++ b/arch/x86/xen/efi.c | |||
@@ -54,38 +54,6 @@ static efi_system_table_t efi_systab_xen __initdata = { | |||
54 | .tables = EFI_INVALID_TABLE_ADDR /* Initialized later. */ | 54 | .tables = EFI_INVALID_TABLE_ADDR /* Initialized later. */ |
55 | }; | 55 | }; |
56 | 56 | ||
57 | static const struct efi efi_xen __initconst = { | ||
58 | .systab = NULL, /* Initialized later. */ | ||
59 | .runtime_version = 0, /* Initialized later. */ | ||
60 | .mps = EFI_INVALID_TABLE_ADDR, | ||
61 | .acpi = EFI_INVALID_TABLE_ADDR, | ||
62 | .acpi20 = EFI_INVALID_TABLE_ADDR, | ||
63 | .smbios = EFI_INVALID_TABLE_ADDR, | ||
64 | .smbios3 = EFI_INVALID_TABLE_ADDR, | ||
65 | .sal_systab = EFI_INVALID_TABLE_ADDR, | ||
66 | .boot_info = EFI_INVALID_TABLE_ADDR, | ||
67 | .hcdp = EFI_INVALID_TABLE_ADDR, | ||
68 | .uga = EFI_INVALID_TABLE_ADDR, | ||
69 | .uv_systab = EFI_INVALID_TABLE_ADDR, | ||
70 | .fw_vendor = EFI_INVALID_TABLE_ADDR, | ||
71 | .runtime = EFI_INVALID_TABLE_ADDR, | ||
72 | .config_table = EFI_INVALID_TABLE_ADDR, | ||
73 | .get_time = xen_efi_get_time, | ||
74 | .set_time = xen_efi_set_time, | ||
75 | .get_wakeup_time = xen_efi_get_wakeup_time, | ||
76 | .set_wakeup_time = xen_efi_set_wakeup_time, | ||
77 | .get_variable = xen_efi_get_variable, | ||
78 | .get_next_variable = xen_efi_get_next_variable, | ||
79 | .set_variable = xen_efi_set_variable, | ||
80 | .query_variable_info = xen_efi_query_variable_info, | ||
81 | .update_capsule = xen_efi_update_capsule, | ||
82 | .query_capsule_caps = xen_efi_query_capsule_caps, | ||
83 | .get_next_high_mono_count = xen_efi_get_next_high_mono_count, | ||
84 | .reset_system = xen_efi_reset_system, | ||
85 | .set_virtual_address_map = NULL, /* Not used under Xen. */ | ||
86 | .flags = 0 /* Initialized later. */ | ||
87 | }; | ||
88 | |||
89 | static efi_system_table_t __init *xen_efi_probe(void) | 57 | static efi_system_table_t __init *xen_efi_probe(void) |
90 | { | 58 | { |
91 | struct xen_platform_op op = { | 59 | struct xen_platform_op op = { |
@@ -102,7 +70,18 @@ static efi_system_table_t __init *xen_efi_probe(void) | |||
102 | 70 | ||
103 | /* Here we know that Xen runs on EFI platform. */ | 71 | /* Here we know that Xen runs on EFI platform. */ |
104 | 72 | ||
105 | efi = efi_xen; | 73 | efi.get_time = xen_efi_get_time; |
74 | efi.set_time = xen_efi_set_time; | ||
75 | efi.get_wakeup_time = xen_efi_get_wakeup_time; | ||
76 | efi.set_wakeup_time = xen_efi_set_wakeup_time; | ||
77 | efi.get_variable = xen_efi_get_variable; | ||
78 | efi.get_next_variable = xen_efi_get_next_variable; | ||
79 | efi.set_variable = xen_efi_set_variable; | ||
80 | efi.query_variable_info = xen_efi_query_variable_info; | ||
81 | efi.update_capsule = xen_efi_update_capsule; | ||
82 | efi.query_capsule_caps = xen_efi_query_capsule_caps; | ||
83 | efi.get_next_high_mono_count = xen_efi_get_next_high_mono_count; | ||
84 | efi.reset_system = xen_efi_reset_system; | ||
106 | 85 | ||
107 | efi_systab_xen.tables = info->cfg.addr; | 86 | efi_systab_xen.tables = info->cfg.addr; |
108 | efi_systab_xen.nr_tables = info->cfg.nent; | 87 | efi_systab_xen.nr_tables = info->cfg.nent; |
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 2e78b0b96d74..394db40ed374 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig | |||
@@ -112,6 +112,15 @@ config EFI_CAPSULE_LOADER | |||
112 | 112 | ||
113 | Most users should say N. | 113 | Most users should say N. |
114 | 114 | ||
115 | config EFI_CAPSULE_QUIRK_QUARK_CSH | ||
116 | boolean "Add support for Quark capsules with non-standard headers" | ||
117 | depends on X86 && !64BIT | ||
118 | select EFI_CAPSULE_LOADER | ||
119 | default y | ||
120 | help | ||
121 | Add support for processing Quark X1000 EFI capsules, whose header | ||
122 | layout deviates from the layout mandated by the UEFI specification. | ||
123 | |||
115 | config EFI_TEST | 124 | config EFI_TEST |
116 | tristate "EFI Runtime Service Tests Support" | 125 | tristate "EFI Runtime Service Tests Support" |
117 | depends on EFI | 126 | depends on EFI |
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 974c5a31a005..1cc41c3d6315 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/dmi.h> | ||
14 | #include <linux/efi.h> | 15 | #include <linux/efi.h> |
15 | #include <linux/io.h> | 16 | #include <linux/io.h> |
16 | #include <linux/memblock.h> | 17 | #include <linux/memblock.h> |
@@ -166,3 +167,18 @@ void efi_virtmap_unload(void) | |||
166 | efi_set_pgd(current->active_mm); | 167 | efi_set_pgd(current->active_mm); |
167 | preempt_enable(); | 168 | preempt_enable(); |
168 | } | 169 | } |
170 | |||
171 | |||
172 | static int __init arm_dmi_init(void) | ||
173 | { | ||
174 | /* | ||
175 | * On arm64/ARM, DMI depends on UEFI, and dmi_scan_machine() needs to | ||
176 | * be called early because dmi_id_init(), which is an arch_initcall | ||
177 | * itself, depends on dmi_scan_machine() having been called already. | ||
178 | */ | ||
179 | dmi_scan_machine(); | ||
180 | if (dmi_available) | ||
181 | dmi_set_dump_stack_arch_desc(); | ||
182 | return 0; | ||
183 | } | ||
184 | core_initcall(arm_dmi_init); | ||
diff --git a/drivers/firmware/efi/capsule-loader.c b/drivers/firmware/efi/capsule-loader.c index 9ae6c116c474..ec8ac5c4dd84 100644 --- a/drivers/firmware/efi/capsule-loader.c +++ b/drivers/firmware/efi/capsule-loader.c | |||
@@ -20,15 +20,9 @@ | |||
20 | 20 | ||
21 | #define NO_FURTHER_WRITE_ACTION -1 | 21 | #define NO_FURTHER_WRITE_ACTION -1 |
22 | 22 | ||
23 | struct capsule_info { | 23 | #ifndef phys_to_page |
24 | bool header_obtained; | 24 | #define phys_to_page(x) pfn_to_page((x) >> PAGE_SHIFT) |
25 | int reset_type; | 25 | #endif |
26 | long index; | ||
27 | size_t count; | ||
28 | size_t total_size; | ||
29 | struct page **pages; | ||
30 | size_t page_bytes_remain; | ||
31 | }; | ||
32 | 26 | ||
33 | /** | 27 | /** |
34 | * efi_free_all_buff_pages - free all previous allocated buffer pages | 28 | * efi_free_all_buff_pages - free all previous allocated buffer pages |
@@ -41,65 +35,70 @@ struct capsule_info { | |||
41 | static void efi_free_all_buff_pages(struct capsule_info *cap_info) | 35 | static void efi_free_all_buff_pages(struct capsule_info *cap_info) |
42 | { | 36 | { |
43 | while (cap_info->index > 0) | 37 | while (cap_info->index > 0) |
44 | __free_page(cap_info->pages[--cap_info->index]); | 38 | __free_page(phys_to_page(cap_info->pages[--cap_info->index])); |
45 | 39 | ||
46 | cap_info->index = NO_FURTHER_WRITE_ACTION; | 40 | cap_info->index = NO_FURTHER_WRITE_ACTION; |
47 | } | 41 | } |
48 | 42 | ||
49 | /** | 43 | int __efi_capsule_setup_info(struct capsule_info *cap_info) |
50 | * efi_capsule_setup_info - obtain the efi capsule header in the binary and | ||
51 | * setup capsule_info structure | ||
52 | * @cap_info: pointer to current instance of capsule_info structure | ||
53 | * @kbuff: a mapped first page buffer pointer | ||
54 | * @hdr_bytes: the total received number of bytes for efi header | ||
55 | **/ | ||
56 | static ssize_t efi_capsule_setup_info(struct capsule_info *cap_info, | ||
57 | void *kbuff, size_t hdr_bytes) | ||
58 | { | 44 | { |
59 | efi_capsule_header_t *cap_hdr; | ||
60 | size_t pages_needed; | 45 | size_t pages_needed; |
61 | int ret; | 46 | int ret; |
62 | void *temp_page; | 47 | void *temp_page; |
63 | 48 | ||
64 | /* Only process data block that is larger than efi header size */ | 49 | pages_needed = ALIGN(cap_info->total_size, PAGE_SIZE) / PAGE_SIZE; |
65 | if (hdr_bytes < sizeof(efi_capsule_header_t)) | ||
66 | return 0; | ||
67 | |||
68 | /* Reset back to the correct offset of header */ | ||
69 | cap_hdr = kbuff - cap_info->count; | ||
70 | pages_needed = ALIGN(cap_hdr->imagesize, PAGE_SIZE) >> PAGE_SHIFT; | ||
71 | 50 | ||
72 | if (pages_needed == 0) { | 51 | if (pages_needed == 0) { |
73 | pr_err("%s: pages count invalid\n", __func__); | 52 | pr_err("invalid capsule size"); |
74 | return -EINVAL; | 53 | return -EINVAL; |
75 | } | 54 | } |
76 | 55 | ||
77 | /* Check if the capsule binary supported */ | 56 | /* Check if the capsule binary supported */ |
78 | ret = efi_capsule_supported(cap_hdr->guid, cap_hdr->flags, | 57 | ret = efi_capsule_supported(cap_info->header.guid, |
79 | cap_hdr->imagesize, | 58 | cap_info->header.flags, |
59 | cap_info->header.imagesize, | ||
80 | &cap_info->reset_type); | 60 | &cap_info->reset_type); |
81 | if (ret) { | 61 | if (ret) { |
82 | pr_err("%s: efi_capsule_supported() failed\n", | 62 | pr_err("capsule not supported\n"); |
83 | __func__); | ||
84 | return ret; | 63 | return ret; |
85 | } | 64 | } |
86 | 65 | ||
87 | cap_info->total_size = cap_hdr->imagesize; | ||
88 | temp_page = krealloc(cap_info->pages, | 66 | temp_page = krealloc(cap_info->pages, |
89 | pages_needed * sizeof(void *), | 67 | pages_needed * sizeof(void *), |
90 | GFP_KERNEL | __GFP_ZERO); | 68 | GFP_KERNEL | __GFP_ZERO); |
91 | if (!temp_page) { | 69 | if (!temp_page) |
92 | pr_debug("%s: krealloc() failed\n", __func__); | ||
93 | return -ENOMEM; | 70 | return -ENOMEM; |
94 | } | ||
95 | 71 | ||
96 | cap_info->pages = temp_page; | 72 | cap_info->pages = temp_page; |
97 | cap_info->header_obtained = true; | ||
98 | 73 | ||
99 | return 0; | 74 | return 0; |
100 | } | 75 | } |
101 | 76 | ||
102 | /** | 77 | /** |
78 | * efi_capsule_setup_info - obtain the efi capsule header in the binary and | ||
79 | * setup capsule_info structure | ||
80 | * @cap_info: pointer to current instance of capsule_info structure | ||
81 | * @kbuff: a mapped first page buffer pointer | ||
82 | * @hdr_bytes: the total received number of bytes for efi header | ||
83 | * | ||
84 | * Platforms with non-standard capsule update mechanisms can override | ||
85 | * this __weak function so they can perform any required capsule | ||
86 | * image munging. See quark_quirk_function() for an example. | ||
87 | **/ | ||
88 | int __weak efi_capsule_setup_info(struct capsule_info *cap_info, void *kbuff, | ||
89 | size_t hdr_bytes) | ||
90 | { | ||
91 | /* Only process data block that is larger than efi header size */ | ||
92 | if (hdr_bytes < sizeof(efi_capsule_header_t)) | ||
93 | return 0; | ||
94 | |||
95 | memcpy(&cap_info->header, kbuff, sizeof(cap_info->header)); | ||
96 | cap_info->total_size = cap_info->header.imagesize; | ||
97 | |||
98 | return __efi_capsule_setup_info(cap_info); | ||
99 | } | ||
100 | |||
101 | /** | ||
103 | * efi_capsule_submit_update - invoke the efi_capsule_update API once binary | 102 | * efi_capsule_submit_update - invoke the efi_capsule_update API once binary |
104 | * upload done | 103 | * upload done |
105 | * @cap_info: pointer to current instance of capsule_info structure | 104 | * @cap_info: pointer to current instance of capsule_info structure |
@@ -107,26 +106,17 @@ static ssize_t efi_capsule_setup_info(struct capsule_info *cap_info, | |||
107 | static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info) | 106 | static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info) |
108 | { | 107 | { |
109 | int ret; | 108 | int ret; |
110 | void *cap_hdr_temp; | ||
111 | |||
112 | cap_hdr_temp = vmap(cap_info->pages, cap_info->index, | ||
113 | VM_MAP, PAGE_KERNEL); | ||
114 | if (!cap_hdr_temp) { | ||
115 | pr_debug("%s: vmap() failed\n", __func__); | ||
116 | return -EFAULT; | ||
117 | } | ||
118 | 109 | ||
119 | ret = efi_capsule_update(cap_hdr_temp, cap_info->pages); | 110 | ret = efi_capsule_update(&cap_info->header, cap_info->pages); |
120 | vunmap(cap_hdr_temp); | ||
121 | if (ret) { | 111 | if (ret) { |
122 | pr_err("%s: efi_capsule_update() failed\n", __func__); | 112 | pr_err("capsule update failed\n"); |
123 | return ret; | 113 | return ret; |
124 | } | 114 | } |
125 | 115 | ||
126 | /* Indicate capsule binary uploading is done */ | 116 | /* Indicate capsule binary uploading is done */ |
127 | cap_info->index = NO_FURTHER_WRITE_ACTION; | 117 | cap_info->index = NO_FURTHER_WRITE_ACTION; |
128 | pr_info("%s: Successfully upload capsule file with reboot type '%s'\n", | 118 | pr_info("Successfully upload capsule file with reboot type '%s'\n", |
129 | __func__, !cap_info->reset_type ? "RESET_COLD" : | 119 | !cap_info->reset_type ? "RESET_COLD" : |
130 | cap_info->reset_type == 1 ? "RESET_WARM" : | 120 | cap_info->reset_type == 1 ? "RESET_WARM" : |
131 | "RESET_SHUTDOWN"); | 121 | "RESET_SHUTDOWN"); |
132 | return 0; | 122 | return 0; |
@@ -171,37 +161,30 @@ static ssize_t efi_capsule_write(struct file *file, const char __user *buff, | |||
171 | if (!cap_info->page_bytes_remain) { | 161 | if (!cap_info->page_bytes_remain) { |
172 | page = alloc_page(GFP_KERNEL); | 162 | page = alloc_page(GFP_KERNEL); |
173 | if (!page) { | 163 | if (!page) { |
174 | pr_debug("%s: alloc_page() failed\n", __func__); | ||
175 | ret = -ENOMEM; | 164 | ret = -ENOMEM; |
176 | goto failed; | 165 | goto failed; |
177 | } | 166 | } |
178 | 167 | ||
179 | cap_info->pages[cap_info->index++] = page; | 168 | cap_info->pages[cap_info->index++] = page_to_phys(page); |
180 | cap_info->page_bytes_remain = PAGE_SIZE; | 169 | cap_info->page_bytes_remain = PAGE_SIZE; |
170 | } else { | ||
171 | page = phys_to_page(cap_info->pages[cap_info->index - 1]); | ||
181 | } | 172 | } |
182 | 173 | ||
183 | page = cap_info->pages[cap_info->index - 1]; | ||
184 | |||
185 | kbuff = kmap(page); | 174 | kbuff = kmap(page); |
186 | if (!kbuff) { | ||
187 | pr_debug("%s: kmap() failed\n", __func__); | ||
188 | ret = -EFAULT; | ||
189 | goto failed; | ||
190 | } | ||
191 | kbuff += PAGE_SIZE - cap_info->page_bytes_remain; | 175 | kbuff += PAGE_SIZE - cap_info->page_bytes_remain; |
192 | 176 | ||
193 | /* Copy capsule binary data from user space to kernel space buffer */ | 177 | /* Copy capsule binary data from user space to kernel space buffer */ |
194 | write_byte = min_t(size_t, count, cap_info->page_bytes_remain); | 178 | write_byte = min_t(size_t, count, cap_info->page_bytes_remain); |
195 | if (copy_from_user(kbuff, buff, write_byte)) { | 179 | if (copy_from_user(kbuff, buff, write_byte)) { |
196 | pr_debug("%s: copy_from_user() failed\n", __func__); | ||
197 | ret = -EFAULT; | 180 | ret = -EFAULT; |
198 | goto fail_unmap; | 181 | goto fail_unmap; |
199 | } | 182 | } |
200 | cap_info->page_bytes_remain -= write_byte; | 183 | cap_info->page_bytes_remain -= write_byte; |
201 | 184 | ||
202 | /* Setup capsule binary info structure */ | 185 | /* Setup capsule binary info structure */ |
203 | if (!cap_info->header_obtained) { | 186 | if (cap_info->header.headersize == 0) { |
204 | ret = efi_capsule_setup_info(cap_info, kbuff, | 187 | ret = efi_capsule_setup_info(cap_info, kbuff - cap_info->count, |
205 | cap_info->count + write_byte); | 188 | cap_info->count + write_byte); |
206 | if (ret) | 189 | if (ret) |
207 | goto fail_unmap; | 190 | goto fail_unmap; |
@@ -211,11 +194,10 @@ static ssize_t efi_capsule_write(struct file *file, const char __user *buff, | |||
211 | kunmap(page); | 194 | kunmap(page); |
212 | 195 | ||
213 | /* Submit the full binary to efi_capsule_update() API */ | 196 | /* Submit the full binary to efi_capsule_update() API */ |
214 | if (cap_info->header_obtained && | 197 | if (cap_info->header.headersize > 0 && |
215 | cap_info->count >= cap_info->total_size) { | 198 | cap_info->count >= cap_info->total_size) { |
216 | if (cap_info->count > cap_info->total_size) { | 199 | if (cap_info->count > cap_info->total_size) { |
217 | pr_err("%s: upload size exceeded header defined size\n", | 200 | pr_err("capsule upload size exceeded header defined size\n"); |
218 | __func__); | ||
219 | ret = -EINVAL; | 201 | ret = -EINVAL; |
220 | goto failed; | 202 | goto failed; |
221 | } | 203 | } |
@@ -249,7 +231,7 @@ static int efi_capsule_flush(struct file *file, fl_owner_t id) | |||
249 | struct capsule_info *cap_info = file->private_data; | 231 | struct capsule_info *cap_info = file->private_data; |
250 | 232 | ||
251 | if (cap_info->index > 0) { | 233 | if (cap_info->index > 0) { |
252 | pr_err("%s: capsule upload not complete\n", __func__); | 234 | pr_err("capsule upload not complete\n"); |
253 | efi_free_all_buff_pages(cap_info); | 235 | efi_free_all_buff_pages(cap_info); |
254 | ret = -ECANCELED; | 236 | ret = -ECANCELED; |
255 | } | 237 | } |
@@ -328,8 +310,7 @@ static int __init efi_capsule_loader_init(void) | |||
328 | 310 | ||
329 | ret = misc_register(&efi_capsule_misc); | 311 | ret = misc_register(&efi_capsule_misc); |
330 | if (ret) | 312 | if (ret) |
331 | pr_err("%s: Failed to register misc char file note\n", | 313 | pr_err("Unable to register capsule loader device\n"); |
332 | __func__); | ||
333 | 314 | ||
334 | return ret; | 315 | return ret; |
335 | } | 316 | } |
diff --git a/drivers/firmware/efi/capsule.c b/drivers/firmware/efi/capsule.c index 6eedff45e6d7..901b9306bf94 100644 --- a/drivers/firmware/efi/capsule.c +++ b/drivers/firmware/efi/capsule.c | |||
@@ -214,7 +214,7 @@ efi_capsule_update_locked(efi_capsule_header_t *capsule, | |||
214 | * | 214 | * |
215 | * Return 0 on success, a converted EFI status code on failure. | 215 | * Return 0 on success, a converted EFI status code on failure. |
216 | */ | 216 | */ |
217 | int efi_capsule_update(efi_capsule_header_t *capsule, struct page **pages) | 217 | int efi_capsule_update(efi_capsule_header_t *capsule, phys_addr_t *pages) |
218 | { | 218 | { |
219 | u32 imagesize = capsule->imagesize; | 219 | u32 imagesize = capsule->imagesize; |
220 | efi_guid_t guid = capsule->guid; | 220 | efi_guid_t guid = capsule->guid; |
@@ -247,16 +247,13 @@ int efi_capsule_update(efi_capsule_header_t *capsule, struct page **pages) | |||
247 | efi_capsule_block_desc_t *sglist; | 247 | efi_capsule_block_desc_t *sglist; |
248 | 248 | ||
249 | sglist = kmap(sg_pages[i]); | 249 | sglist = kmap(sg_pages[i]); |
250 | if (!sglist) { | ||
251 | rv = -ENOMEM; | ||
252 | goto out; | ||
253 | } | ||
254 | 250 | ||
255 | for (j = 0; j < SGLIST_PER_PAGE && count > 0; j++) { | 251 | for (j = 0; j < SGLIST_PER_PAGE && count > 0; j++) { |
256 | u64 sz = min_t(u64, imagesize, PAGE_SIZE); | 252 | u64 sz = min_t(u64, imagesize, |
253 | PAGE_SIZE - (u64)*pages % PAGE_SIZE); | ||
257 | 254 | ||
258 | sglist[j].length = sz; | 255 | sglist[j].length = sz; |
259 | sglist[j].data = page_to_phys(*pages++); | 256 | sglist[j].data = *pages++; |
260 | 257 | ||
261 | imagesize -= sz; | 258 | imagesize -= sz; |
262 | count--; | 259 | count--; |
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index b372aad3b449..045d6d311bde 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c | |||
@@ -528,7 +528,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz, | |||
528 | } | 528 | } |
529 | } | 529 | } |
530 | 530 | ||
531 | efi_memattr_init(); | 531 | if (efi_enabled(EFI_MEMMAP)) |
532 | efi_memattr_init(); | ||
532 | 533 | ||
533 | /* Parse the EFI Properties table if it exists */ | 534 | /* Parse the EFI Properties table if it exists */ |
534 | if (efi.properties_table != EFI_INVALID_TABLE_ADDR) { | 535 | if (efi.properties_table != EFI_INVALID_TABLE_ADDR) { |
diff --git a/drivers/firmware/efi/test/efi_test.c b/drivers/firmware/efi/test/efi_test.c index 8cd578f62059..08129b7b80ab 100644 --- a/drivers/firmware/efi/test/efi_test.c +++ b/drivers/firmware/efi/test/efi_test.c | |||
@@ -71,18 +71,13 @@ copy_ucs2_from_user_len(efi_char16_t **dst, efi_char16_t __user *src, | |||
71 | if (!access_ok(VERIFY_READ, src, 1)) | 71 | if (!access_ok(VERIFY_READ, src, 1)) |
72 | return -EFAULT; | 72 | return -EFAULT; |
73 | 73 | ||
74 | buf = kmalloc(len, GFP_KERNEL); | 74 | buf = memdup_user(src, len); |
75 | if (!buf) { | 75 | if (IS_ERR(buf)) { |
76 | *dst = NULL; | 76 | *dst = NULL; |
77 | return -ENOMEM; | 77 | return PTR_ERR(buf); |
78 | } | 78 | } |
79 | *dst = buf; | 79 | *dst = buf; |
80 | 80 | ||
81 | if (copy_from_user(*dst, src, len)) { | ||
82 | kfree(buf); | ||
83 | return -EFAULT; | ||
84 | } | ||
85 | |||
86 | return 0; | 81 | return 0; |
87 | } | 82 | } |
88 | 83 | ||
diff --git a/include/linux/efi.h b/include/linux/efi.h index ec36f42a2add..8269bcb8ccf7 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
@@ -137,6 +137,18 @@ struct efi_boot_memmap { | |||
137 | #define EFI_CAPSULE_POPULATE_SYSTEM_TABLE 0x00020000 | 137 | #define EFI_CAPSULE_POPULATE_SYSTEM_TABLE 0x00020000 |
138 | #define EFI_CAPSULE_INITIATE_RESET 0x00040000 | 138 | #define EFI_CAPSULE_INITIATE_RESET 0x00040000 |
139 | 139 | ||
140 | struct capsule_info { | ||
141 | efi_capsule_header_t header; | ||
142 | int reset_type; | ||
143 | long index; | ||
144 | size_t count; | ||
145 | size_t total_size; | ||
146 | phys_addr_t *pages; | ||
147 | size_t page_bytes_remain; | ||
148 | }; | ||
149 | |||
150 | int __efi_capsule_setup_info(struct capsule_info *cap_info); | ||
151 | |||
140 | /* | 152 | /* |
141 | * Allocation types for calls to boottime->allocate_pages. | 153 | * Allocation types for calls to boottime->allocate_pages. |
142 | */ | 154 | */ |
@@ -1403,7 +1415,7 @@ extern int efi_capsule_supported(efi_guid_t guid, u32 flags, | |||
1403 | size_t size, int *reset); | 1415 | size_t size, int *reset); |
1404 | 1416 | ||
1405 | extern int efi_capsule_update(efi_capsule_header_t *capsule, | 1417 | extern int efi_capsule_update(efi_capsule_header_t *capsule, |
1406 | struct page **pages); | 1418 | phys_addr_t *pages); |
1407 | 1419 | ||
1408 | #ifdef CONFIG_EFI_RUNTIME_MAP | 1420 | #ifdef CONFIG_EFI_RUNTIME_MAP |
1409 | int efi_runtime_map_init(struct kobject *); | 1421 | int efi_runtime_map_init(struct kobject *); |