2020-02-10 17:02:43 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/*
|
|
|
|
* Helper functions used by the EFI stub on multiple
|
|
|
|
* architectures. This should be #included by the EFI stub
|
|
|
|
* implementation files.
|
|
|
|
*
|
|
|
|
* Copyright 2011 Intel Corporation; author Matt Fleming
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/efi.h>
|
|
|
|
#include <asm/efi.h>
|
|
|
|
|
|
|
|
#include "efistub.h"
|
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
#define MAX_FILENAME_SIZE 256
|
|
|
|
|
2020-02-10 17:02:43 +01:00
|
|
|
/*
|
|
|
|
* Some firmware implementations have problems reading files in one go.
|
|
|
|
* A read chunk size of 1MB seems to work for most platforms.
|
|
|
|
*
|
|
|
|
* Unfortunately, reading files in chunks triggers *other* bugs on some
|
|
|
|
* platforms, so we provide a way to disable this workaround, which can
|
|
|
|
* be done by passing "efi=nochunk" on the EFI boot stub command line.
|
|
|
|
*
|
|
|
|
* If you experience issues with initrd images being corrupt it's worth
|
|
|
|
* trying efi=nochunk, but chunking is enabled by default on x86 because
|
|
|
|
* there are far more machines that require the workaround than those that
|
|
|
|
* break with it enabled.
|
|
|
|
*/
|
|
|
|
#define EFI_READ_CHUNK_SIZE SZ_1M
|
|
|
|
|
2020-04-09 15:04:32 +02:00
|
|
|
struct finfo {
|
|
|
|
efi_file_info_t info;
|
|
|
|
efi_char16_t filename[MAX_FILENAME_SIZE];
|
|
|
|
};
|
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
static efi_status_t efi_open_file(efi_file_protocol_t *volume,
|
2020-04-09 15:04:32 +02:00
|
|
|
struct finfo *fi,
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
efi_file_protocol_t **handle,
|
|
|
|
unsigned long *file_size)
|
2020-02-10 17:02:43 +01:00
|
|
|
{
|
|
|
|
efi_guid_t info_guid = EFI_FILE_INFO_ID;
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
efi_file_protocol_t *fh;
|
2020-02-10 17:02:43 +01:00
|
|
|
unsigned long info_sz;
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
efi_status_t status;
|
efi: libstub: Implement devicepath support for initrd commandline loader
Currently, the initrd= command line option to the EFI stub only supports
loading files that reside on the same volume as the loaded image, which
is not workable for loaders like GRUB that don't even implement the
volume abstraction (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL), and load the
kernel from an anonymous buffer in memory. For this reason, another
method was devised that relies on the LoadFile2 protocol.
However, the command line loader is rather useful when using the UEFI
shell or other generic loaders that have no awareness of Linux specific
protocols so let's make it a bit more flexible, by permitting textual
device paths to be provided to initrd= as well, provided that they refer
to a file hosted on a EFI_SIMPLE_FILE_SYSTEM_PROTOCOL volume. E.g.,
initrd=PciRoot(0x0)/Pci(0x3,0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/rootfs.cpio.gz
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2022-09-26 21:32:16 +02:00
|
|
|
efi_char16_t *c;
|
|
|
|
|
|
|
|
/* Replace UNIX dir separators with EFI standard ones */
|
|
|
|
for (c = fi->filename; *c != L'\0'; c++) {
|
|
|
|
if (*c == L'/')
|
|
|
|
*c = L'\\';
|
|
|
|
}
|
2020-02-10 17:02:43 +01:00
|
|
|
|
2022-09-26 22:17:21 +02:00
|
|
|
status = efi_call_proto(volume, open, &fh, fi->filename,
|
|
|
|
EFI_FILE_MODE_READ, 0);
|
2020-02-10 17:02:43 +01:00
|
|
|
if (status != EFI_SUCCESS) {
|
2020-05-18 15:07:14 -04:00
|
|
|
efi_err("Failed to open file: %ls\n", fi->filename);
|
2020-02-10 17:02:43 +01:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2020-04-09 15:04:32 +02:00
|
|
|
info_sz = sizeof(struct finfo);
|
2022-09-26 22:17:21 +02:00
|
|
|
status = efi_call_proto(fh, get_info, &info_guid, &info_sz, fi);
|
2020-02-10 17:02:43 +01:00
|
|
|
if (status != EFI_SUCCESS) {
|
2020-04-30 14:28:35 -04:00
|
|
|
efi_err("Failed to get file info\n");
|
2022-09-26 22:17:21 +02:00
|
|
|
efi_call_proto(fh, close);
|
2020-02-10 17:02:43 +01:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
*handle = fh;
|
2020-04-09 15:04:32 +02:00
|
|
|
*file_size = fi->info.file_size;
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
return EFI_SUCCESS;
|
2020-02-10 17:02:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static efi_status_t efi_open_volume(efi_loaded_image_t *image,
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
efi_file_protocol_t **fh)
|
2020-02-10 17:02:43 +01:00
|
|
|
{
|
|
|
|
efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
efi_simple_file_system_protocol_t *io;
|
2020-02-10 17:02:43 +01:00
|
|
|
efi_status_t status;
|
|
|
|
|
2022-09-26 22:17:21 +02:00
|
|
|
status = efi_bs_call(handle_protocol, efi_table_attr(image, device_handle),
|
|
|
|
&fs_proto, (void **)&io);
|
2020-02-10 17:02:43 +01:00
|
|
|
if (status != EFI_SUCCESS) {
|
2020-04-30 14:28:35 -04:00
|
|
|
efi_err("Failed to handle fs_proto\n");
|
2020-02-10 17:02:43 +01:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2022-09-26 22:17:21 +02:00
|
|
|
status = efi_call_proto(io, open_volume, fh);
|
2020-02-10 17:02:43 +01:00
|
|
|
if (status != EFI_SUCCESS)
|
2020-04-30 14:28:35 -04:00
|
|
|
efi_err("Failed to open volume\n");
|
2020-02-10 17:02:43 +01:00
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
static int find_file_option(const efi_char16_t *cmdline, int cmdline_len,
|
|
|
|
const efi_char16_t *prefix, int prefix_size,
|
|
|
|
efi_char16_t *result, int result_len)
|
|
|
|
{
|
|
|
|
int prefix_len = prefix_size / 2;
|
|
|
|
bool found = false;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = prefix_len; i < cmdline_len; i++) {
|
|
|
|
if (!memcmp(&cmdline[i - prefix_len], prefix, prefix_size)) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found)
|
|
|
|
return 0;
|
|
|
|
|
2020-06-15 13:51:09 +02:00
|
|
|
/* Skip any leading slashes */
|
2021-04-23 14:48:31 +03:00
|
|
|
while (i < cmdline_len && (cmdline[i] == L'/' || cmdline[i] == L'\\'))
|
2020-06-15 13:51:09 +02:00
|
|
|
i++;
|
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
while (--result_len > 0 && i < cmdline_len) {
|
2020-06-15 13:51:09 +02:00
|
|
|
efi_char16_t c = cmdline[i++];
|
|
|
|
|
|
|
|
if (c == L'\0' || c == L'\n' || c == L' ')
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
break;
|
efi: libstub: Implement devicepath support for initrd commandline loader
Currently, the initrd= command line option to the EFI stub only supports
loading files that reside on the same volume as the loaded image, which
is not workable for loaders like GRUB that don't even implement the
volume abstraction (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL), and load the
kernel from an anonymous buffer in memory. For this reason, another
method was devised that relies on the LoadFile2 protocol.
However, the command line loader is rather useful when using the UEFI
shell or other generic loaders that have no awareness of Linux specific
protocols so let's make it a bit more flexible, by permitting textual
device paths to be provided to initrd= as well, provided that they refer
to a file hosted on a EFI_SIMPLE_FILE_SYSTEM_PROTOCOL volume. E.g.,
initrd=PciRoot(0x0)/Pci(0x3,0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/rootfs.cpio.gz
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2022-09-26 21:32:16 +02:00
|
|
|
*result++ = c;
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
}
|
|
|
|
*result = L'\0';
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
efi: libstub: Implement devicepath support for initrd commandline loader
Currently, the initrd= command line option to the EFI stub only supports
loading files that reside on the same volume as the loaded image, which
is not workable for loaders like GRUB that don't even implement the
volume abstraction (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL), and load the
kernel from an anonymous buffer in memory. For this reason, another
method was devised that relies on the LoadFile2 protocol.
However, the command line loader is rather useful when using the UEFI
shell or other generic loaders that have no awareness of Linux specific
protocols so let's make it a bit more flexible, by permitting textual
device paths to be provided to initrd= as well, provided that they refer
to a file hosted on a EFI_SIMPLE_FILE_SYSTEM_PROTOCOL volume. E.g.,
initrd=PciRoot(0x0)/Pci(0x3,0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/rootfs.cpio.gz
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2022-09-26 21:32:16 +02:00
|
|
|
static efi_status_t efi_open_device_path(efi_file_protocol_t **volume,
|
|
|
|
struct finfo *fi)
|
|
|
|
{
|
|
|
|
efi_guid_t text_to_dp_guid = EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID;
|
|
|
|
static efi_device_path_from_text_protocol_t *text_to_dp = NULL;
|
|
|
|
efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
|
|
|
|
efi_device_path_protocol_t *initrd_dp;
|
|
|
|
efi_simple_file_system_protocol_t *io;
|
|
|
|
struct efi_file_path_dev_path *fpath;
|
|
|
|
efi_handle_t handle;
|
|
|
|
efi_status_t status;
|
|
|
|
|
|
|
|
/* See if the text to device path protocol exists */
|
|
|
|
if (!text_to_dp &&
|
|
|
|
efi_bs_call(locate_protocol, &text_to_dp_guid, NULL,
|
|
|
|
(void **)&text_to_dp) != EFI_SUCCESS)
|
|
|
|
return EFI_UNSUPPORTED;
|
|
|
|
|
|
|
|
|
|
|
|
/* Convert the filename wide string into a device path */
|
2022-09-26 22:17:21 +02:00
|
|
|
initrd_dp = efi_fn_call(text_to_dp, convert_text_to_device_path,
|
|
|
|
fi->filename);
|
efi: libstub: Implement devicepath support for initrd commandline loader
Currently, the initrd= command line option to the EFI stub only supports
loading files that reside on the same volume as the loaded image, which
is not workable for loaders like GRUB that don't even implement the
volume abstraction (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL), and load the
kernel from an anonymous buffer in memory. For this reason, another
method was devised that relies on the LoadFile2 protocol.
However, the command line loader is rather useful when using the UEFI
shell or other generic loaders that have no awareness of Linux specific
protocols so let's make it a bit more flexible, by permitting textual
device paths to be provided to initrd= as well, provided that they refer
to a file hosted on a EFI_SIMPLE_FILE_SYSTEM_PROTOCOL volume. E.g.,
initrd=PciRoot(0x0)/Pci(0x3,0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/rootfs.cpio.gz
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2022-09-26 21:32:16 +02:00
|
|
|
|
|
|
|
/* Check whether the device path in question implements simple FS */
|
|
|
|
if ((efi_bs_call(locate_device_path, &fs_proto, &initrd_dp, &handle) ?:
|
|
|
|
efi_bs_call(handle_protocol, handle, &fs_proto, (void **)&io))
|
|
|
|
!= EFI_SUCCESS)
|
|
|
|
return EFI_NOT_FOUND;
|
|
|
|
|
|
|
|
/* Check whether the remaining device path is a file device path */
|
|
|
|
if (initrd_dp->type != EFI_DEV_MEDIA ||
|
|
|
|
initrd_dp->sub_type != EFI_DEV_MEDIA_FILE) {
|
|
|
|
efi_warn("Unexpected device path node type: (%x, %x)\n",
|
|
|
|
initrd_dp->type, initrd_dp->sub_type);
|
|
|
|
return EFI_LOAD_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy the remaining file path into the fi structure */
|
|
|
|
fpath = (struct efi_file_path_dev_path *)initrd_dp;
|
|
|
|
memcpy(fi->filename, fpath->filename,
|
|
|
|
min(sizeof(fi->filename),
|
|
|
|
fpath->header.length - sizeof(fpath->header)));
|
|
|
|
|
2022-09-26 22:17:21 +02:00
|
|
|
status = efi_call_proto(io, open_volume, volume);
|
efi: libstub: Implement devicepath support for initrd commandline loader
Currently, the initrd= command line option to the EFI stub only supports
loading files that reside on the same volume as the loaded image, which
is not workable for loaders like GRUB that don't even implement the
volume abstraction (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL), and load the
kernel from an anonymous buffer in memory. For this reason, another
method was devised that relies on the LoadFile2 protocol.
However, the command line loader is rather useful when using the UEFI
shell or other generic loaders that have no awareness of Linux specific
protocols so let's make it a bit more flexible, by permitting textual
device paths to be provided to initrd= as well, provided that they refer
to a file hosted on a EFI_SIMPLE_FILE_SYSTEM_PROTOCOL volume. E.g.,
initrd=PciRoot(0x0)/Pci(0x3,0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/rootfs.cpio.gz
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2022-09-26 21:32:16 +02:00
|
|
|
if (status != EFI_SUCCESS)
|
|
|
|
efi_err("Failed to open volume\n");
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2024-10-13 11:20:45 +02:00
|
|
|
#ifndef CONFIG_CMDLINE
|
|
|
|
#define CONFIG_CMDLINE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static const efi_char16_t builtin_cmdline[] = L"" CONFIG_CMDLINE;
|
|
|
|
|
2020-02-10 17:02:43 +01:00
|
|
|
/*
|
|
|
|
* Check the cmdline for a LILO-style file= arguments.
|
|
|
|
*
|
|
|
|
* We only support loading a file from the same filesystem as
|
|
|
|
* the kernel image.
|
|
|
|
*/
|
2020-04-21 09:17:35 +02:00
|
|
|
efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
|
|
|
|
const efi_char16_t *optstr,
|
|
|
|
int optstr_size,
|
|
|
|
unsigned long soft_limit,
|
|
|
|
unsigned long hard_limit,
|
|
|
|
unsigned long *load_addr,
|
|
|
|
unsigned long *load_size)
|
2020-02-10 17:02:43 +01:00
|
|
|
{
|
2024-10-13 13:10:38 +02:00
|
|
|
const bool ignore_load_options = IS_ENABLED(CONFIG_CMDLINE_OVERRIDE) ||
|
|
|
|
IS_ENABLED(CONFIG_CMDLINE_FORCE);
|
2022-09-26 22:17:21 +02:00
|
|
|
const efi_char16_t *cmdline = efi_table_attr(image, load_options);
|
|
|
|
u32 cmdline_len = efi_table_attr(image, load_options_size);
|
2020-02-10 17:02:43 +01:00
|
|
|
unsigned long efi_chunk_size = ULONG_MAX;
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
efi_file_protocol_t *volume = NULL;
|
|
|
|
efi_file_protocol_t *file;
|
|
|
|
unsigned long alloc_addr;
|
|
|
|
unsigned long alloc_size;
|
2020-02-10 17:02:43 +01:00
|
|
|
efi_status_t status;
|
2024-10-13 11:20:45 +02:00
|
|
|
bool twopass;
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
int offset;
|
2020-02-10 17:02:43 +01:00
|
|
|
|
|
|
|
if (!load_addr || !load_size)
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
|
2020-09-14 17:35:35 -04:00
|
|
|
efi_apply_loadoptions_quirk((const void **)&cmdline, &cmdline_len);
|
|
|
|
cmdline_len /= sizeof(*cmdline);
|
|
|
|
|
2020-04-16 18:45:24 +02:00
|
|
|
if (IS_ENABLED(CONFIG_X86) && !efi_nochunk)
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
efi_chunk_size = EFI_READ_CHUNK_SIZE;
|
2020-02-10 17:02:43 +01:00
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
alloc_addr = alloc_size = 0;
|
2024-10-13 11:20:45 +02:00
|
|
|
|
|
|
|
if (!ignore_load_options && cmdline_len > 0) {
|
|
|
|
twopass = IS_ENABLED(CONFIG_CMDLINE_BOOL) ||
|
|
|
|
IS_ENABLED(CONFIG_CMDLINE_EXTEND);
|
|
|
|
} else {
|
|
|
|
do_builtin: cmdline = builtin_cmdline;
|
|
|
|
cmdline_len = ARRAY_SIZE(builtin_cmdline) - 1;
|
|
|
|
twopass = false;
|
|
|
|
}
|
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
do {
|
2020-04-09 15:04:32 +02:00
|
|
|
struct finfo fi;
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
unsigned long size;
|
|
|
|
void *addr;
|
2020-02-10 17:02:43 +01:00
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
offset = find_file_option(cmdline, cmdline_len,
|
|
|
|
optstr, optstr_size,
|
2020-04-09 15:04:32 +02:00
|
|
|
fi.filename, ARRAY_SIZE(fi.filename));
|
2020-02-10 17:02:43 +01:00
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
if (!offset)
|
2020-02-10 17:02:43 +01:00
|
|
|
break;
|
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
cmdline += offset;
|
|
|
|
cmdline_len -= offset;
|
2020-02-10 17:02:43 +01:00
|
|
|
|
efi: libstub: Implement devicepath support for initrd commandline loader
Currently, the initrd= command line option to the EFI stub only supports
loading files that reside on the same volume as the loaded image, which
is not workable for loaders like GRUB that don't even implement the
volume abstraction (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL), and load the
kernel from an anonymous buffer in memory. For this reason, another
method was devised that relies on the LoadFile2 protocol.
However, the command line loader is rather useful when using the UEFI
shell or other generic loaders that have no awareness of Linux specific
protocols so let's make it a bit more flexible, by permitting textual
device paths to be provided to initrd= as well, provided that they refer
to a file hosted on a EFI_SIMPLE_FILE_SYSTEM_PROTOCOL volume. E.g.,
initrd=PciRoot(0x0)/Pci(0x3,0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/rootfs.cpio.gz
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2022-09-26 21:32:16 +02:00
|
|
|
status = efi_open_device_path(&volume, &fi);
|
|
|
|
if (status == EFI_UNSUPPORTED || status == EFI_NOT_FOUND)
|
|
|
|
/* try the volume that holds the kernel itself */
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
status = efi_open_volume(image, &volume);
|
efi: libstub: Implement devicepath support for initrd commandline loader
Currently, the initrd= command line option to the EFI stub only supports
loading files that reside on the same volume as the loaded image, which
is not workable for loaders like GRUB that don't even implement the
volume abstraction (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL), and load the
kernel from an anonymous buffer in memory. For this reason, another
method was devised that relies on the LoadFile2 protocol.
However, the command line loader is rather useful when using the UEFI
shell or other generic loaders that have no awareness of Linux specific
protocols so let's make it a bit more flexible, by permitting textual
device paths to be provided to initrd= as well, provided that they refer
to a file hosted on a EFI_SIMPLE_FILE_SYSTEM_PROTOCOL volume. E.g.,
initrd=PciRoot(0x0)/Pci(0x3,0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/rootfs.cpio.gz
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2022-09-26 21:32:16 +02:00
|
|
|
|
|
|
|
if (status != EFI_SUCCESS)
|
|
|
|
goto err_free_alloc;
|
2020-02-10 17:02:43 +01:00
|
|
|
|
2020-04-09 15:04:32 +02:00
|
|
|
status = efi_open_file(volume, &fi, &file, &size);
|
2020-02-10 17:02:43 +01:00
|
|
|
if (status != EFI_SUCCESS)
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
goto err_close_volume;
|
2020-02-10 17:02:43 +01:00
|
|
|
|
|
|
|
/*
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
* Check whether the existing allocation can contain the next
|
|
|
|
* file. This condition will also trigger naturally during the
|
|
|
|
* first (and typically only) iteration of the loop, given that
|
|
|
|
* alloc_size == 0 in that case.
|
2020-02-10 17:02:43 +01:00
|
|
|
*/
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
if (round_up(alloc_size + size, EFI_ALLOC_ALIGN) >
|
|
|
|
round_up(alloc_size, EFI_ALLOC_ALIGN)) {
|
|
|
|
unsigned long old_addr = alloc_addr;
|
|
|
|
|
2020-02-10 17:02:45 +01:00
|
|
|
status = EFI_OUT_OF_RESOURCES;
|
|
|
|
if (soft_limit < hard_limit)
|
|
|
|
status = efi_allocate_pages(alloc_size + size,
|
|
|
|
&alloc_addr,
|
|
|
|
soft_limit);
|
|
|
|
if (status == EFI_OUT_OF_RESOURCES)
|
|
|
|
status = efi_allocate_pages(alloc_size + size,
|
|
|
|
&alloc_addr,
|
|
|
|
hard_limit);
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
if (status != EFI_SUCCESS) {
|
2020-04-30 14:28:35 -04:00
|
|
|
efi_err("Failed to allocate memory for files\n");
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
goto err_close_file;
|
|
|
|
}
|
2020-02-10 17:02:43 +01:00
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
if (old_addr != 0) {
|
|
|
|
/*
|
|
|
|
* This is not the first time we've gone
|
|
|
|
* around this loop, and so we are loading
|
|
|
|
* multiple files that need to be concatenated
|
|
|
|
* and returned in a single buffer.
|
|
|
|
*/
|
|
|
|
memcpy((void *)alloc_addr, (void *)old_addr, alloc_size);
|
|
|
|
efi_free(alloc_size, old_addr);
|
|
|
|
}
|
2020-02-10 17:02:43 +01:00
|
|
|
}
|
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
addr = (void *)alloc_addr + alloc_size;
|
|
|
|
alloc_size += size;
|
2020-02-10 17:02:43 +01:00
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
while (size) {
|
|
|
|
unsigned long chunksize = min(size, efi_chunk_size);
|
|
|
|
|
2022-09-26 22:17:21 +02:00
|
|
|
status = efi_call_proto(file, read, &chunksize, addr);
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
if (status != EFI_SUCCESS) {
|
2020-04-30 14:28:35 -04:00
|
|
|
efi_err("Failed to read file\n");
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
goto err_close_file;
|
|
|
|
}
|
|
|
|
addr += chunksize;
|
|
|
|
size -= chunksize;
|
2020-02-10 17:02:43 +01:00
|
|
|
}
|
2022-09-26 22:17:21 +02:00
|
|
|
efi_call_proto(file, close);
|
|
|
|
efi_call_proto(volume, close);
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
} while (offset > 0);
|
2020-02-10 17:02:43 +01:00
|
|
|
|
2024-10-13 11:20:45 +02:00
|
|
|
if (twopass)
|
|
|
|
goto do_builtin;
|
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
*load_addr = alloc_addr;
|
|
|
|
*load_size = alloc_size;
|
2020-02-10 17:02:43 +01:00
|
|
|
|
2022-09-16 14:03:06 +02:00
|
|
|
if (*load_size == 0)
|
|
|
|
return EFI_NOT_READY;
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
return EFI_SUCCESS;
|
2020-02-10 17:02:43 +01:00
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
err_close_file:
|
2022-09-26 22:17:21 +02:00
|
|
|
efi_call_proto(file, close);
|
2020-02-10 17:02:43 +01:00
|
|
|
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
err_close_volume:
|
2022-09-26 22:17:21 +02:00
|
|
|
efi_call_proto(volume, close);
|
efi: libstub: Implement devicepath support for initrd commandline loader
Currently, the initrd= command line option to the EFI stub only supports
loading files that reside on the same volume as the loaded image, which
is not workable for loaders like GRUB that don't even implement the
volume abstraction (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL), and load the
kernel from an anonymous buffer in memory. For this reason, another
method was devised that relies on the LoadFile2 protocol.
However, the command line loader is rather useful when using the UEFI
shell or other generic loaders that have no awareness of Linux specific
protocols so let's make it a bit more flexible, by permitting textual
device paths to be provided to initrd= as well, provided that they refer
to a file hosted on a EFI_SIMPLE_FILE_SYSTEM_PROTOCOL volume. E.g.,
initrd=PciRoot(0x0)/Pci(0x3,0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)/rootfs.cpio.gz
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2022-09-26 21:32:16 +02:00
|
|
|
|
|
|
|
err_free_alloc:
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
efi_free(alloc_size, alloc_addr);
|
2020-02-10 17:02:43 +01:00
|
|
|
return status;
|
efi/libstub: Rewrite file I/O routine
The file I/O routine that is used to load initrd or dtb files from
the EFI system partition suffers from a few issues:
- it converts the u8[] command line back to a UTF-16 string, which is
pointless since we only handle initrd or dtb arguments provided via
the loaded image protocol anyway, which is where we got the UTF-16[]
command line from in the first place when booting via the PE entry
point,
- in the far majority of cases, only a single initrd= option is present,
but it optimizes for multiple options, by going over the command line
twice, allocating heap buffers for dynamically sized arrays, etc.
- the coding style is hard to follow, with few comments, and all logic
including string parsing etc all combined in a single routine.
Let's fix this by rewriting most of it, based on the idea that in the
case of multiple initrds, we can just allocate a new, bigger buffer
and copy over the data before freeing the old one.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
2020-02-10 17:02:44 +01:00
|
|
|
}
|