aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware/efi/libstub/efi-stub-helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware/efi/libstub/efi-stub-helper.c')
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c62
1 files changed, 60 insertions, 2 deletions
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