All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ricardo Koller <ricarkol@google.com>
To: Nikos Nikoleris <nikos.nikoleris@arm.com>
Cc: kvm@vger.kernel.org, drjones@redhat.com, pbonzini@redhat.com,
	jade.alglave@arm.com, alexandru.elisei@arm.com
Subject: Re: [kvm-unit-tests PATCH v2 11/23] lib/efi: Add support for getting the cmdline
Date: Tue, 21 Jun 2022 09:33:41 -0700	[thread overview]
Message-ID: <YrHy5TLGLHkAYfzy@google.com> (raw)
In-Reply-To: <20220506205605.359830-12-nikos.nikoleris@arm.com>

On Fri, May 06, 2022 at 09:55:53PM +0100, Nikos Nikoleris wrote:
> 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/linux/efi.h |  39 +++++++++++++++
>  lib/stdlib.h    |   1 +
>  lib/efi.c       | 123 ++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/string.c    |   2 +-
>  4 files changed, 164 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/linux/efi.h b/lib/linux/efi.h
> index 455625a..e3aba1d 100644
> --- a/lib/linux/efi.h
> +++ b/lib/linux/efi.h
> @@ -60,6 +60,10 @@ 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)
> +
> +#define efi_table_attr(inst, attr) (inst->attr)
> +
>  typedef struct {
>  	efi_guid_t guid;
>  	void *table;
> @@ -416,6 +420,41 @@ struct efi_boot_memmap {
>  	unsigned long           *buff_size;
>  };
>  
> +#define __aligned_u64 u64 __attribute__((aligned(8)))
> +
> +typedef union {
> +	struct {
> +		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);
> +	};
> +	struct {
> +		u32		revision;
> +		u32		parent_handle;
> +		u32		system_table;
> +		u32		device_handle;
> +		u32		file_path;
> +		u32		reserved;
> +		u32		load_options_size;
> +		u32		load_options;
> +		u32		image_base;
> +		__aligned_u64	image_size;
> +		u32		image_code_type;
> +		u32		image_data_type;
> +		u32		unload;
> +	} mixed_mode;
> +} efi_loaded_image_t;

Is the 32-bit mode used (in later commits)? Why not reuse
efi_loaded_image_64_t only and make sure it's the one expected.

> +
>  #define efi_bs_call(func, ...) efi_system_table->boottime->func(__VA_ARGS__)
>  #define efi_rs_call(func, ...) efi_system_table->runtime->func(__VA_ARGS__)
>  
> diff --git a/lib/stdlib.h b/lib/stdlib.h
> index 28496d7..2c524d7 100644
> --- a/lib/stdlib.h
> +++ b/lib/stdlib.h
> @@ -7,6 +7,7 @@
>  #ifndef _STDLIB_H_
>  #define _STDLIB_H_
>  
> +int isspace(int c);
>  long int strtol(const char *nptr, char **endptr, int base);
>  unsigned long int strtoul(const char *nptr, char **endptr, int base);
>  long long int strtoll(const char *nptr, char **endptr, int base);
> diff --git a/lib/efi.c b/lib/efi.c
> index 64cc978..5341942 100644
> --- a/lib/efi.c
> +++ b/lib/efi.c
> @@ -8,6 +8,7 @@
>   */
>  
>  #include "efi.h"
> +#include <stdlib.h>
>  #include <libcflat.h>
>  #include <asm/setup.h>
>  
> @@ -96,6 +97,97 @@ static void efi_exit(efi_status_t code)
>  	efi_rs_call(reset_system, EFI_RESET_SHUTDOWN, code, 0, NULL);
>  }
>  
> +static void efi_cmdline_to_argv(char *cmdline_ptr)
> +{
> +	char *c = cmdline_ptr;
> +	bool narg = true;
> +	while (*c) {
> +		if (isspace(*c)) {
> +			*c = '\0';
> +			narg = true;
> +		} else if (narg) {
> +			__argv[__argc++] = c;
> +			narg = false;
> +		}
> +		c++;
> +	}
> +}
> +
> +static char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)

Mention that this was adapted from drivers/firmware/efi/libstub/efi-stub.c.

> +{
> +	const u16 *s2;
> +	unsigned long cmdline_addr = 0;
> +	int options_chars = efi_table_attr(image, load_options_size) / 2;
> +	const u16 *options = efi_table_attr(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 +201,37 @@ 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 */
> +	efi_loaded_image_t *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;
> +	}
> +
> +	/*
> +	 * Get the command line from EFI, using the LOADED_IMAGE
> +	 * protocol. We are going to copy the command line into the
> +	 * device tree, so this can be allocated anywhere.

Does the "device tree" comment still make sense?

> +	 */
> +	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;
> +	}
> +	efi_cmdline_to_argv(cmdline_ptr);
> +
>  	/* Set up efi_bootinfo */
>  	efi_bootinfo.mem_map.map = &map;
>  	efi_bootinfo.mem_map.map_size = &map_size;
> diff --git a/lib/string.c b/lib/string.c
> index 27106da..b191ab1 100644
> --- a/lib/string.c
> +++ b/lib/string.c
> @@ -163,7 +163,7 @@ void *memchr(const void *s, int c, size_t n)
>      return NULL;
>  }
>  
> -static int isspace(int c)
> +int isspace(int c)
>  {
>      return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\v' || c == '\f';
>  }
> -- 
> 2.25.1
> 

  reply	other threads:[~2022-06-21 16:33 UTC|newest]

