aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt5
-rw-r--r--arch/x86/boot/compressed/eboot.c4
-rw-r--r--arch/x86/platform/efi/efi.c19
-rw-r--r--drivers/firmware/efi/libstub/arm-stub.c4
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c62
-rw-r--r--include/linux/efi.h2
6 files changed, 91 insertions, 5 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 5ae8608ca9f5..67d79597d9d6 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -992,10 +992,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
992 Format: {"off" | "on" | "skip[mbr]"} 992 Format: {"off" | "on" | "skip[mbr]"}
993 993
994 efi= [EFI] 994 efi= [EFI]
995 Format: { "old_map" } 995 Format: { "old_map", "nochunk" }
996 old_map [X86-64]: switch to the old ioremap-based EFI 996 old_map [X86-64]: switch to the old ioremap-based EFI
997 runtime services mapping. 32-bit still uses this one by 997 runtime services mapping. 32-bit still uses this one by
998 default. 998 default.
999 nochunk: disable reading files in "chunks" in the EFI
1000 boot stub, as chunking can cause problems with some
1001 firmware implementations.
999 1002
1000 efi_no_storage_paranoia [EFI; X86] 1003 efi_no_storage_paranoia [EFI; X86]
1001 Using this parameter you can use more than 50% of 1004 Using this parameter you can use more than 50% of
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index f277184e2ac1..f4bdab1dbf66 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -1100,6 +1100,10 @@ struct boot_params *make_boot_params(struct efi_config *c)
1100 else 1100 else
1101 initrd_addr_max = hdr->initrd_addr_max; 1101 initrd_addr_max = hdr->initrd_addr_max;
1102 1102
1103 status = efi_parse_options(cmdline_ptr);
1104 if (status != EFI_SUCCESS)
1105 goto fail2;
1106
1103 status = handle_cmdline_files(sys_table, image, 1107 status = handle_cmdline_files(sys_table, image,
1104 (char *)(unsigned long)hdr->cmd_line_ptr, 1108 (char *)(unsigned long)hdr->cmd_line_ptr,
1105 "initrd=", initrd_addr_max, 1109 "initrd=", initrd_addr_max,
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 850da94fef30..a1f745b0bf1d 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -943,8 +943,23 @@ static int __init parse_efi_cmdline(char *str)
943 if (*str == '=') 943 if (*str == '=')
944 str++; 944 str++;
945 945
946 if (!strncmp(str, "old_map", 7)) 946 while (*str) {
947 set_bit(EFI_OLD_MEMMAP, &efi.flags); 947 if (!strncmp(str, "old_map", 7)) {
948 set_bit(EFI_OLD_MEMMAP, &efi.flags);
949 str += strlen("old_map");
950 }
951
952 /*
953 * Skip any options we don't understand. Presumably
954 * they apply to the EFI boot stub.
955 */
956 while (*str && *str != ',')
957 str++;
958
959 /* If we hit a delimiter, skip it */
960 if (*str == ',')
961 str++;
962 }
948 963
949 return 0; 964 return 0;
950} 965}
diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c
index 480339b6b110..75ee05964cbc 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -226,6 +226,10 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
226 goto fail_free_image; 226 goto fail_free_image;
227 } 227 }
228 228
229 status = efi_parse_options(cmdline_ptr);
230 if (status != EFI_SUCCESS)
231 pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n");
232
229 /* 233 /*
230 * Unauthenticated device tree data is a security hazard, so 234 * Unauthenticated device tree data is a security hazard, so
231 * ignore 'dtb=' unless UEFI Secure Boot is disabled. 235 * ignore 'dtb=' unless UEFI Secure Boot is disabled.
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 32d5cca30f49..a920fec8fe88 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -15,8 +15,23 @@
15 15
16#include "efistub.h" 16#include "efistub.h"
17 17
18/*
19 * Some firmware implementations have problems reading files in one go.
20 * A read chunk size of 1MB seems to work for most platforms.
21 *
22 * Unfortunately, reading files in chunks triggers *other* bugs on some
23 * platforms, so we provide a way to disable this workaround, which can
24 * be done by passing "efi=nochunk" on the EFI boot stub command line.
25 *
26 * If you experience issues with initrd images being corrupt it's worth
27 * trying efi=nochunk, but chunking is enabled by default because there
28 * are far more machines that require the workaround than those that
29 * break with it enabled.
30 */
18#define EFI_READ_CHUNK_SIZE (1024 * 1024) 31#define EFI_READ_CHUNK_SIZE (1024 * 1024)
19 32
33static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
34
20struct file_info { 35struct file_info {
21 efi_file_handle_t *handle; 36 efi_file_handle_t *handle;
22 u64 size; 37 u64 size;
@@ -281,6 +296,49 @@ void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
281 efi_call_early(free_pages, addr, nr_pages); 296 efi_call_early(free_pages, addr, nr_pages);
282} 297}
283 298
299/*
300 * Parse the ASCII string 'cmdline' for EFI options, denoted by the efi=
301 * option, e.g. efi=nochunk.
302 *
303 * It should be noted that efi= is parsed in two very different
304 * environments, first in the early boot environment of the EFI boot
305 * stub, and subsequently during the kernel boot.
306 */
307efi_status_t efi_parse_options(char *cmdline)
308{
309 char *str;
310
311 /*
312 * If no EFI parameters were specified on the cmdline we've got
313 * nothing to do.
314 */
315 str = strstr(cmdline, "efi=");
316 if (!str)
317 return EFI_SUCCESS;
318
319 /* Skip ahead to first argument */
320 str += strlen("efi=");
321
322 /*
323 * Remember, because efi= is also used by the kernel we need to
324 * skip over arguments we don't understand.
325 */
326 while (*str) {
327 if (!strncmp(str, "nochunk", 7)) {
328 str += strlen("nochunk");
329 __chunk_size = -1UL;
330 }
331
332 /* Group words together, delimited by "," */
333 while (*str && *str != ',')
334 str++;
335
336 if (*str == ',')
337 str++;
338 }
339
340 return EFI_SUCCESS;
341}
284 342
285/* 343/*
286 * Check the cmdline for a LILO-style file= arguments. 344 * Check the cmdline for a LILO-style file= arguments.
@@ -423,8 +481,8 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
423 size = files[j].size; 481 size = files[j].size;
424 while (size) { 482 while (size) {
425 unsigned long chunksize; 483 unsigned long chunksize;
426 if (size > EFI_READ_CHUNK_SIZE) 484 if (size > __chunk_size)
427 chunksize = EFI_READ_CHUNK_SIZE; 485 chunksize = __chunk_size;
428 else 486 else
429 chunksize = size; 487 chunksize = size;
430 488
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 45cb4ffdea62..518779fb5e90 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1227,4 +1227,6 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
1227 unsigned long *load_addr, 1227 unsigned long *load_addr,
1228 unsigned long *load_size); 1228 unsigned long *load_size);
1229 1229
1230efi_status_t efi_parse_options(char *cmdline);
1231
1230#endif /* _LINUX_EFI_H */ 1232#endif /* _LINUX_EFI_H */