@@ -13,6 +13,7 @@
#include <linux/efi.h>
#include <linux/kernel.h>
#include <linux/printk.h> /* For CONSOLE_LOGLEVEL_* */
+#include <linux/cmdline.h>
#include <asm/efi.h>
#include <asm/setup.h>
@@ -339,13 +340,13 @@ void efi_apply_loadoptions_quirk(const void **load_options, int *load_options_si
* Size of memory allocated return in *cmd_line_len.
* Returns NULL on error.
*/
-char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
+char *efi_convert_cmdline(efi_loaded_image_t *image)
{
const u16 *s2;
- unsigned long cmdline_addr = 0;
+ unsigned long cmdline_addr = 0, options_addr = 0;
int options_chars = efi_table_attr(image, load_options_size);
const u16 *options = efi_table_attr(image, load_options);
- int options_bytes = 0, safe_options_bytes = 0; /* UTF-8 bytes */
+ int options_bytes = 0; /* UTF-8 bytes */
bool in_quote = false;
efi_status_t status;
@@ -354,16 +355,12 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
if (options) {
s2 = options;
- while (options_bytes < COMMAND_LINE_SIZE && options_chars--) {
+ while (options_chars--) {
u16 c = *s2++;
if (c < 0x80) {
if (c == L'\0' || c == L'\n')
break;
- if (c == L'"')
- in_quote = !in_quote;
- else if (!in_quote && isspace((char)c))
- safe_options_bytes = options_bytes;
options_bytes++;
continue;
@@ -395,24 +392,30 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
}
}
}
- if (options_bytes >= COMMAND_LINE_SIZE) {
- options_bytes = safe_options_bytes;
- efi_err("Command line is too long: truncated to %d bytes\n",
- options_bytes);
- }
}
options_bytes++; /* NUL termination */
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, options_bytes,
- (void **)&cmdline_addr);
+ (void **)&options_addr);
if (status != EFI_SUCCESS)
return NULL;
- snprintf((char *)cmdline_addr, options_bytes, "%.*ls",
+ snprintf((char *)options_addr, options_bytes, "%.*ls",
options_bytes - 1, options);
- *cmd_line_len = options_bytes;
+ status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, COMMAND_LINE_SIZE,
+ (void **)&cmdline_addr);
+ if (status != EFI_SUCCESS) {
+ efi_bs_call(free_pool, (void *)options_addr);
+ return NULL;
+ }
+
+ if (!__cmdline_build((char *)cmdline_addr, (char *)options_addr))
+ efi_err("Command line is too long\n");
+
+ efi_bs_call(free_pool, (void *)cmdline_addr);
+
return (char *)cmdline_addr;
}
@@ -127,7 +127,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
unsigned long fdt_addr = 0; /* Original DTB */
unsigned long fdt_size = 0;
char *cmdline_ptr = NULL;
- int cmdline_size = 0;
efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
unsigned long reserve_addr = 0;
unsigned long reserve_size = 0;
@@ -165,29 +164,17 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
* protocol. We are going to copy the command line into the
* device tree, so this can be allocated anywhere.
*/
- cmdline_ptr = efi_convert_cmdline(image, &cmdline_size);
+ cmdline_ptr = efi_convert_cmdline(image);
if (!cmdline_ptr) {
efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
status = EFI_OUT_OF_RESOURCES;
goto fail;
}
- if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
- IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
- cmdline_size == 0) {
- status = efi_parse_options(CONFIG_CMDLINE);
- if (status != EFI_SUCCESS) {
- efi_err("Failed to parse options\n");
- goto fail_free_cmdline;
- }
- }
-
- if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) {
- status = efi_parse_options(cmdline_ptr);
- if (status != EFI_SUCCESS) {
- efi_err("Failed to parse options\n");
- goto fail_free_cmdline;
- }
+ status = efi_parse_options(cmdline_ptr);
+ if (status != EFI_SUCCESS) {
+ efi_err("Failed to parse options\n");
+ goto fail_free_cmdline;
}
efi_info("Booting Linux Kernel...\n");
@@ -780,7 +780,7 @@ void efi_free(unsigned long size, unsigned long addr);
void efi_apply_loadoptions_quirk(const void **load_options, int *load_options_size);
-char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len);
+char *efi_convert_cmdline(efi_loaded_image_t *image);
efi_status_t efi_get_memory_map(struct efi_boot_memmap *map);
@@ -359,7 +359,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
struct setup_header *hdr;
void *image_base;
efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
- int options_size = 0;
efi_status_t status;
char *cmdline_ptr;
@@ -404,7 +403,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
hdr->type_of_loader = 0x21;
/* Convert unicode cmdline to ascii */
- cmdline_ptr = efi_convert_cmdline(image, &options_size);
+ cmdline_ptr = efi_convert_cmdline(image);
if (!cmdline_ptr)
goto fail;
@@ -674,6 +673,8 @@ unsigned long efi_main(efi_handle_t handle,
unsigned long buffer_start, buffer_end;
struct setup_header *hdr = &boot_params->hdr;
efi_status_t status;
+ unsigned long cmdline_paddr = ((u64)hdr->cmd_line_ptr |
+ ((u64)boot_params->ext_cmd_line_ptr << 32));
efi_system_table = sys_table_arg;
@@ -735,22 +736,11 @@ unsigned long efi_main(efi_handle_t handle,
image_offset = 0;
}
-#ifdef CONFIG_CMDLINE_BOOL
- status = efi_parse_options(CONFIG_CMDLINE);
+ status = efi_parse_options((char *)cmdline_paddr);
if (status != EFI_SUCCESS) {
efi_err("Failed to parse options\n");
goto fail;
}
-#endif
- if (!IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
- unsigned long cmdline_paddr = ((u64)hdr->cmd_line_ptr |
- ((u64)boot_params->ext_cmd_line_ptr << 32));
- status = efi_parse_options((char *)cmdline_paddr);
- if (status != EFI_SUCCESS) {
- efi_err("Failed to parse options\n");
- goto fail;
- }
- }
/*
* At this point, an initrd may already have been loaded by the
Use cmdline building function in EFI. EFI cannot use pr_err() and doesn't have a .init.data section, so use the __cmdline_build() internal function and provides both a source and a destination. Remove the handling of too long command lines as it is handled by the generic CMDLINE. Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> --- v4: New --- .../firmware/efi/libstub/efi-stub-helper.c | 35 ++++++++++--------- drivers/firmware/efi/libstub/efi-stub.c | 23 +++--------- drivers/firmware/efi/libstub/efistub.h | 2 +- drivers/firmware/efi/libstub/x86-stub.c | 18 +++------- 4 files changed, 29 insertions(+), 49 deletions(-)