content = mfree(content);
/* read the embedded cmdline file */
- err = file_read(linux_dir, f->FileName, offs[SECTION_CMDLINE], szs[SECTION_CMDLINE], &content, NULL);
+ size_t cmdline_len;
+ err = file_read(linux_dir, f->FileName, offs[SECTION_CMDLINE], szs[SECTION_CMDLINE], &content, &cmdline_len);
if (err == EFI_SUCCESS) {
- /* chomp the newline */
- if (content[szs[SECTION_CMDLINE] - 1] == '\n')
- content[szs[SECTION_CMDLINE] - 1] = '\0';
-
- entry->options = xstr8_to_16(content);
+ entry->options = xstrn8_to_16(content, cmdline_len);
+ mangle_stub_cmdline(entry->options);
}
}
}
EFI_STATUS linux_exec(
EFI_HANDLE parent,
- const char *cmdline, UINTN cmdline_len,
- const void *linux_buffer, UINTN linux_length,
- const void *initrd_buffer, UINTN initrd_length) {
+ const char16_t *cmdline,
+ const void *linux_buffer,
+ size_t linux_length,
+ const void *initrd_buffer,
+ size_t initrd_length) {
uint32_t compat_address;
EFI_STATUS err;
assert(parent);
- assert(cmdline || cmdline_len == 0);
assert(linux_buffer && linux_length > 0);
assert(initrd_buffer || initrd_length == 0);
return linux_exec_efi_handover(
parent,
cmdline,
- cmdline_len,
linux_buffer,
linux_length,
initrd_buffer,
return log_error_status_stall(err, u"Error getting kernel loaded image protocol: %r", err);
if (cmdline) {
- loaded_image->LoadOptions = xstrn8_to_16(cmdline, cmdline_len);
+ loaded_image->LoadOptions = (void *) cmdline;
loaded_image->LoadOptionsSize = strsize16(loaded_image->LoadOptions);
}
#pragma once
#include <efi.h>
+#include <uchar.h>
EFI_STATUS linux_exec(
EFI_HANDLE parent,
- const char *cmdline, UINTN cmdline_len,
- const void *linux_buffer, UINTN linux_length,
- const void *initrd_buffer, UINTN initrd_length);
+ const char16_t *cmdline,
+ const void *linux_buffer,
+ size_t linux_length,
+ const void *initrd_buffer,
+ size_t initrd_length);
EFI_STATUS linux_exec_efi_handover(
EFI_HANDLE parent,
- const char *cmdline, UINTN cmdline_len,
- const void *linux_buffer, UINTN linux_length,
- const void *initrd_buffer, UINTN initrd_length);
+ const char16_t *cmdline,
+ const void *linux_buffer,
+ size_t linux_length,
+ const void *initrd_buffer,
+ size_t initrd_length);
EFI_STATUS linux_exec_efi_handover(
EFI_HANDLE parent,
- const char *cmdline, UINTN cmdline_len,
- const void *linux_buffer, UINTN linux_length,
- const void *initrd_buffer, UINTN initrd_length) {
+ const char16_t *cmdline,
+ const void *linux_buffer,
+ size_t linux_length,
+ const void *initrd_buffer,
+ size_t initrd_length) {
assert(parent);
- assert(cmdline || cmdline_len == 0);
assert(linux_buffer);
assert(initrd_buffer || initrd_length == 0);
_cleanup_pages_ Pages cmdline_pages = {};
if (cmdline) {
+ size_t len = MIN(strlen16(cmdline), image_params->hdr.cmdline_size);
+
cmdline_pages = xmalloc_pages(
can_4g ? AllocateAnyPages : AllocateMaxAddress,
EfiLoaderData,
- EFI_SIZE_TO_PAGES(cmdline_len + 1),
+ EFI_SIZE_TO_PAGES(len + 1),
CMDLINE_PTR_MAX);
- memcpy(PHYSICAL_ADDRESS_TO_POINTER(cmdline_pages.addr), cmdline, cmdline_len);
- ((char *) PHYSICAL_ADDRESS_TO_POINTER(cmdline_pages.addr))[cmdline_len] = 0;
+ /* Convert cmdline to ASCII. */
+ char *cmdline8 = PHYSICAL_ADDRESS_TO_POINTER(cmdline_pages.addr);
+ for (size_t i = 0; i < len; i++)
+ cmdline8[i] = cmdline[i] <= 0x7E ? cmdline[i] : ' ';
+ cmdline8[len] = '\0';
+
boot_params->hdr.cmd_line_ptr = (uint32_t) cmdline_pages.addr;
boot_params->ext_cmd_line_ptr = cmdline_pages.addr >> 32;
assert(can_4g || cmdline_pages.addr <= CMDLINE_PTR_MAX);
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
_cleanup_free_ void *credential_initrd = NULL, *global_credential_initrd = NULL, *sysext_initrd = NULL, *pcrsig_initrd = NULL, *pcrpkey_initrd = NULL;
- UINTN credential_initrd_size = 0, global_credential_initrd_size = 0, sysext_initrd_size = 0, pcrsig_initrd_size = 0, pcrpkey_initrd_size = 0;
- UINTN cmdline_len = 0, linux_size, initrd_size, dt_size;
+ size_t credential_initrd_size = 0, global_credential_initrd_size = 0, sysext_initrd_size = 0, pcrsig_initrd_size = 0, pcrpkey_initrd_size = 0;
+ size_t linux_size, initrd_size, dt_size;
EFI_PHYSICAL_ADDRESS linux_base, initrd_base, dt_base;
_cleanup_(devicetree_cleanup) struct devicetree_state dt_state = {};
EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
- UINTN addrs[_UNIFIED_SECTION_MAX] = {}, szs[_UNIFIED_SECTION_MAX] = {};
- char *cmdline = NULL;
- _cleanup_free_ char *cmdline_owned = NULL;
+ size_t addrs[_UNIFIED_SECTION_MAX] = {}, szs[_UNIFIED_SECTION_MAX] = {};
+ _cleanup_free_ char16_t *cmdline = NULL;
int sections_measured = -1, parameters_measured = -1;
bool sysext_measured = false, m;
EFI_STATUS err;
/* Show splash screen as early as possible */
graphics_splash((const uint8_t*) loaded_image->ImageBase + addrs[UNIFIED_SECTION_SPLASH], szs[UNIFIED_SECTION_SPLASH]);
- if (szs[UNIFIED_SECTION_CMDLINE] > 0) {
- cmdline = (char *) loaded_image->ImageBase + addrs[UNIFIED_SECTION_CMDLINE];
- cmdline_len = szs[UNIFIED_SECTION_CMDLINE];
- }
-
/* if we are not in secure boot mode, or none was provided, accept a custom command line and replace
* the built-in one. We also do a superficial check whether first character of passed command line
* is printable character (for compat with some Dell systems which fill in garbage?). */
- if ((!secure_boot_enabled() || cmdline_len == 0) &&
- loaded_image->LoadOptionsSize > 0 &&
+ if ((!secure_boot_enabled() || szs[UNIFIED_SECTION_CMDLINE] == 0) &&
+ loaded_image->LoadOptionsSize > sizeof(char16_t) &&
((char16_t *) loaded_image->LoadOptions)[0] > 0x1F) {
- cmdline_len = (loaded_image->LoadOptionsSize / sizeof(char16_t)) * sizeof(char);
- cmdline = cmdline_owned = xnew(char, cmdline_len);
-
- for (UINTN i = 0; i < cmdline_len; i++) {
- char16_t c = ((char16_t *) loaded_image->LoadOptions)[i];
- cmdline[i] = c > 0x1F && c < 0x7F ? c : ' '; /* convert non-printable and non_ASCII characters to spaces. */
- }
+ /* Note that LoadOptions is a void*, so it could be anything! */
+ cmdline = xstrndup16(
+ loaded_image->LoadOptions, loaded_image->LoadOptionsSize / sizeof(char16_t));
+ mangle_stub_cmdline(cmdline);
/* Let's measure the passed kernel command line into the TPM. Note that this possibly
* duplicates what we already did in the boot menu, if that was already used. However, since
* we want the boot menu to support an EFI binary, and want to this stub to be usable from
* any boot menu, let's measure things anyway. */
m = false;
- (void) tpm_log_load_options(loaded_image->LoadOptions, &m);
+ (void) tpm_log_load_options(cmdline, &m);
parameters_measured = m;
+ } else if (szs[UNIFIED_SECTION_CMDLINE] > 0) {
+ cmdline = xstrn8_to_16(
+ (char *) loaded_image->ImageBase + addrs[UNIFIED_SECTION_CMDLINE],
+ szs[UNIFIED_SECTION_CMDLINE]);
+ mangle_stub_cmdline(cmdline);
}
export_variables(loaded_image);
log_error_stall(L"Error loading embedded devicetree: %r", err);
}
- err = linux_exec(image, cmdline, cmdline_len,
+ err = linux_exec(image, cmdline,
PHYSICAL_ADDRESS_TO_POINTER(linux_base), linux_size,
PHYSICAL_ADDRESS_TO_POINTER(initrd_base), initrd_size);
graphics_mode(false);
return path;
}
+void mangle_stub_cmdline(char16_t *cmdline) {
+ for (; *cmdline != '\0'; cmdline++)
+ /* Convert ASCII control characters to spaces. */
+ if (*cmdline <= 0x1F)
+ *cmdline = ' ';
+}
+
EFI_STATUS file_read(EFI_FILE *dir, const char16_t *name, UINTN off, UINTN size, char **ret, UINTN *ret_size) {
_cleanup_(file_closep) EFI_FILE *handle = NULL;
_cleanup_free_ char *buf = NULL;
void convert_efi_path(char16_t *path);
char16_t *xstr8_to_path(const char *stra);
+void mangle_stub_cmdline(char16_t *cmdline);
EFI_STATUS file_read(EFI_FILE *dir, const char16_t *name, UINTN off, UINTN size, char **content, UINTN *content_size);