diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-20 14:47:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-20 14:47:11 -0500 |
commit | 32e2d7c8afb35d59fbf7d96619538427568ecb68 (patch) | |
tree | 966713f2a72ca241d4285210cd8bd8034bbaebac | |
parent | f7458a5d631df2ecdbfe4a606053aba19913cc41 (diff) | |
parent | b3879a4d3a31ef14265a52e8d941cf4b0f6627ae (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:
- Changes to the EFI init code to establish whether secure boot
authentication was performed at boot time. (Josh Boyer, David
Howells)
- Wire up the UEFI memory attributes table for x86. This eliminates
any runtime memory regions that are both writable and executable,
on recent firmware versions. (Sai Praneeth)
- Move the BGRT init code to an earlier stage so that we can still
use efi_mem_reserve(). (Dave Young)
- Preserve debug symbols in the ARM/arm64 UEFI stub (Ard Biesheuvel)
- Code deduplication work and various other cleanups (Lukas Wunner)
- ... plus various other fixes and cleanups"
* 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
efi/libstub: Make file I/O chunking x86-specific
efi: Print the secure boot status in x86 setup_arch()
efi: Disable secure boot if shim is in insecure mode
efi: Get and store the secure boot status
efi: Add SHIM and image security database GUID definitions
arm/efi: Allow invocation of arbitrary runtime services
x86/efi: Allow invocation of arbitrary runtime services
efi/libstub: Preserve .debug sections after absolute relocation check
efi/x86: Add debug code to print cooked memmap
efi/x86: Move the EFI BGRT init code to early init code
efi: Use typed function pointers for the runtime services table
efi/esrt: Fix typo in pr_err() message
x86/efi: Add support for EFI_MEMORY_ATTRIBUTES_TABLE
efi: Introduce the EFI_MEM_ATTR bit and set it from the memory attributes table
efi: Make EFI_MEMORY_ATTRIBUTES_TABLE initialization common across all architectures
x86/efi: Deduplicate efi_char16_printk()
efi: Deduplicate efi_file_size() / _read() / _close()
27 files changed, 383 insertions, 413 deletions
diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt index 95a4d34af3fd..b8527c6b7646 100644 --- a/Documentation/x86/zero-page.txt +++ b/Documentation/x86/zero-page.txt | |||
@@ -31,6 +31,8 @@ Offset Proto Name Meaning | |||
31 | 1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below) | 31 | 1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below) |
32 | 1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer | 32 | 1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer |
33 | (below) | 33 | (below) |
34 | 1EB/001 ALL kbd_status Numlock is enabled | ||
35 | 1EC/001 ALL secure_boot Secure boot is enabled in the firmware | ||
34 | 1EF/001 ALL sentinel Used to detect broken bootloaders | 36 | 1EF/001 ALL sentinel Used to detect broken bootloaders |
35 | 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures | 37 | 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures |
36 | 2D0/A00 ALL e820_map E820 memory map table | 38 | 2D0/A00 ALL e820_map E820 memory map table |
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index 0b06f5341b45..e4e6a9d6a825 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h | |||
@@ -55,6 +55,7 @@ void efi_virtmap_unload(void); | |||
55 | 55 | ||
56 | #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) | 56 | #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) |
57 | #define __efi_call_early(f, ...) f(__VA_ARGS__) | 57 | #define __efi_call_early(f, ...) f(__VA_ARGS__) |
58 | #define efi_call_runtime(f, ...) sys_table_arg->runtime->f(__VA_ARGS__) | ||
58 | #define efi_is_64bit() (false) | 59 | #define efi_is_64bit() (false) |
59 | 60 | ||
60 | #define efi_call_proto(protocol, f, instance, ...) \ | 61 | #define efi_call_proto(protocol, f, instance, ...) \ |
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 0b6b1633017f..e7445281e534 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h | |||
@@ -50,6 +50,7 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); | |||
50 | 50 | ||
51 | #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) | 51 | #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) |
52 | #define __efi_call_early(f, ...) f(__VA_ARGS__) | 52 | #define __efi_call_early(f, ...) f(__VA_ARGS__) |
53 | #define efi_call_runtime(f, ...) sys_table_arg->runtime->f(__VA_ARGS__) | ||
53 | #define efi_is_64bit() (true) | 54 | #define efi_is_64bit() (true) |
54 | 55 | ||
55 | #define efi_call_proto(protocol, f, instance, ...) \ | 56 | #define efi_call_proto(protocol, f, instance, ...) \ |
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index ff01c8fc76f7..801c7a158e55 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c | |||
@@ -32,160 +32,13 @@ static void setup_boot_services##bits(struct efi_config *c) \ | |||
32 | \ | 32 | \ |
33 | table = (typeof(table))sys_table; \ | 33 | table = (typeof(table))sys_table; \ |
34 | \ | 34 | \ |
35 | c->runtime_services = table->runtime; \ | ||
35 | c->boot_services = table->boottime; \ | 36 | c->boot_services = table->boottime; \ |
36 | c->text_output = table->con_out; \ | 37 | c->text_output = table->con_out; \ |
37 | } | 38 | } |
38 | BOOT_SERVICES(32); | 39 | BOOT_SERVICES(32); |
39 | BOOT_SERVICES(64); | 40 | BOOT_SERVICES(64); |
40 | 41 | ||
41 | void efi_char16_printk(efi_system_table_t *, efi_char16_t *); | ||
42 | |||
43 | static efi_status_t | ||
44 | __file_size32(void *__fh, efi_char16_t *filename_16, | ||
45 | void **handle, u64 *file_sz) | ||
46 | { | ||
47 | efi_file_handle_32_t *h, *fh = __fh; | ||
48 | efi_file_info_t *info; | ||
49 | efi_status_t status; | ||
50 | efi_guid_t info_guid = EFI_FILE_INFO_ID; | ||
51 | u32 info_sz; | ||
52 | |||
53 | status = efi_early->call((unsigned long)fh->open, fh, &h, filename_16, | ||
54 | EFI_FILE_MODE_READ, (u64)0); | ||
55 | if (status != EFI_SUCCESS) { | ||
56 | efi_printk(sys_table, "Failed to open file: "); | ||
57 | efi_char16_printk(sys_table, filename_16); | ||
58 | efi_printk(sys_table, "\n"); | ||
59 | return status; | ||
60 | } | ||
61 | |||
62 | *handle = h; | ||
63 | |||
64 | info_sz = 0; | ||
65 | status = efi_early->call((unsigned long)h->get_info, h, &info_guid, | ||
66 | &info_sz, NULL); | ||
67 | if (status != EFI_BUFFER_TOO_SMALL) { | ||
68 | efi_printk(sys_table, "Failed to get file info size\n"); | ||
69 | return status; | ||
70 | } | ||
71 | |||
72 | grow: | ||
73 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, | ||
74 | info_sz, (void **)&info); | ||
75 | if (status != EFI_SUCCESS) { | ||
76 | efi_printk(sys_table, "Failed to alloc mem for file info\n"); | ||
77 | return status; | ||
78 | } | ||
79 | |||
80 | status = efi_early->call((unsigned long)h->get_info, h, &info_guid, | ||
81 | &info_sz, info); | ||
82 | if (status == EFI_BUFFER_TOO_SMALL) { | ||
83 | efi_call_early(free_pool, info); | ||
84 | goto grow; | ||
85 | } | ||
86 | |||
87 | *file_sz = info->file_size; | ||
88 | efi_call_early(free_pool, info); | ||
89 | |||
90 | if (status != EFI_SUCCESS) | ||
91 | efi_printk(sys_table, "Failed to get initrd info\n"); | ||
92 | |||
93 | return status; | ||
94 | } | ||
95 | |||
96 | static efi_status_t | ||
97 | __file_size64(void *__fh, efi_char16_t *filename_16, | ||
98 | void **handle, u64 *file_sz) | ||
99 | { | ||
100 | efi_file_handle_64_t *h, *fh = __fh; | ||
101 | efi_file_info_t *info; | ||
102 | efi_status_t status; | ||
103 | efi_guid_t info_guid = EFI_FILE_INFO_ID; | ||
104 | u64 info_sz; | ||
105 | |||
106 | status = efi_early->call((unsigned long)fh->open, fh, &h, filename_16, | ||
107 | EFI_FILE_MODE_READ, (u64)0); | ||
108 | if (status != EFI_SUCCESS) { | ||
109 | efi_printk(sys_table, "Failed to open file: "); | ||
110 | efi_char16_printk(sys_table, filename_16); | ||
111 | efi_printk(sys_table, "\n"); | ||
112 | return status; | ||
113 | } | ||
114 | |||
115 | *handle = h; | ||
116 | |||
117 | info_sz = 0; | ||
118 | status = efi_early->call((unsigned long)h->get_info, h, &info_guid, | ||
119 | &info_sz, NULL); | ||
120 | if (status != EFI_BUFFER_TOO_SMALL) { | ||
121 | efi_printk(sys_table, "Failed to get file info size\n"); | ||
122 | return status; | ||
123 | } | ||
124 | |||
125 | grow: | ||
126 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, | ||
127 | info_sz, (void **)&info); | ||
128 | if (status != EFI_SUCCESS) { | ||
129 | efi_printk(sys_table, "Failed to alloc mem for file info\n"); | ||
130 | return status; | ||
131 | } | ||
132 | |||
133 | status = efi_early->call((unsigned long)h->get_info, h, &info_guid, | ||
134 | &info_sz, info); | ||
135 | if (status == EFI_BUFFER_TOO_SMALL) { | ||
136 | efi_call_early(free_pool, info); | ||
137 | goto grow; | ||
138 | } | ||
139 | |||
140 | *file_sz = info->file_size; | ||
141 | efi_call_early(free_pool, info); | ||
142 | |||
143 | if (status != EFI_SUCCESS) | ||
144 | efi_printk(sys_table, "Failed to get initrd info\n"); | ||
145 | |||
146 | return status; | ||
147 | } | ||
148 | efi_status_t | ||
149 | efi_file_size(efi_system_table_t *sys_table, void *__fh, | ||
150 | efi_char16_t *filename_16, void **handle, u64 *file_sz) | ||
151 | { | ||
152 | if (efi_early->is64) | ||
153 | return __file_size64(__fh, filename_16, handle, file_sz); | ||
154 | |||
155 | return __file_size32(__fh, filename_16, handle, file_sz); | ||
156 | } | ||
157 | |||
158 | efi_status_t | ||
159 | efi_file_read(void *handle, unsigned long *size, void *addr) | ||
160 | { | ||
161 | unsigned long func; | ||
162 | |||
163 | if (efi_early->is64) { | ||
164 | efi_file_handle_64_t *fh = handle; | ||
165 | |||
166 | func = (unsigned long)fh->read; | ||
167 | return efi_early->call(func, handle, size, addr); | ||
168 | } else { | ||
169 | efi_file_handle_32_t *fh = handle; | ||
170 | |||
171 | func = (unsigned long)fh->read; | ||
172 | return efi_early->call(func, handle, size, addr); | ||
173 | } | ||
174 | } | ||
175 | |||
176 | efi_status_t efi_file_close(void *handle) | ||
177 | { | ||
178 | if (efi_early->is64) { | ||
179 | efi_file_handle_64_t *fh = handle; | ||
180 | |||
181 | return efi_early->call((unsigned long)fh->close, handle); | ||
182 | } else { | ||
183 | efi_file_handle_32_t *fh = handle; | ||
184 | |||
185 | return efi_early->call((unsigned long)fh->close, handle); | ||
186 | } | ||
187 | } | ||
188 | |||
189 | static inline efi_status_t __open_volume32(void *__image, void **__fh) | 42 | static inline efi_status_t __open_volume32(void *__image, void **__fh) |
190 | { | 43 | { |
191 | efi_file_io_interface_t *io; | 44 | efi_file_io_interface_t *io; |
@@ -249,30 +102,8 @@ efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh) | |||
249 | 102 | ||
250 | void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str) | 103 | void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str) |
251 | { | 104 | { |
252 | unsigned long output_string; | 105 | efi_call_proto(efi_simple_text_output_protocol, output_string, |
253 | size_t offset; | 106 | efi_early->text_output, str); |
254 | |||
255 | if (efi_early->is64) { | ||
256 | struct efi_simple_text_output_protocol_64 *out; | ||
257 | u64 *func; | ||
258 | |||
259 | offset = offsetof(typeof(*out), output_string); | ||
260 | output_string = efi_early->text_output + offset; | ||
261 | out = (typeof(out))(unsigned long)efi_early->text_output; | ||
262 | func = (u64 *)output_string; | ||
263 | |||
264 | efi_early->call(*func, out, str); | ||
265 | } else { | ||
266 | struct efi_simple_text_output_protocol_32 *out; | ||
267 | u32 *func; | ||
268 | |||
269 | offset = offsetof(typeof(*out), output_string); | ||
270 | output_string = efi_early->text_output + offset; | ||
271 | out = (typeof(out))(unsigned long)efi_early->text_output; | ||
272 | func = (u32 *)output_string; | ||
273 | |||
274 | efi_early->call(*func, out, str); | ||
275 | } | ||
276 | } | 107 | } |
277 | 108 | ||
278 | static efi_status_t | 109 | static efi_status_t |
@@ -1157,6 +988,13 @@ struct boot_params *efi_main(struct efi_config *c, | |||
1157 | else | 988 | else |
1158 | setup_boot_services32(efi_early); | 989 | setup_boot_services32(efi_early); |
1159 | 990 | ||
991 | /* | ||
992 | * If the boot loader gave us a value for secure_boot then we use that, | ||
993 | * otherwise we ask the BIOS. | ||
994 | */ | ||
995 | if (boot_params->secure_boot == efi_secureboot_mode_unset) | ||
996 | boot_params->secure_boot = efi_get_secureboot(sys_table); | ||
997 | |||
1160 | setup_graphics(boot_params); | 998 | setup_graphics(boot_params); |
1161 | 999 | ||
1162 | setup_efi_pci(boot_params); | 1000 | setup_efi_pci(boot_params); |
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index fd0b6a272dd5..d85b9625e836 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S | |||
@@ -82,7 +82,7 @@ ENTRY(efi_pe_entry) | |||
82 | 82 | ||
83 | /* Relocate efi_config->call() */ | 83 | /* Relocate efi_config->call() */ |
84 | leal efi32_config(%esi), %eax | 84 | leal efi32_config(%esi), %eax |
85 | add %esi, 32(%eax) | 85 | add %esi, 40(%eax) |
86 | pushl %eax | 86 | pushl %eax |
87 | 87 | ||
88 | call make_boot_params | 88 | call make_boot_params |
@@ -108,7 +108,7 @@ ENTRY(efi32_stub_entry) | |||
108 | 108 | ||
109 | /* Relocate efi_config->call() */ | 109 | /* Relocate efi_config->call() */ |
110 | leal efi32_config(%esi), %eax | 110 | leal efi32_config(%esi), %eax |
111 | add %esi, 32(%eax) | 111 | add %esi, 40(%eax) |
112 | pushl %eax | 112 | pushl %eax |
113 | 2: | 113 | 2: |
114 | call efi_main | 114 | call efi_main |
@@ -264,7 +264,7 @@ relocated: | |||
264 | #ifdef CONFIG_EFI_STUB | 264 | #ifdef CONFIG_EFI_STUB |
265 | .data | 265 | .data |
266 | efi32_config: | 266 | efi32_config: |
267 | .fill 4,8,0 | 267 | .fill 5,8,0 |
268 | .long efi_call_phys | 268 | .long efi_call_phys |
269 | .long 0 | 269 | .long 0 |
270 | .byte 0 | 270 | .byte 0 |
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index 4d85e600db78..d2ae1f821e0c 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S | |||
@@ -264,7 +264,7 @@ ENTRY(efi_pe_entry) | |||
264 | /* | 264 | /* |
265 | * Relocate efi_config->call(). | 265 | * Relocate efi_config->call(). |
266 | */ | 266 | */ |
267 | addq %rbp, efi64_config+32(%rip) | 267 | addq %rbp, efi64_config+40(%rip) |
268 | 268 | ||
269 | movq %rax, %rdi | 269 | movq %rax, %rdi |
270 | call make_boot_params | 270 | call make_boot_params |
@@ -284,7 +284,7 @@ handover_entry: | |||
284 | * Relocate efi_config->call(). | 284 | * Relocate efi_config->call(). |
285 | */ | 285 | */ |
286 | movq efi_config(%rip), %rax | 286 | movq efi_config(%rip), %rax |
287 | addq %rbp, 32(%rax) | 287 | addq %rbp, 40(%rax) |
288 | 2: | 288 | 2: |
289 | movq efi_config(%rip), %rdi | 289 | movq efi_config(%rip), %rdi |
290 | call efi_main | 290 | call efi_main |
@@ -456,14 +456,14 @@ efi_config: | |||
456 | #ifdef CONFIG_EFI_MIXED | 456 | #ifdef CONFIG_EFI_MIXED |
457 | .global efi32_config | 457 | .global efi32_config |
458 | efi32_config: | 458 | efi32_config: |
459 | .fill 4,8,0 | 459 | .fill 5,8,0 |
460 | .quad efi64_thunk | 460 | .quad efi64_thunk |
461 | .byte 0 | 461 | .byte 0 |
462 | #endif | 462 | #endif |
463 | 463 | ||
464 | .global efi64_config | 464 | .global efi64_config |
465 | efi64_config: | 465 | efi64_config: |
466 | .fill 4,8,0 | 466 | .fill 5,8,0 |
467 | .quad efi_call | 467 | .quad efi_call |
468 | .byte 1 | 468 | .byte 1 |
469 | #endif /* CONFIG_EFI_STUB */ | 469 | #endif /* CONFIG_EFI_STUB */ |
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index e99675b9c861..2f77bcefe6b4 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h | |||
@@ -191,6 +191,7 @@ static inline efi_status_t efi_thunk_set_virtual_address_map( | |||
191 | struct efi_config { | 191 | struct efi_config { |
192 | u64 image_handle; | 192 | u64 image_handle; |
193 | u64 table; | 193 | u64 table; |
194 | u64 runtime_services; | ||
194 | u64 boot_services; | 195 | u64 boot_services; |
195 | u64 text_output; | 196 | u64 text_output; |
196 | efi_status_t (*call)(unsigned long, ...); | 197 | efi_status_t (*call)(unsigned long, ...); |
@@ -226,6 +227,10 @@ static inline bool efi_is_64bit(void) | |||
226 | #define __efi_call_early(f, ...) \ | 227 | #define __efi_call_early(f, ...) \ |
227 | __efi_early()->call((unsigned long)f, __VA_ARGS__); | 228 | __efi_early()->call((unsigned long)f, __VA_ARGS__); |
228 | 229 | ||
230 | #define efi_call_runtime(f, ...) \ | ||
231 | __efi_early()->call(efi_table_attr(efi_runtime_services, f, \ | ||
232 | __efi_early()->runtime_services), __VA_ARGS__) | ||
233 | |||
229 | extern bool efi_reboot_required(void); | 234 | extern bool efi_reboot_required(void); |
230 | 235 | ||
231 | #else | 236 | #else |
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h index b10bf319ed20..5138dacf8bb8 100644 --- a/arch/x86/include/uapi/asm/bootparam.h +++ b/arch/x86/include/uapi/asm/bootparam.h | |||
@@ -135,7 +135,8 @@ struct boot_params { | |||
135 | __u8 eddbuf_entries; /* 0x1e9 */ | 135 | __u8 eddbuf_entries; /* 0x1e9 */ |
136 | __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ | 136 | __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ |
137 | __u8 kbd_status; /* 0x1eb */ | 137 | __u8 kbd_status; /* 0x1eb */ |
138 | __u8 _pad5[3]; /* 0x1ec */ | 138 | __u8 secure_boot; /* 0x1ec */ |
139 | __u8 _pad5[2]; /* 0x1ed */ | ||
139 | /* | 140 | /* |
140 | * The sentinel is set to a nonzero value (0xff) in header.S. | 141 | * The sentinel is set to a nonzero value (0xff) in header.S. |
141 | * | 142 | * |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 64422f850e95..7ff007ed899d 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/bootmem.h> | 35 | #include <linux/bootmem.h> |
36 | #include <linux/ioport.h> | 36 | #include <linux/ioport.h> |
37 | #include <linux/pci.h> | 37 | #include <linux/pci.h> |
38 | #include <linux/efi-bgrt.h> | ||
38 | 39 | ||
39 | #include <asm/irqdomain.h> | 40 | #include <asm/irqdomain.h> |
40 | #include <asm/pci_x86.h> | 41 | #include <asm/pci_x86.h> |
@@ -1557,6 +1558,12 @@ int __init early_acpi_boot_init(void) | |||
1557 | return 0; | 1558 | return 0; |
1558 | } | 1559 | } |
1559 | 1560 | ||
1561 | static int __init acpi_parse_bgrt(struct acpi_table_header *table) | ||
1562 | { | ||
1563 | efi_bgrt_init(table); | ||
1564 | return 0; | ||
1565 | } | ||
1566 | |||
1560 | int __init acpi_boot_init(void) | 1567 | int __init acpi_boot_init(void) |
1561 | { | 1568 | { |
1562 | /* those are executed after early-quirks are executed */ | 1569 | /* those are executed after early-quirks are executed */ |
@@ -1581,6 +1588,8 @@ int __init acpi_boot_init(void) | |||
1581 | acpi_process_madt(); | 1588 | acpi_process_madt(); |
1582 | 1589 | ||
1583 | acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet); | 1590 | acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet); |
1591 | if (IS_ENABLED(CONFIG_ACPI_BGRT)) | ||
1592 | acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); | ||
1584 | 1593 | ||
1585 | if (!acpi_noirq) | 1594 | if (!acpi_noirq) |
1586 | x86_init.pci.init = pci_acpi_init; | 1595 | x86_init.pci.init = pci_acpi_init; |
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c index c62e015b126c..de827d6ac8c2 100644 --- a/arch/x86/kernel/asm-offsets.c +++ b/arch/x86/kernel/asm-offsets.c | |||
@@ -81,6 +81,7 @@ void common(void) { | |||
81 | 81 | ||
82 | BLANK(); | 82 | BLANK(); |
83 | OFFSET(BP_scratch, boot_params, scratch); | 83 | OFFSET(BP_scratch, boot_params, scratch); |
84 | OFFSET(BP_secure_boot, boot_params, secure_boot); | ||
84 | OFFSET(BP_loadflags, boot_params, hdr.loadflags); | 85 | OFFSET(BP_loadflags, boot_params, hdr.loadflags); |
85 | OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch); | 86 | OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch); |
86 | OFFSET(BP_version, boot_params, hdr.version); | 87 | OFFSET(BP_version, boot_params, hdr.version); |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 4cfba947d774..69780edf0dde 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -1176,6 +1176,20 @@ void __init setup_arch(char **cmdline_p) | |||
1176 | /* Allocate bigger log buffer */ | 1176 | /* Allocate bigger log buffer */ |
1177 | setup_log_buf(1); | 1177 | setup_log_buf(1); |
1178 | 1178 | ||
1179 | if (efi_enabled(EFI_BOOT)) { | ||
1180 | switch (boot_params.secure_boot) { | ||
1181 | case efi_secureboot_mode_disabled: | ||
1182 | pr_info("Secure boot disabled\n"); | ||
1183 | break; | ||
1184 | case efi_secureboot_mode_enabled: | ||
1185 | pr_info("Secure boot enabled\n"); | ||
1186 | break; | ||
1187 | default: | ||
1188 | pr_info("Secure boot could not be determined\n"); | ||
1189 | break; | ||
1190 | } | ||
1191 | } | ||
1192 | |||
1179 | reserve_initrd(); | 1193 | reserve_initrd(); |
1180 | 1194 | ||
1181 | acpi_table_upgrade(); | 1195 | acpi_table_upgrade(); |
diff --git a/arch/x86/platform/efi/efi-bgrt.c b/arch/x86/platform/efi/efi-bgrt.c index 6aad870e8962..04ca8764f0c0 100644 --- a/arch/x86/platform/efi/efi-bgrt.c +++ b/arch/x86/platform/efi/efi-bgrt.c | |||
@@ -19,8 +19,7 @@ | |||
19 | #include <linux/efi.h> | 19 | #include <linux/efi.h> |
20 | #include <linux/efi-bgrt.h> | 20 | #include <linux/efi-bgrt.h> |
21 | 21 | ||
22 | struct acpi_table_bgrt *bgrt_tab; | 22 | struct acpi_table_bgrt bgrt_tab; |
23 | void *__initdata bgrt_image; | ||
24 | size_t __initdata bgrt_image_size; | 23 | size_t __initdata bgrt_image_size; |
25 | 24 | ||
26 | struct bmp_header { | 25 | struct bmp_header { |
@@ -28,66 +27,58 @@ struct bmp_header { | |||
28 | u32 size; | 27 | u32 size; |
29 | } __packed; | 28 | } __packed; |
30 | 29 | ||
31 | void __init efi_bgrt_init(void) | 30 | void __init efi_bgrt_init(struct acpi_table_header *table) |
32 | { | 31 | { |
33 | acpi_status status; | ||
34 | void *image; | 32 | void *image; |
35 | struct bmp_header bmp_header; | 33 | struct bmp_header bmp_header; |
34 | struct acpi_table_bgrt *bgrt = &bgrt_tab; | ||
36 | 35 | ||
37 | if (acpi_disabled) | 36 | if (acpi_disabled) |
38 | return; | 37 | return; |
39 | 38 | ||
40 | status = acpi_get_table("BGRT", 0, | 39 | if (table->length < sizeof(bgrt_tab)) { |
41 | (struct acpi_table_header **)&bgrt_tab); | ||
42 | if (ACPI_FAILURE(status)) | ||
43 | return; | ||
44 | |||
45 | if (bgrt_tab->header.length < sizeof(*bgrt_tab)) { | ||
46 | pr_notice("Ignoring BGRT: invalid length %u (expected %zu)\n", | 40 | pr_notice("Ignoring BGRT: invalid length %u (expected %zu)\n", |
47 | bgrt_tab->header.length, sizeof(*bgrt_tab)); | 41 | table->length, sizeof(bgrt_tab)); |
48 | return; | 42 | return; |
49 | } | 43 | } |
50 | if (bgrt_tab->version != 1) { | 44 | *bgrt = *(struct acpi_table_bgrt *)table; |
45 | if (bgrt->version != 1) { | ||
51 | pr_notice("Ignoring BGRT: invalid version %u (expected 1)\n", | 46 | pr_notice("Ignoring BGRT: invalid version %u (expected 1)\n", |
52 | bgrt_tab->version); | 47 | bgrt->version); |
53 | return; | 48 | goto out; |
54 | } | 49 | } |
55 | if (bgrt_tab->status & 0xfe) { | 50 | if (bgrt->status & 0xfe) { |
56 | pr_notice("Ignoring BGRT: reserved status bits are non-zero %u\n", | 51 | pr_notice("Ignoring BGRT: reserved status bits are non-zero %u\n", |
57 | bgrt_tab->status); | 52 | bgrt->status); |
58 | return; | 53 | goto out; |
59 | } | 54 | } |
60 | if (bgrt_tab->image_type != 0) { | 55 | if (bgrt->image_type != 0) { |
61 | pr_notice("Ignoring BGRT: invalid image type %u (expected 0)\n", | 56 | pr_notice("Ignoring BGRT: invalid image type %u (expected 0)\n", |
62 | bgrt_tab->image_type); | 57 | bgrt->image_type); |
63 | return; | 58 | goto out; |
64 | } | 59 | } |
65 | if (!bgrt_tab->image_address) { | 60 | if (!bgrt->image_address) { |
66 | pr_notice("Ignoring BGRT: null image address\n"); | 61 | pr_notice("Ignoring BGRT: null image address\n"); |
67 | return; | 62 | goto out; |
68 | } | 63 | } |
69 | 64 | ||
70 | image = memremap(bgrt_tab->image_address, sizeof(bmp_header), MEMREMAP_WB); | 65 | image = early_memremap(bgrt->image_address, sizeof(bmp_header)); |
71 | if (!image) { | 66 | if (!image) { |
72 | pr_notice("Ignoring BGRT: failed to map image header memory\n"); | 67 | pr_notice("Ignoring BGRT: failed to map image header memory\n"); |
73 | return; | 68 | goto out; |
74 | } | 69 | } |
75 | 70 | ||
76 | memcpy(&bmp_header, image, sizeof(bmp_header)); | 71 | memcpy(&bmp_header, image, sizeof(bmp_header)); |
77 | memunmap(image); | 72 | early_memunmap(image, sizeof(bmp_header)); |
78 | if (bmp_header.id != 0x4d42) { | 73 | if (bmp_header.id != 0x4d42) { |
79 | pr_notice("Ignoring BGRT: Incorrect BMP magic number 0x%x (expected 0x4d42)\n", | 74 | pr_notice("Ignoring BGRT: Incorrect BMP magic number 0x%x (expected 0x4d42)\n", |
80 | bmp_header.id); | 75 | bmp_header.id); |
81 | return; | 76 | goto out; |
82 | } | 77 | } |
83 | bgrt_image_size = bmp_header.size; | 78 | bgrt_image_size = bmp_header.size; |
79 | efi_mem_reserve(bgrt->image_address, bgrt_image_size); | ||
84 | 80 | ||
85 | bgrt_image = memremap(bgrt_tab->image_address, bmp_header.size, MEMREMAP_WB); | 81 | return; |
86 | if (!bgrt_image) { | 82 | out: |
87 | pr_notice("Ignoring BGRT: failed to map image memory\n"); | 83 | memset(bgrt, 0, sizeof(bgrt_tab)); |
88 | bgrt_image = NULL; | ||
89 | return; | ||
90 | } | ||
91 | |||
92 | efi_mem_reserve(bgrt_tab->image_address, bgrt_image_size); | ||
93 | } | 84 | } |
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 274dfc481849..565dff3c9a12 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
@@ -542,11 +542,6 @@ void __init efi_init(void) | |||
542 | efi_print_memmap(); | 542 | efi_print_memmap(); |
543 | } | 543 | } |
544 | 544 | ||
545 | void __init efi_late_init(void) | ||
546 | { | ||
547 | efi_bgrt_init(); | ||
548 | } | ||
549 | |||
550 | void __init efi_set_executable(efi_memory_desc_t *md, bool executable) | 545 | void __init efi_set_executable(efi_memory_desc_t *md, bool executable) |
551 | { | 546 | { |
552 | u64 addr, npages; | 547 | u64 addr, npages; |
@@ -960,6 +955,11 @@ static void __init __efi_enter_virtual_mode(void) | |||
960 | return; | 955 | return; |
961 | } | 956 | } |
962 | 957 | ||
958 | if (efi_enabled(EFI_DBG)) { | ||
959 | pr_info("EFI runtime memory map:\n"); | ||
960 | efi_print_memmap(); | ||
961 | } | ||
962 | |||
963 | BUG_ON(!efi.systab); | 963 | BUG_ON(!efi.systab); |
964 | 964 | ||
965 | if (efi_setup_page_tables(pa, 1 << pg_shift)) { | 965 | if (efi_setup_page_tables(pa, 1 << pg_shift)) { |
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 2f25a363068c..a4695da42d77 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c | |||
@@ -414,10 +414,44 @@ void __init parse_efi_setup(u64 phys_addr, u32 data_len) | |||
414 | efi_setup = phys_addr + sizeof(struct setup_data); | 414 | efi_setup = phys_addr + sizeof(struct setup_data); |
415 | } | 415 | } |
416 | 416 | ||
417 | void __init efi_runtime_update_mappings(void) | 417 | static int __init efi_update_mappings(efi_memory_desc_t *md, unsigned long pf) |
418 | { | 418 | { |
419 | unsigned long pfn; | 419 | unsigned long pfn; |
420 | pgd_t *pgd = efi_pgd; | 420 | pgd_t *pgd = efi_pgd; |
421 | int err1, err2; | ||
422 | |||
423 | /* Update the 1:1 mapping */ | ||
424 | pfn = md->phys_addr >> PAGE_SHIFT; | ||
425 | err1 = kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, md->num_pages, pf); | ||
426 | if (err1) { | ||
427 | pr_err("Error while updating 1:1 mapping PA 0x%llx -> VA 0x%llx!\n", | ||
428 | md->phys_addr, md->virt_addr); | ||
429 | } | ||
430 | |||
431 | err2 = kernel_map_pages_in_pgd(pgd, pfn, md->virt_addr, md->num_pages, pf); | ||
432 | if (err2) { | ||
433 | pr_err("Error while updating VA mapping PA 0x%llx -> VA 0x%llx!\n", | ||
434 | md->phys_addr, md->virt_addr); | ||
435 | } | ||
436 | |||
437 | return err1 || err2; | ||
438 | } | ||
439 | |||
440 | static int __init efi_update_mem_attr(struct mm_struct *mm, efi_memory_desc_t *md) | ||
441 | { | ||
442 | unsigned long pf = 0; | ||
443 | |||
444 | if (md->attribute & EFI_MEMORY_XP) | ||
445 | pf |= _PAGE_NX; | ||
446 | |||
447 | if (!(md->attribute & EFI_MEMORY_RO)) | ||
448 | pf |= _PAGE_RW; | ||
449 | |||
450 | return efi_update_mappings(md, pf); | ||
451 | } | ||
452 | |||
453 | void __init efi_runtime_update_mappings(void) | ||
454 | { | ||
421 | efi_memory_desc_t *md; | 455 | efi_memory_desc_t *md; |
422 | 456 | ||
423 | if (efi_enabled(EFI_OLD_MEMMAP)) { | 457 | if (efi_enabled(EFI_OLD_MEMMAP)) { |
@@ -426,6 +460,24 @@ void __init efi_runtime_update_mappings(void) | |||
426 | return; | 460 | return; |
427 | } | 461 | } |
428 | 462 | ||
463 | /* | ||
464 | * Use the EFI Memory Attribute Table for mapping permissions if it | ||
465 | * exists, since it is intended to supersede EFI_PROPERTIES_TABLE. | ||
466 | */ | ||
467 | if (efi_enabled(EFI_MEM_ATTR)) { | ||
468 | efi_memattr_apply_permissions(NULL, efi_update_mem_attr); | ||
469 | return; | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * EFI_MEMORY_ATTRIBUTES_TABLE is intended to replace | ||
474 | * EFI_PROPERTIES_TABLE. So, use EFI_PROPERTIES_TABLE to update | ||
475 | * permissions only if EFI_MEMORY_ATTRIBUTES_TABLE is not | ||
476 | * published by the firmware. Even if we find a buggy implementation of | ||
477 | * EFI_MEMORY_ATTRIBUTES_TABLE, don't fall back to | ||
478 | * EFI_PROPERTIES_TABLE, because of the same reason. | ||
479 | */ | ||
480 | |||
429 | if (!efi_enabled(EFI_NX_PE_DATA)) | 481 | if (!efi_enabled(EFI_NX_PE_DATA)) |
430 | return; | 482 | return; |
431 | 483 | ||
@@ -446,15 +498,7 @@ void __init efi_runtime_update_mappings(void) | |||
446 | (md->type != EFI_RUNTIME_SERVICES_CODE)) | 498 | (md->type != EFI_RUNTIME_SERVICES_CODE)) |
447 | pf |= _PAGE_RW; | 499 | pf |= _PAGE_RW; |
448 | 500 | ||
449 | /* Update the 1:1 mapping */ | 501 | efi_update_mappings(md, pf); |
450 | pfn = md->phys_addr >> PAGE_SHIFT; | ||
451 | if (kernel_map_pages_in_pgd(pgd, pfn, md->phys_addr, md->num_pages, pf)) | ||
452 | pr_warn("Error mapping PA 0x%llx -> VA 0x%llx!\n", | ||
453 | md->phys_addr, md->virt_addr); | ||
454 | |||
455 | if (kernel_map_pages_in_pgd(pgd, pfn, md->virt_addr, md->num_pages, pf)) | ||
456 | pr_warn("Error mapping PA 0x%llx -> VA 0x%llx!\n", | ||
457 | md->phys_addr, md->virt_addr); | ||
458 | } | 502 | } |
459 | } | 503 | } |
460 | 504 | ||
diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c index 75f128e766a9..ca28aa572aa9 100644 --- a/drivers/acpi/bgrt.c +++ b/drivers/acpi/bgrt.c | |||
@@ -15,40 +15,41 @@ | |||
15 | #include <linux/sysfs.h> | 15 | #include <linux/sysfs.h> |
16 | #include <linux/efi-bgrt.h> | 16 | #include <linux/efi-bgrt.h> |
17 | 17 | ||
18 | static void *bgrt_image; | ||
18 | static struct kobject *bgrt_kobj; | 19 | static struct kobject *bgrt_kobj; |
19 | 20 | ||
20 | static ssize_t show_version(struct device *dev, | 21 | static ssize_t show_version(struct device *dev, |
21 | struct device_attribute *attr, char *buf) | 22 | struct device_attribute *attr, char *buf) |
22 | { | 23 | { |
23 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->version); | 24 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.version); |
24 | } | 25 | } |
25 | static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); | 26 | static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); |
26 | 27 | ||
27 | static ssize_t show_status(struct device *dev, | 28 | static ssize_t show_status(struct device *dev, |
28 | struct device_attribute *attr, char *buf) | 29 | struct device_attribute *attr, char *buf) |
29 | { | 30 | { |
30 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->status); | 31 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.status); |
31 | } | 32 | } |
32 | static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); | 33 | static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); |
33 | 34 | ||
34 | static ssize_t show_type(struct device *dev, | 35 | static ssize_t show_type(struct device *dev, |
35 | struct device_attribute *attr, char *buf) | 36 | struct device_attribute *attr, char *buf) |
36 | { | 37 | { |
37 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_type); | 38 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_type); |
38 | } | 39 | } |
39 | static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); | 40 | static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); |
40 | 41 | ||
41 | static ssize_t show_xoffset(struct device *dev, | 42 | static ssize_t show_xoffset(struct device *dev, |
42 | struct device_attribute *attr, char *buf) | 43 | struct device_attribute *attr, char *buf) |
43 | { | 44 | { |
44 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_offset_x); | 45 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_offset_x); |
45 | } | 46 | } |
46 | static DEVICE_ATTR(xoffset, S_IRUGO, show_xoffset, NULL); | 47 | static DEVICE_ATTR(xoffset, S_IRUGO, show_xoffset, NULL); |
47 | 48 | ||
48 | static ssize_t show_yoffset(struct device *dev, | 49 | static ssize_t show_yoffset(struct device *dev, |
49 | struct device_attribute *attr, char *buf) | 50 | struct device_attribute *attr, char *buf) |
50 | { | 51 | { |
51 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_offset_y); | 52 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_offset_y); |
52 | } | 53 | } |
53 | static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL); | 54 | static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL); |
54 | 55 | ||
@@ -84,15 +85,24 @@ static int __init bgrt_init(void) | |||
84 | { | 85 | { |
85 | int ret; | 86 | int ret; |
86 | 87 | ||
87 | if (!bgrt_image) | 88 | if (!bgrt_tab.image_address) |
88 | return -ENODEV; | 89 | return -ENODEV; |
89 | 90 | ||
91 | bgrt_image = memremap(bgrt_tab.image_address, bgrt_image_size, | ||
92 | MEMREMAP_WB); | ||
93 | if (!bgrt_image) { | ||
94 | pr_notice("Ignoring BGRT: failed to map image memory\n"); | ||
95 | return -ENOMEM; | ||
96 | } | ||
97 | |||
90 | bin_attr_image.private = bgrt_image; | 98 | bin_attr_image.private = bgrt_image; |
91 | bin_attr_image.size = bgrt_image_size; | 99 | bin_attr_image.size = bgrt_image_size; |
92 | 100 | ||
93 | bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj); | 101 | bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj); |
94 | if (!bgrt_kobj) | 102 | if (!bgrt_kobj) { |
95 | return -EINVAL; | 103 | ret = -EINVAL; |
104 | goto out_memmap; | ||
105 | } | ||
96 | 106 | ||
97 | ret = sysfs_create_group(bgrt_kobj, &bgrt_attribute_group); | 107 | ret = sysfs_create_group(bgrt_kobj, &bgrt_attribute_group); |
98 | if (ret) | 108 | if (ret) |
@@ -102,6 +112,8 @@ static int __init bgrt_init(void) | |||
102 | 112 | ||
103 | out_kobject: | 113 | out_kobject: |
104 | kobject_put(bgrt_kobj); | 114 | kobject_put(bgrt_kobj); |
115 | out_memmap: | ||
116 | memunmap(bgrt_image); | ||
105 | return ret; | 117 | return ret; |
106 | } | 118 | } |
107 | device_initcall(bgrt_init); | 119 | device_initcall(bgrt_init); |
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index f853ad2c4ca0..1027d7b44358 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c | |||
@@ -250,7 +250,6 @@ void __init efi_init(void) | |||
250 | } | 250 | } |
251 | 251 | ||
252 | reserve_regions(); | 252 | reserve_regions(); |
253 | efi_memattr_init(); | ||
254 | efi_esrt_init(); | 253 | efi_esrt_init(); |
255 | efi_memmap_unmap(); | 254 | efi_memmap_unmap(); |
256 | 255 | ||
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 92914801e388..e7d404059b73 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c | |||
@@ -529,6 +529,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz, | |||
529 | } | 529 | } |
530 | } | 530 | } |
531 | 531 | ||
532 | efi_memattr_init(); | ||
533 | |||
532 | /* Parse the EFI Properties table if it exists */ | 534 | /* Parse the EFI Properties table if it exists */ |
533 | if (efi.properties_table != EFI_INVALID_TABLE_ADDR) { | 535 | if (efi.properties_table != EFI_INVALID_TABLE_ADDR) { |
534 | efi_properties_table_t *tbl; | 536 | efi_properties_table_t *tbl; |
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c index 14914074f716..08b026864d4e 100644 --- a/drivers/firmware/efi/esrt.c +++ b/drivers/firmware/efi/esrt.c | |||
@@ -269,7 +269,7 @@ void __init efi_esrt_init(void) | |||
269 | max -= efi.esrt; | 269 | max -= efi.esrt; |
270 | 270 | ||
271 | if (max < size) { | 271 | if (max < size) { |
272 | pr_err("ESRT header doen't fit on single memory map entry. (size: %zu max: %zu)\n", | 272 | pr_err("ESRT header doesn't fit on single memory map entry. (size: %zu max: %zu)\n", |
273 | size, max); | 273 | size, max); |
274 | return; | 274 | return; |
275 | } | 275 | } |
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index d564d25df8ab..f7425960f6a5 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile | |||
@@ -11,7 +11,7 @@ cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ -O2 \ | |||
11 | -mno-mmx -mno-sse | 11 | -mno-mmx -mno-sse |
12 | 12 | ||
13 | cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) | 13 | cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) |
14 | cflags-$(CONFIG_ARM) := $(subst -pg,,$(KBUILD_CFLAGS)) -g0 \ | 14 | cflags-$(CONFIG_ARM) := $(subst -pg,,$(KBUILD_CFLAGS)) \ |
15 | -fno-builtin -fpic -mno-single-pic-base | 15 | -fno-builtin -fpic -mno-single-pic-base |
16 | 16 | ||
17 | cflags-$(CONFIG_EFI_ARMSTUB) += -I$(srctree)/scripts/dtc/libfdt | 17 | cflags-$(CONFIG_EFI_ARMSTUB) += -I$(srctree)/scripts/dtc/libfdt |
@@ -28,7 +28,7 @@ OBJECT_FILES_NON_STANDARD := y | |||
28 | # Prevents link failures: __sanitizer_cov_trace_pc() is not linked in. | 28 | # Prevents link failures: __sanitizer_cov_trace_pc() is not linked in. |
29 | KCOV_INSTRUMENT := n | 29 | KCOV_INSTRUMENT := n |
30 | 30 | ||
31 | lib-y := efi-stub-helper.o gop.o | 31 | lib-y := efi-stub-helper.o gop.o secureboot.o |
32 | 32 | ||
33 | # include the stub's generic dependencies from lib/ when building for ARM/arm64 | 33 | # include the stub's generic dependencies from lib/ when building for ARM/arm64 |
34 | arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c | 34 | arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c |
@@ -60,7 +60,7 @@ CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) | |||
60 | extra-$(CONFIG_EFI_ARMSTUB) := $(lib-y) | 60 | extra-$(CONFIG_EFI_ARMSTUB) := $(lib-y) |
61 | lib-$(CONFIG_EFI_ARMSTUB) := $(patsubst %.o,%.stub.o,$(lib-y)) | 61 | lib-$(CONFIG_EFI_ARMSTUB) := $(patsubst %.o,%.stub.o,$(lib-y)) |
62 | 62 | ||
63 | STUBCOPY_FLAGS-y := -R .debug* -R *ksymtab* -R *kcrctab* | 63 | STUBCOPY_RM-y := -R *ksymtab* -R *kcrctab* |
64 | STUBCOPY_FLAGS-$(CONFIG_ARM64) += --prefix-alloc-sections=.init \ | 64 | STUBCOPY_FLAGS-$(CONFIG_ARM64) += --prefix-alloc-sections=.init \ |
65 | --prefix-symbols=__efistub_ | 65 | --prefix-symbols=__efistub_ |
66 | STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS | 66 | STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS |
@@ -68,17 +68,25 @@ STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS | |||
68 | $(obj)/%.stub.o: $(obj)/%.o FORCE | 68 | $(obj)/%.stub.o: $(obj)/%.o FORCE |
69 | $(call if_changed,stubcopy) | 69 | $(call if_changed,stubcopy) |
70 | 70 | ||
71 | # | ||
72 | # Strip debug sections and some other sections that may legally contain | ||
73 | # absolute relocations, so that we can inspect the remaining sections for | ||
74 | # such relocations. If none are found, regenerate the output object, but | ||
75 | # this time, use objcopy and leave all sections in place. | ||
76 | # | ||
71 | quiet_cmd_stubcopy = STUBCPY $@ | 77 | quiet_cmd_stubcopy = STUBCPY $@ |
72 | cmd_stubcopy = if $(OBJCOPY) $(STUBCOPY_FLAGS-y) $< $@; then \ | 78 | cmd_stubcopy = if $(STRIP) --strip-debug $(STUBCOPY_RM-y) -o $@ $<; \ |
73 | $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y) \ | 79 | then if $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y); \ |
74 | && (echo >&2 "$@: absolute symbol references not allowed in the EFI stub"; \ | 80 | then (echo >&2 "$@: absolute symbol references not allowed in the EFI stub"; \ |
75 | rm -f $@; /bin/false); else /bin/false; fi | 81 | rm -f $@; /bin/false); \ |
82 | else $(OBJCOPY) $(STUBCOPY_FLAGS-y) $< $@; fi \ | ||
83 | else /bin/false; fi | ||
76 | 84 | ||
77 | # | 85 | # |
78 | # ARM discards the .data section because it disallows r/w data in the | 86 | # ARM discards the .data section because it disallows r/w data in the |
79 | # decompressor. So move our .data to .data.efistub, which is preserved | 87 | # decompressor. So move our .data to .data.efistub, which is preserved |
80 | # explicitly by the decompressor linker script. | 88 | # explicitly by the decompressor linker script. |
81 | # | 89 | # |
82 | STUBCOPY_FLAGS-$(CONFIG_ARM) += --rename-section .data=.data.efistub \ | 90 | STUBCOPY_FLAGS-$(CONFIG_ARM) += --rename-section .data=.data.efistub |
83 | -R ___ksymtab+sort -R ___kcrctab+sort | 91 | STUBCOPY_RM-$(CONFIG_ARM) += -R ___ksymtab+sort -R ___kcrctab+sort |
84 | STUBCOPY_RELOC-$(CONFIG_ARM) := R_ARM_ABS | 92 | STUBCOPY_RELOC-$(CONFIG_ARM) := R_ARM_ABS |
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index b4f7d78f9e8b..d4056c6be1ec 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c | |||
@@ -20,52 +20,6 @@ | |||
20 | 20 | ||
21 | bool __nokaslr; | 21 | bool __nokaslr; |
22 | 22 | ||
23 | static int efi_get_secureboot(efi_system_table_t *sys_table_arg) | ||
24 | { | ||
25 | static efi_char16_t const sb_var_name[] = { | ||
26 | 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; | ||
27 | static efi_char16_t const sm_var_name[] = { | ||
28 | 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 }; | ||
29 | |||
30 | efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; | ||
31 | efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable; | ||
32 | u8 val; | ||
33 | unsigned long size = sizeof(val); | ||
34 | efi_status_t status; | ||
35 | |||
36 | status = f_getvar((efi_char16_t *)sb_var_name, (efi_guid_t *)&var_guid, | ||
37 | NULL, &size, &val); | ||
38 | |||
39 | if (status != EFI_SUCCESS) | ||
40 | goto out_efi_err; | ||
41 | |||
42 | if (val == 0) | ||
43 | return 0; | ||
44 | |||
45 | status = f_getvar((efi_char16_t *)sm_var_name, (efi_guid_t *)&var_guid, | ||
46 | NULL, &size, &val); | ||
47 | |||
48 | if (status != EFI_SUCCESS) | ||
49 | goto out_efi_err; | ||
50 | |||
51 | if (val == 1) | ||
52 | return 0; | ||
53 | |||
54 | return 1; | ||
55 | |||
56 | out_efi_err: | ||
57 | switch (status) { | ||
58 | case EFI_NOT_FOUND: | ||
59 | return 0; | ||
60 | case EFI_DEVICE_ERROR: | ||
61 | return -EIO; | ||
62 | case EFI_SECURITY_VIOLATION: | ||
63 | return -EACCES; | ||
64 | default: | ||
65 | return -EINVAL; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, | 23 | efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, |
70 | void *__image, void **__fh) | 24 | void *__image, void **__fh) |
71 | { | 25 | { |
@@ -91,75 +45,6 @@ efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, | |||
91 | return status; | 45 | return status; |
92 | } | 46 | } |
93 | 47 | ||
94 | efi_status_t efi_file_close(void *handle) | ||
95 | { | ||
96 | efi_file_handle_t *fh = handle; | ||
97 | |||
98 | return fh->close(handle); | ||
99 | } | ||
100 | |||
101 | efi_status_t | ||
102 | efi_file_read(void *handle, unsigned long *size, void *addr) | ||
103 | { | ||
104 | efi_file_handle_t *fh = handle; | ||
105 | |||
106 | return fh->read(handle, size, addr); | ||
107 | } | ||
108 | |||
109 | |||
110 | efi_status_t | ||
111 | efi_file_size(efi_system_table_t *sys_table_arg, void *__fh, | ||
112 | efi_char16_t *filename_16, void **handle, u64 *file_sz) | ||
113 | { | ||
114 | efi_file_handle_t *h, *fh = __fh; | ||
115 | efi_file_info_t *info; | ||
116 | efi_status_t status; | ||
117 | efi_guid_t info_guid = EFI_FILE_INFO_ID; | ||
118 | unsigned long info_sz; | ||
119 | |||
120 | status = fh->open(fh, &h, filename_16, EFI_FILE_MODE_READ, (u64)0); | ||
121 | if (status != EFI_SUCCESS) { | ||
122 | efi_printk(sys_table_arg, "Failed to open file: "); | ||
123 | efi_char16_printk(sys_table_arg, filename_16); | ||
124 | efi_printk(sys_table_arg, "\n"); | ||
125 | return status; | ||
126 | } | ||
127 | |||
128 | *handle = h; | ||
129 | |||
130 | info_sz = 0; | ||
131 | status = h->get_info(h, &info_guid, &info_sz, NULL); | ||
132 | if (status != EFI_BUFFER_TOO_SMALL) { | ||
133 | efi_printk(sys_table_arg, "Failed to get file info size\n"); | ||
134 | return status; | ||
135 | } | ||
136 | |||
137 | grow: | ||
138 | status = sys_table_arg->boottime->allocate_pool(EFI_LOADER_DATA, | ||
139 | info_sz, (void **)&info); | ||
140 | if (status != EFI_SUCCESS) { | ||
141 | efi_printk(sys_table_arg, "Failed to alloc mem for file info\n"); | ||
142 | return status; | ||
143 | } | ||
144 | |||
145 | status = h->get_info(h, &info_guid, &info_sz, | ||
146 | info); | ||
147 | if (status == EFI_BUFFER_TOO_SMALL) { | ||
148 | sys_table_arg->boottime->free_pool(info); | ||
149 | goto grow; | ||
150 | } | ||
151 | |||
152 | *file_sz = info->file_size; | ||
153 | sys_table_arg->boottime->free_pool(info); | ||
154 | |||
155 | if (status != EFI_SUCCESS) | ||
156 | efi_printk(sys_table_arg, "Failed to get initrd info\n"); | ||
157 | |||
158 | return status; | ||
159 | } | ||
160 | |||
161 | |||
162 | |||
163 | void efi_char16_printk(efi_system_table_t *sys_table_arg, | 48 | void efi_char16_printk(efi_system_table_t *sys_table_arg, |
164 | efi_char16_t *str) | 49 | efi_char16_t *str) |
165 | { | 50 | { |
@@ -226,7 +111,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, | |||
226 | efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; | 111 | efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID; |
227 | unsigned long reserve_addr = 0; | 112 | unsigned long reserve_addr = 0; |
228 | unsigned long reserve_size = 0; | 113 | unsigned long reserve_size = 0; |
229 | int secure_boot = 0; | 114 | enum efi_secureboot_mode secure_boot; |
230 | struct screen_info *si; | 115 | struct screen_info *si; |
231 | 116 | ||
232 | /* Check if we were booted by the EFI firmware */ | 117 | /* Check if we were booted by the EFI firmware */ |
@@ -296,19 +181,14 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, | |||
296 | pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n"); | 181 | pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n"); |
297 | 182 | ||
298 | secure_boot = efi_get_secureboot(sys_table); | 183 | secure_boot = efi_get_secureboot(sys_table); |
299 | if (secure_boot > 0) | ||
300 | pr_efi(sys_table, "UEFI Secure Boot is enabled.\n"); | ||
301 | |||
302 | if (secure_boot < 0) { | ||
303 | pr_efi_err(sys_table, | ||
304 | "could not determine UEFI Secure Boot status.\n"); | ||
305 | } | ||
306 | 184 | ||
307 | /* | 185 | /* |
308 | * Unauthenticated device tree data is a security hazard, so | 186 | * Unauthenticated device tree data is a security hazard, so ignore |
309 | * ignore 'dtb=' unless UEFI Secure Boot is disabled. | 187 | * 'dtb=' unless UEFI Secure Boot is disabled. We assume that secure |
188 | * boot is enabled if we can't determine its state. | ||
310 | */ | 189 | */ |
311 | if (secure_boot != 0 && strstr(cmdline_ptr, "dtb=")) { | 190 | if (secure_boot != efi_secureboot_mode_disabled && |
191 | strstr(cmdline_ptr, "dtb=")) { | ||
312 | pr_efi(sys_table, "Ignoring DTB from command line.\n"); | 192 | pr_efi(sys_table, "Ignoring DTB from command line.\n"); |
313 | } else { | 193 | } else { |
314 | status = handle_cmdline_files(sys_table, image, cmdline_ptr, | 194 | status = handle_cmdline_files(sys_table, image, cmdline_ptr, |
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 757badc1debb..919822b7773d 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c | |||
@@ -338,6 +338,69 @@ void efi_free(efi_system_table_t *sys_table_arg, unsigned long size, | |||
338 | efi_call_early(free_pages, addr, nr_pages); | 338 | efi_call_early(free_pages, addr, nr_pages); |
339 | } | 339 | } |
340 | 340 | ||
341 | static efi_status_t efi_file_size(efi_system_table_t *sys_table_arg, void *__fh, | ||
342 | efi_char16_t *filename_16, void **handle, | ||
343 | u64 *file_sz) | ||
344 | { | ||
345 | efi_file_handle_t *h, *fh = __fh; | ||
346 | efi_file_info_t *info; | ||
347 | efi_status_t status; | ||
348 | efi_guid_t info_guid = EFI_FILE_INFO_ID; | ||
349 | unsigned long info_sz; | ||
350 | |||
351 | status = efi_call_proto(efi_file_handle, open, fh, &h, filename_16, | ||
352 | EFI_FILE_MODE_READ, (u64)0); | ||
353 | if (status != EFI_SUCCESS) { | ||
354 | efi_printk(sys_table_arg, "Failed to open file: "); | ||
355 | efi_char16_printk(sys_table_arg, filename_16); | ||
356 | efi_printk(sys_table_arg, "\n"); | ||
357 | return status; | ||
358 | } | ||
359 | |||
360 | *handle = h; | ||
361 | |||
362 | info_sz = 0; | ||
363 | status = efi_call_proto(efi_file_handle, get_info, h, &info_guid, | ||
364 | &info_sz, NULL); | ||
365 | if (status != EFI_BUFFER_TOO_SMALL) { | ||
366 | efi_printk(sys_table_arg, "Failed to get file info size\n"); | ||
367 | return status; | ||
368 | } | ||
369 | |||
370 | grow: | ||
371 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, | ||
372 | info_sz, (void **)&info); | ||
373 | if (status != EFI_SUCCESS) { | ||
374 | efi_printk(sys_table_arg, "Failed to alloc mem for file info\n"); | ||
375 | return status; | ||
376 | } | ||
377 | |||
378 | status = efi_call_proto(efi_file_handle, get_info, h, &info_guid, | ||
379 | &info_sz, info); | ||
380 | if (status == EFI_BUFFER_TOO_SMALL) { | ||
381 | efi_call_early(free_pool, info); | ||
382 | goto grow; | ||
383 | } | ||
384 | |||
385 | *file_sz = info->file_size; | ||
386 | efi_call_early(free_pool, info); | ||
387 | |||
388 | if (status != EFI_SUCCESS) | ||
389 | efi_printk(sys_table_arg, "Failed to get initrd info\n"); | ||
390 | |||
391 | return status; | ||
392 | } | ||
393 | |||
394 | static efi_status_t efi_file_read(void *handle, unsigned long *size, void *addr) | ||
395 | { | ||
396 | return efi_call_proto(efi_file_handle, read, handle, size, addr); | ||
397 | } | ||
398 | |||
399 | static efi_status_t efi_file_close(void *handle) | ||
400 | { | ||
401 | return efi_call_proto(efi_file_handle, close, handle); | ||
402 | } | ||
403 | |||
341 | /* | 404 | /* |
342 | * Parse the ASCII string 'cmdline' for EFI options, denoted by the efi= | 405 | * Parse the ASCII string 'cmdline' for EFI options, denoted by the efi= |
343 | * option, e.g. efi=nochunk. | 406 | * option, e.g. efi=nochunk. |
@@ -351,6 +414,14 @@ efi_status_t efi_parse_options(char *cmdline) | |||
351 | char *str; | 414 | char *str; |
352 | 415 | ||
353 | /* | 416 | /* |
417 | * Currently, the only efi= option we look for is 'nochunk', which | ||
418 | * is intended to work around known issues on certain x86 UEFI | ||
419 | * versions. So ignore for now on other architectures. | ||
420 | */ | ||
421 | if (!IS_ENABLED(CONFIG_X86)) | ||
422 | return EFI_SUCCESS; | ||
423 | |||
424 | /* | ||
354 | * If no EFI parameters were specified on the cmdline we've got | 425 | * If no EFI parameters were specified on the cmdline we've got |
355 | * nothing to do. | 426 | * nothing to do. |
356 | */ | 427 | */ |
@@ -523,7 +594,8 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, | |||
523 | size = files[j].size; | 594 | size = files[j].size; |
524 | while (size) { | 595 | while (size) { |
525 | unsigned long chunksize; | 596 | unsigned long chunksize; |
526 | if (size > __chunk_size) | 597 | |
598 | if (IS_ENABLED(CONFIG_X86) && size > __chunk_size) | ||
527 | chunksize = __chunk_size; | 599 | chunksize = __chunk_size; |
528 | else | 600 | else |
529 | chunksize = size; | 601 | chunksize = size; |
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index 0e2a96b12cb3..71c4d0e3c4ed 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h | |||
@@ -29,14 +29,6 @@ void efi_char16_printk(efi_system_table_t *, efi_char16_t *); | |||
29 | efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image, | 29 | efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image, |
30 | void **__fh); | 30 | void **__fh); |
31 | 31 | ||
32 | efi_status_t efi_file_size(efi_system_table_t *sys_table_arg, void *__fh, | ||
33 | efi_char16_t *filename_16, void **handle, | ||
34 | u64 *file_sz); | ||
35 | |||
36 | efi_status_t efi_file_read(void *handle, unsigned long *size, void *addr); | ||
37 | |||
38 | efi_status_t efi_file_close(void *handle); | ||
39 | |||
40 | unsigned long get_dram_base(efi_system_table_t *sys_table_arg); | 32 | unsigned long get_dram_base(efi_system_table_t *sys_table_arg); |
41 | 33 | ||
42 | efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, | 34 | efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, |
diff --git a/drivers/firmware/efi/libstub/secureboot.c b/drivers/firmware/efi/libstub/secureboot.c new file mode 100644 index 000000000000..6def402bf569 --- /dev/null +++ b/drivers/firmware/efi/libstub/secureboot.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * Secure boot handling. | ||
3 | * | ||
4 | * Copyright (C) 2013,2014 Linaro Limited | ||
5 | * Roy Franz <roy.franz@linaro.org | ||
6 | * Copyright (C) 2013 Red Hat, Inc. | ||
7 | * Mark Salter <msalter@redhat.com> | ||
8 | * | ||
9 | * This file is part of the Linux kernel, and is made available under the | ||
10 | * terms of the GNU General Public License version 2. | ||
11 | */ | ||
12 | #include <linux/efi.h> | ||
13 | #include <asm/efi.h> | ||
14 | |||
15 | /* BIOS variables */ | ||
16 | static const efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID; | ||
17 | static const efi_char16_t const efi_SecureBoot_name[] = { | ||
18 | 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 | ||
19 | }; | ||
20 | static const efi_char16_t const efi_SetupMode_name[] = { | ||
21 | 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 | ||
22 | }; | ||
23 | |||
24 | /* SHIM variables */ | ||
25 | static const efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID; | ||
26 | static efi_char16_t const shim_MokSBState_name[] = { | ||
27 | 'M', 'o', 'k', 'S', 'B', 'S', 't', 'a', 't', 'e', 0 | ||
28 | }; | ||
29 | |||
30 | #define get_efi_var(name, vendor, ...) \ | ||
31 | efi_call_runtime(get_variable, \ | ||
32 | (efi_char16_t *)(name), (efi_guid_t *)(vendor), \ | ||
33 | __VA_ARGS__); | ||
34 | |||
35 | /* | ||
36 | * Determine whether we're in secure boot mode. | ||
37 | */ | ||
38 | enum efi_secureboot_mode efi_get_secureboot(efi_system_table_t *sys_table_arg) | ||
39 | { | ||
40 | u32 attr; | ||
41 | u8 secboot, setupmode, moksbstate; | ||
42 | unsigned long size; | ||
43 | efi_status_t status; | ||
44 | |||
45 | size = sizeof(secboot); | ||
46 | status = get_efi_var(efi_SecureBoot_name, &efi_variable_guid, | ||
47 | NULL, &size, &secboot); | ||
48 | if (status != EFI_SUCCESS) | ||
49 | goto out_efi_err; | ||
50 | |||
51 | size = sizeof(setupmode); | ||
52 | status = get_efi_var(efi_SetupMode_name, &efi_variable_guid, | ||
53 | NULL, &size, &setupmode); | ||
54 | if (status != EFI_SUCCESS) | ||
55 | goto out_efi_err; | ||
56 | |||
57 | if (secboot == 0 || setupmode == 1) | ||
58 | return efi_secureboot_mode_disabled; | ||
59 | |||
60 | /* | ||
61 | * See if a user has put the shim into insecure mode. If so, and if the | ||
62 | * variable doesn't have the runtime attribute set, we might as well | ||
63 | * honor that. | ||
64 | */ | ||
65 | size = sizeof(moksbstate); | ||
66 | status = get_efi_var(shim_MokSBState_name, &shim_guid, | ||
67 | &attr, &size, &moksbstate); | ||
68 | |||
69 | /* If it fails, we don't care why. Default to secure */ | ||
70 | if (status != EFI_SUCCESS) | ||
71 | goto secure_boot_enabled; | ||
72 | if (!(attr & EFI_VARIABLE_RUNTIME_ACCESS) && moksbstate == 1) | ||
73 | return efi_secureboot_mode_disabled; | ||
74 | |||
75 | secure_boot_enabled: | ||
76 | pr_efi(sys_table_arg, "UEFI Secure Boot is enabled.\n"); | ||
77 | return efi_secureboot_mode_enabled; | ||
78 | |||
79 | out_efi_err: | ||
80 | pr_efi_err(sys_table_arg, "Could not determine UEFI Secure Boot status.\n"); | ||
81 | if (status == EFI_NOT_FOUND) | ||
82 | return efi_secureboot_mode_disabled; | ||
83 | return efi_secureboot_mode_unknown; | ||
84 | } | ||
diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c index 236004b9a50d..8986757eafaf 100644 --- a/drivers/firmware/efi/memattr.c +++ b/drivers/firmware/efi/memattr.c | |||
@@ -43,6 +43,7 @@ int __init efi_memattr_init(void) | |||
43 | 43 | ||
44 | tbl_size = sizeof(*tbl) + tbl->num_entries * tbl->desc_size; | 44 | tbl_size = sizeof(*tbl) + tbl->num_entries * tbl->desc_size; |
45 | memblock_reserve(efi.mem_attr_table, tbl_size); | 45 | memblock_reserve(efi.mem_attr_table, tbl_size); |
46 | set_bit(EFI_MEM_ATTR, &efi.flags); | ||
46 | 47 | ||
47 | unmap: | 48 | unmap: |
48 | early_memunmap(tbl, sizeof(*tbl)); | 49 | early_memunmap(tbl, sizeof(*tbl)); |
@@ -174,8 +175,11 @@ int __init efi_memattr_apply_permissions(struct mm_struct *mm, | |||
174 | md.phys_addr + size - 1, | 175 | md.phys_addr + size - 1, |
175 | efi_md_typeattr_format(buf, sizeof(buf), &md)); | 176 | efi_md_typeattr_format(buf, sizeof(buf), &md)); |
176 | 177 | ||
177 | if (valid) | 178 | if (valid) { |
178 | ret = fn(mm, &md); | 179 | ret = fn(mm, &md); |
180 | if (ret) | ||
181 | pr_err("Error updating mappings, skipping subsequent md's\n"); | ||
182 | } | ||
179 | } | 183 | } |
180 | memunmap(tbl); | 184 | memunmap(tbl); |
181 | return ret; | 185 | return ret; |
diff --git a/include/linux/efi-bgrt.h b/include/linux/efi-bgrt.h index 051b21fedf68..2fd3993c370b 100644 --- a/include/linux/efi-bgrt.h +++ b/include/linux/efi-bgrt.h | |||
@@ -1,20 +1,19 @@ | |||
1 | #ifndef _LINUX_EFI_BGRT_H | 1 | #ifndef _LINUX_EFI_BGRT_H |
2 | #define _LINUX_EFI_BGRT_H | 2 | #define _LINUX_EFI_BGRT_H |
3 | 3 | ||
4 | #ifdef CONFIG_ACPI_BGRT | ||
5 | |||
6 | #include <linux/acpi.h> | 4 | #include <linux/acpi.h> |
7 | 5 | ||
8 | void efi_bgrt_init(void); | 6 | #ifdef CONFIG_ACPI_BGRT |
7 | |||
8 | void efi_bgrt_init(struct acpi_table_header *table); | ||
9 | 9 | ||
10 | /* The BGRT data itself; only valid if bgrt_image != NULL. */ | 10 | /* The BGRT data itself; only valid if bgrt_image != NULL. */ |
11 | extern void *bgrt_image; | ||
12 | extern size_t bgrt_image_size; | 11 | extern size_t bgrt_image_size; |
13 | extern struct acpi_table_bgrt *bgrt_tab; | 12 | extern struct acpi_table_bgrt bgrt_tab; |
14 | 13 | ||
15 | #else /* !CONFIG_ACPI_BGRT */ | 14 | #else /* !CONFIG_ACPI_BGRT */ |
16 | 15 | ||
17 | static inline void efi_bgrt_init(void) {} | 16 | static inline void efi_bgrt_init(struct acpi_table_header *table) {} |
18 | 17 | ||
19 | #endif /* !CONFIG_ACPI_BGRT */ | 18 | #endif /* !CONFIG_ACPI_BGRT */ |
20 | 19 | ||
diff --git a/include/linux/efi.h b/include/linux/efi.h index 5b1af30ece55..94d34e0be24f 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
@@ -509,24 +509,6 @@ typedef struct { | |||
509 | u64 query_variable_info; | 509 | u64 query_variable_info; |
510 | } efi_runtime_services_64_t; | 510 | } efi_runtime_services_64_t; |
511 | 511 | ||
512 | typedef struct { | ||
513 | efi_table_hdr_t hdr; | ||
514 | void *get_time; | ||
515 | void *set_time; | ||
516 | void *get_wakeup_time; | ||
517 | void *set_wakeup_time; | ||
518 | void *set_virtual_address_map; | ||
519 | void *convert_pointer; | ||
520 | void *get_variable; | ||
521 | void *get_next_variable; | ||
522 | void *set_variable; | ||
523 | void *get_next_high_mono_count; | ||
524 | void *reset_system; | ||
525 | void *update_capsule; | ||
526 | void *query_capsule_caps; | ||
527 | void *query_variable_info; | ||
528 | } efi_runtime_services_t; | ||
529 | |||
530 | typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc); | 512 | typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc); |
531 | typedef efi_status_t efi_set_time_t (efi_time_t *tm); | 513 | typedef efi_status_t efi_set_time_t (efi_time_t *tm); |
532 | typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending, | 514 | typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending, |
@@ -561,6 +543,24 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, | |||
561 | unsigned long size, | 543 | unsigned long size, |
562 | bool nonblocking); | 544 | bool nonblocking); |
563 | 545 | ||
546 | typedef struct { | ||
547 | efi_table_hdr_t hdr; | ||
548 | efi_get_time_t *get_time; | ||
549 | efi_set_time_t *set_time; | ||
550 | efi_get_wakeup_time_t *get_wakeup_time; | ||
551 | efi_set_wakeup_time_t *set_wakeup_time; | ||
552 | efi_set_virtual_address_map_t *set_virtual_address_map; | ||
553 | void *convert_pointer; | ||
554 | efi_get_variable_t *get_variable; | ||
555 | efi_get_next_variable_t *get_next_variable; | ||
556 | efi_set_variable_t *set_variable; | ||
557 | efi_get_next_high_mono_count_t *get_next_high_mono_count; | ||
558 | efi_reset_system_t *reset_system; | ||
559 | efi_update_capsule_t *update_capsule; | ||
560 | efi_query_capsule_caps_t *query_capsule_caps; | ||
561 | efi_query_variable_info_t *query_variable_info; | ||
562 | } efi_runtime_services_t; | ||
563 | |||
564 | void efi_native_runtime_setup(void); | 564 | void efi_native_runtime_setup(void); |
565 | 565 | ||
566 | /* | 566 | /* |
@@ -611,6 +611,9 @@ void efi_native_runtime_setup(void); | |||
611 | #define EFI_CONSOLE_OUT_DEVICE_GUID EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) | 611 | #define EFI_CONSOLE_OUT_DEVICE_GUID EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) |
612 | #define APPLE_PROPERTIES_PROTOCOL_GUID EFI_GUID(0x91bd12fe, 0xf6c3, 0x44fb, 0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0) | 612 | #define APPLE_PROPERTIES_PROTOCOL_GUID EFI_GUID(0x91bd12fe, 0xf6c3, 0x44fb, 0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0) |
613 | 613 | ||
614 | #define EFI_IMAGE_SECURITY_DATABASE_GUID EFI_GUID(0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f) | ||
615 | #define EFI_SHIM_LOCK_GUID EFI_GUID(0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23) | ||
616 | |||
614 | /* | 617 | /* |
615 | * This GUID is used to pass to the kernel proper the struct screen_info | 618 | * This GUID is used to pass to the kernel proper the struct screen_info |
616 | * structure that was populated by the stub based on the GOP protocol instance | 619 | * structure that was populated by the stub based on the GOP protocol instance |
@@ -1065,6 +1068,7 @@ extern int __init efi_setup_pcdp_console(char *); | |||
1065 | #define EFI_ARCH_1 7 /* First arch-specific bit */ | 1068 | #define EFI_ARCH_1 7 /* First arch-specific bit */ |
1066 | #define EFI_DBG 8 /* Print additional debug info at runtime */ | 1069 | #define EFI_DBG 8 /* Print additional debug info at runtime */ |
1067 | #define EFI_NX_PE_DATA 9 /* Can runtime data regions be mapped non-executable? */ | 1070 | #define EFI_NX_PE_DATA 9 /* Can runtime data regions be mapped non-executable? */ |
1071 | #define EFI_MEM_ATTR 10 /* Did firmware publish an EFI_MEMORY_ATTRIBUTES table? */ | ||
1068 | 1072 | ||
1069 | #ifdef CONFIG_EFI | 1073 | #ifdef CONFIG_EFI |
1070 | /* | 1074 | /* |
@@ -1240,17 +1244,17 @@ struct efivar_entry { | |||
1240 | bool deleting; | 1244 | bool deleting; |
1241 | }; | 1245 | }; |
1242 | 1246 | ||
1243 | struct efi_simple_text_output_protocol_32 { | 1247 | typedef struct { |
1244 | u32 reset; | 1248 | u32 reset; |
1245 | u32 output_string; | 1249 | u32 output_string; |
1246 | u32 test_string; | 1250 | u32 test_string; |
1247 | }; | 1251 | } efi_simple_text_output_protocol_32_t; |
1248 | 1252 | ||
1249 | struct efi_simple_text_output_protocol_64 { | 1253 | typedef struct { |
1250 | u64 reset; | 1254 | u64 reset; |
1251 | u64 output_string; | 1255 | u64 output_string; |
1252 | u64 test_string; | 1256 | u64 test_string; |
1253 | }; | 1257 | } efi_simple_text_output_protocol_64_t; |
1254 | 1258 | ||
1255 | struct efi_simple_text_output_protocol { | 1259 | struct efi_simple_text_output_protocol { |
1256 | void *reset; | 1260 | void *reset; |
@@ -1476,6 +1480,14 @@ efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg, | |||
1476 | bool efi_runtime_disabled(void); | 1480 | bool efi_runtime_disabled(void); |
1477 | extern void efi_call_virt_check_flags(unsigned long flags, const char *call); | 1481 | extern void efi_call_virt_check_flags(unsigned long flags, const char *call); |
1478 | 1482 | ||
1483 | enum efi_secureboot_mode { | ||
1484 | efi_secureboot_mode_unset, | ||
1485 | efi_secureboot_mode_unknown, | ||
1486 | efi_secureboot_mode_disabled, | ||
1487 | efi_secureboot_mode_enabled, | ||
1488 | }; | ||
1489 | enum efi_secureboot_mode efi_get_secureboot(efi_system_table_t *sys_table); | ||
1490 | |||
1479 | /* | 1491 | /* |
1480 | * Arch code can implement the following three template macros, avoiding | 1492 | * Arch code can implement the following three template macros, avoiding |
1481 | * reptition for the void/non-void return cases of {__,}efi_call_virt(): | 1493 | * reptition for the void/non-void return cases of {__,}efi_call_virt(): |
diff --git a/init/main.c b/init/main.c index b0c9d6facef9..9648d707eea5 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -663,7 +663,6 @@ asmlinkage __visible void __init start_kernel(void) | |||
663 | sfi_init_late(); | 663 | sfi_init_late(); |
664 | 664 | ||
665 | if (efi_enabled(EFI_RUNTIME_SERVICES)) { | 665 | if (efi_enabled(EFI_RUNTIME_SERVICES)) { |
666 | efi_late_init(); | ||
667 | efi_free_boot_services(); | 666 | efi_free_boot_services(); |
668 | } | 667 | } |
669 | 668 | ||