diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 5 | ||||
-rw-r--r-- | arch/x86/boot/compressed/eboot.c | 4 | ||||
-rw-r--r-- | arch/x86/platform/efi/efi.c | 19 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/arm-stub.c | 4 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/efi-stub-helper.c | 62 | ||||
-rw-r--r-- | include/linux/efi.h | 2 |
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 | ||
33 | static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE; | ||
34 | |||
20 | struct file_info { | 35 | struct 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 | */ | ||
307 | efi_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 | ||
1230 | efi_status_t efi_parse_options(char *cmdline); | ||
1231 | |||
1230 | #endif /* _LINUX_EFI_H */ | 1232 | #endif /* _LINUX_EFI_H */ |