Thread overview: 72+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-06 20:55 [kvm-unit-tests PATCH v2 00/23] EFI and ACPI support for arm64 Nikos Nikoleris
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 01/23] lib: Move acpi header and implementation to lib Nikos Nikoleris
2022-05-19 13:21   ` Andrew Jones
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 02/23] lib: Ensure all struct definition for ACPI tables are packed Nikos Nikoleris
2022-05-19 13:17   ` Andrew Jones
2022-05-19 15:52     ` Nikos Nikoleris
2022-05-19 17:14       ` Andrew Jones
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 03/23] lib: Add support for the XSDT ACPI table Nikos Nikoleris
2022-05-19 13:30   ` Andrew Jones
2022-06-18  0:38   ` Ricardo Koller
2022-06-20  8:53     ` Alexandru Elisei
2022-06-20 11:06       ` Nikos Nikoleris
2022-06-21 12:25         ` Alexandru Elisei
2022-06-21 11:26     ` Nikos Nikoleris
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 04/23] lib: Extend the definition of the ACPI table FADT Nikos Nikoleris
2022-05-19 13:42   ` Andrew Jones
2022-06-18  1:00   ` Ricardo Koller
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 05/23] arm/arm64: Add support for setting up the PSCI conduit through ACPI Nikos Nikoleris
2022-05-19 13:54   ` Andrew Jones
2022-06-21 16:06   ` Ricardo Koller
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 06/23] arm/arm64: Add support for discovering the UART " Nikos Nikoleris
2022-05-19 13:59   ` Andrew Jones
2022-06-21 16:07   ` Ricardo Koller
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 07/23] arm/arm64: Add support for timer initialization " Nikos Nikoleris
2022-05-19 14:10   ` Andrew Jones
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 08/23] arm/arm64: Add support for cpu " Nikos Nikoleris
2022-05-19 14:23   ` Andrew Jones
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 09/23] lib/printf: Support for precision modifier in printing strings Nikos Nikoleris
2022-05-19 14:52   ` Andrew Jones
2022-05-19 16:02     ` Andrew Jones
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 10/23] lib/printf: Add support for printing wide strings Nikos Nikoleris
2022-06-21 16:11   ` Ricardo Koller
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 11/23] lib/efi: Add support for getting the cmdline Nikos Nikoleris
2022-06-21 16:33   ` Ricardo Koller [this message]
2022-06-27 16:12     ` Nikos Nikoleris
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 12/23] arm/arm64: mmu_disable: Clean and invalidate before disabling Nikos Nikoleris
2022-05-13 13:15   ` Alexandru Elisei
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 13/23] arm/arm64: Rename etext to _etext Nikos Nikoleris
2022-06-21 16:42   ` Ricardo Koller
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 14/23] lib: Avoid ms_abi for calls related to EFI on arm64 Nikos Nikoleris
2022-05-20 14:02   ` Andrew Jones
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 15/23] arm64: Add a new type of memory type flag MR_F_RESERVED Nikos Nikoleris
2022-06-21 16:44   ` Ricardo Koller
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 16/23] arm/arm64: Add a setup sequence for systems that boot through EFI Nikos Nikoleris
2022-05-13 13:31   ` Alexandru Elisei
2022-06-27 16:36     ` Nikos Nikoleris
2022-05-06 20:55 ` [kvm-unit-tests PATCH v2 17/23] arm64: Copy code from GNU-EFI Nikos Nikoleris
2022-06-21 17:59   ` Ricardo Koller
2022-05-06 20:56 ` [kvm-unit-tests PATCH v2 18/23] arm64: Change gnu-efi imported file to use defined types Nikos Nikoleris
2022-05-06 20:56 ` [kvm-unit-tests PATCH v2 19/23] arm64: Use code from the gnu-efi when booting with EFI Nikos Nikoleris
2022-06-21 22:32   ` Ricardo Koller
2022-06-27 17:10     ` Nikos Nikoleris
2022-06-30  5:13       ` Ricardo Koller
2022-05-06 20:56 ` [kvm-unit-tests PATCH v2 20/23] lib: Avoid external dependency in libelf Nikos Nikoleris
2022-06-21 22:39   ` Ricardo Koller
2022-05-06 20:56 ` [kvm-unit-tests PATCH v2 21/23] x86: Move x86_64-specific EFI CFLAGS to x86_64 Makefile Nikos Nikoleris
2022-06-21 22:45   ` Ricardo Koller
2022-06-22 13:47     ` Nikos Nikoleris
2022-05-06 20:56 ` [kvm-unit-tests PATCH v2 22/23] arm64: Add support for efi in Makefile Nikos Nikoleris
2022-06-21 22:51   ` Ricardo Koller
2022-06-22 13:52     ` Nikos Nikoleris
2022-06-21 22:52   ` Ricardo Koller
2022-05-06 20:56 ` [kvm-unit-tests PATCH v2 23/23] arm64: Add an efi/run script Nikos Nikoleris
2022-06-21 23:09   ` Ricardo Koller
2022-06-22 14:13     ` Nikos Nikoleris
2022-06-30  5:22       ` Ricardo Koller
2022-05-13 14:09 ` [kvm-unit-tests PATCH v2 00/23] EFI and ACPI support for arm64 Alexandru Elisei
2022-05-18  9:00   ` Nikos Nikoleris
2022-05-20  9:58     ` Alexandru Elisei
2022-05-17 17:56 ` Ricardo Koller
2022-05-18 12:44   ` Nikos Nikoleris
2022-05-18 16:10     ` Ricardo Koller

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=YrHy5TLGLHkAYfzy@google.com \
    --to=ricarkol@google.com \
    --cc=alexandru.elisei@arm.com \
    --cc=drjones@redhat.com \
    --cc=jade.alglave@arm.com \
    --cc=kvm@vger.kernel.org \
    --cc=nikos.nikoleris@arm.com \
    --cc=pbonzini@redhat.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.