From: Nikos Nikoleris <nikos.nikoleris@arm.com>
To: kvm@vger.kernel.org, kvmarm@lists.linux.dev, andrew.jones@linux.dev
Cc: pbonzini@redhat.com, alexandru.elisei@arm.com, ricarkol@google.com
Subject: [PATCH v4 19/30] lib/efi: Add support for getting the cmdline
Date: Mon, 13 Feb 2023 10:17:48 +0000 [thread overview]
Message-ID: <20230213101759.2577077-20-nikos.nikoleris@arm.com> (raw)
In-Reply-To: <20230213101759.2577077-1-nikos.nikoleris@arm.com>
This change adds support for discovering the command line arguments,
as a string. Then, we parse this string to populate __argc and __argv
for EFI tests.
Signed-off-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
---
lib/argv.c | 2 +-
lib/argv.h | 1 +
lib/efi.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/linux/efi.h | 20 ++++++++++
4 files changed, 124 insertions(+), 1 deletion(-)
diff --git a/lib/argv.c b/lib/argv.c
index 9ffa673e..fa5ff9ae 100644
--- a/lib/argv.c
+++ b/lib/argv.c
@@ -41,7 +41,7 @@ void __setup_args(void)
__argc = argv - __argv;
}
-static void setup_args(const char *args)
+void setup_args(const char *args)
{
if (!args)
return;
diff --git a/lib/argv.h b/lib/argv.h
index 1fd746dc..0fa77725 100644
--- a/lib/argv.h
+++ b/lib/argv.h
@@ -9,6 +9,7 @@
#define _ARGV_H_
extern void __setup_args(void);
+extern void setup_args(const char *args);
extern void setup_args_progname(const char *args);
extern void setup_env(char *env, int size);
extern void add_setup_arg(const char *arg);
diff --git a/lib/efi.c b/lib/efi.c
index 64cc9789..f524ec9b 100644
--- a/lib/efi.c
+++ b/lib/efi.c
@@ -8,6 +8,9 @@
*/
#include "efi.h"
+#include <argv.h>
+#include <stdlib.h>
+#include <ctype.h>
#include <libcflat.h>
#include <asm/setup.h>
@@ -96,6 +99,80 @@ static void efi_exit(efi_status_t code)
efi_rs_call(reset_system, EFI_RESET_SHUTDOWN, code, 0, NULL);
}
+/* Adapted from drivers/firmware/efi/libstub/efi-stub.c */
+static char *efi_convert_cmdline(struct efi_loaded_image_64 *image, int *cmd_line_len)
+{
+ const u16 *s2;
+ unsigned long cmdline_addr = 0;
+ int options_chars = image->load_options_size;
+ const u16 *options = image->load_options;
+ int options_bytes = 0, safe_options_bytes = 0; /* UTF-8 bytes */
+ bool in_quote = false;
+ efi_status_t status;
+ const int COMMAND_LINE_SIZE = 2048;
+
+ if (options) {
+ s2 = options;
+ while (options_bytes < COMMAND_LINE_SIZE && 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;
+ }
+
+ /*
+ * Get the number of UTF-8 bytes corresponding to a
+ * UTF-16 character.
+ * The first part handles everything in the BMP.
+ */
+ options_bytes += 2 + (c >= 0x800);
+ /*
+ * Add one more byte for valid surrogate pairs. Invalid
+ * surrogates will be replaced with 0xfffd and take up
+ * only 3 bytes.
+ */
+ if ((c & 0xfc00) == 0xd800) {
+ /*
+ * If the very last word is a high surrogate,
+ * we must ignore it since we can't access the
+ * low surrogate.
+ */
+ if (!options_chars) {
+ options_bytes -= 3;
+ } else if ((*s2 & 0xfc00) == 0xdc00) {
+ options_bytes++;
+ options_chars--;
+ s2++;
+ }
+ }
+ }
+ if (options_bytes >= COMMAND_LINE_SIZE) {
+ options_bytes = safe_options_bytes;
+ printf("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);
+ if (status != EFI_SUCCESS)
+ return NULL;
+
+ snprintf((char *)cmdline_addr, options_bytes, "%.*ls", options_bytes - 1, options);
+
+ *cmd_line_len = options_bytes;
+ return (char *)cmdline_addr;
+}
+
efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab)
{
int ret;
@@ -109,6 +186,31 @@ efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab)
unsigned long map_size = 0, desc_size = 0, key = 0, buff_size = 0;
u32 desc_ver;
+ /* Helper variables needed to get the cmdline */
+ struct efi_loaded_image_64 *image;
+ efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
+ char *cmdline_ptr = NULL;
+ int cmdline_size = 0;
+
+ /*
+ * Get a handle to the loaded image protocol. This is used to get
+ * information about the running image, such as size and the command
+ * line.
+ */
+ status = efi_bs_call(handle_protocol, handle, &loaded_image_proto, (void *)&image);
+ if (status != EFI_SUCCESS) {
+ printf("Failed to get loaded image protocol\n");
+ goto efi_main_error;
+ }
+
+ cmdline_ptr = efi_convert_cmdline(image, &cmdline_size);
+ if (!cmdline_ptr) {
+ printf("getting command line via LOADED_IMAGE_PROTOCOL\n");
+ status = EFI_OUT_OF_RESOURCES;
+ goto efi_main_error;
+ }
+ setup_args(cmdline_ptr);
+
/* Set up efi_bootinfo */
efi_bootinfo.mem_map.map = ↦
efi_bootinfo.mem_map.map_size = &map_size;
diff --git a/lib/linux/efi.h b/lib/linux/efi.h
index 455625aa..9a1cf87b 100644
--- a/lib/linux/efi.h
+++ b/lib/linux/efi.h
@@ -60,6 +60,8 @@ typedef guid_t efi_guid_t;
#define ACPI_TABLE_GUID EFI_GUID(0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+#define LOADED_IMAGE_PROTOCOL_GUID EFI_GUID(0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
typedef struct {
efi_guid_t guid;
void *table;
@@ -416,6 +418,24 @@ struct efi_boot_memmap {
unsigned long *buff_size;
};
+#define __aligned_u64 u64 __attribute__((aligned(8)))
+
+struct efi_loaded_image_64 {
+ u32 revision;
+ efi_handle_t parent_handle;
+ efi_system_table_t *system_table;
+ efi_handle_t device_handle;
+ void *file_path;
+ void *reserved;
+ u32 load_options_size;
+ void *load_options;
+ void *image_base;
+ __aligned_u64 image_size;
+ unsigned int image_code_type;
+ unsigned int image_data_type;
+ efi_status_t (__efiapi * unload)(efi_handle_t image_handle);
+};
+
#define efi_bs_call(func, ...) efi_system_table->boottime->func(__VA_ARGS__)
#define efi_rs_call(func, ...) efi_system_table->runtime->func(__VA_ARGS__)
--
2.25.1
next prev parent reply other threads:[~2023-02-13 10:18 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-13 10:17 [PATCH v4 00/30] EFI and ACPI support for arm64 Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 01/30] lib: Move acpi header and implementation to lib Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 02/30] x86: Move x86_64-specific EFI CFLAGS to x86_64 Makefile Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 03/30] arm/Makefile.common: Compile lib/acpi.c if CONFIG_EFI=y Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 04/30] lib: Apply Lindent to acpi.{c,h} Nikos Nikoleris
2023-03-09 7:11 ` Shaoqin Huang
2023-03-21 17:32 ` Andrew Jones
2023-03-22 10:05 ` Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 05/30] lib: Fix style for acpi.{c,h} Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 06/30] lib/acpi: Convert table names to Linux style Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 07/30] x86: Avoid references to fields of ACPI tables Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 08/30] lib/acpi: Ensure all struct definition for ACPI tables are packed Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 09/30] lib/acpi: Add support for the XSDT table Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 10/30] lib/acpi: Extend the definition of the FADT table Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 11/30] devicetree: Check that fdt is not NULL in dt_available() Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 12/30] arm64: Add support for setting up the PSCI conduit through ACPI Nikos Nikoleris
2023-03-21 17:31 ` Andrew Jones
2023-02-13 10:17 ` [PATCH v4 13/30] arm64: Add support for discovering the UART " Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 14/30] arm64: Add support for timer initialization " Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 15/30] arm64: Add support for cpu " Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 16/30] arm64: Add support for gic " Nikos Nikoleris
2023-03-30 6:46 ` Shaoqin Huang
2023-02-13 10:17 ` [PATCH v4 17/30] lib/printf: Support for precision modifier in printf Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 18/30] lib/printf: Add support for printing wide strings Nikos Nikoleris
2023-02-13 10:17 ` Nikos Nikoleris [this message]
2023-02-13 10:17 ` [PATCH v4 20/30] arm/arm64: Rename etext to _etext Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 21/30] lib: Avoid ms_abi for calls related to EFI on arm64 Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 22/30] arm64: Add a new type of memory type flag MR_F_RESERVED Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 23/30] arm64: Add a setup sequence for systems that boot through EFI Nikos Nikoleris
2023-04-25 7:04 ` Shaoqin Huang
2023-04-25 9:09 ` Nikos Nikoleris
2023-04-25 18:31 ` Andrew Jones
2023-02-13 10:17 ` [PATCH v4 24/30] arm64: Copy code from GNU-EFI Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 25/30] arm64: Change GNU-EFI imported code to use defined types Nikos Nikoleris
2023-03-30 6:49 ` Shaoqin Huang
2023-02-13 10:17 ` [PATCH v4 26/30] arm64: Use code from the gnu-efi when booting with EFI Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 27/30] lib: Avoid external dependency in libelf Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 28/30] arm64: Add support for efi in Makefile Nikos Nikoleris
2023-03-21 18:21 ` Andrew Jones
2023-02-13 10:17 ` [PATCH v4 29/30] lib: arm: Print test exit status Nikos Nikoleris
2023-02-13 10:17 ` [PATCH v4 30/30] arm64: Add an efi/run script Nikos Nikoleris
2023-03-21 18:41 ` Andrew Jones
2023-03-22 10:02 ` Nikos Nikoleris
2023-03-22 11:24 ` Andrew Jones
2023-03-22 11:57 ` Nikos Nikoleris
2023-03-22 12:32 ` Andrew Jones
2023-03-22 19:09 ` Nikos Nikoleris
2023-03-23 17:52 ` Andrew Jones
2023-03-28 9:03 ` Alexandru Elisei
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230213101759.2577077-20-nikos.nikoleris@arm.com \
--to=nikos.nikoleris@arm.com \
--cc=alexandru.elisei@arm.com \
--cc=andrew.jones@linux.dev \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=pbonzini@redhat.com \
--cc=ricarkol@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.