Analogous to passing a script to ipxe.lkrn via kernel parameters, this patch enables the same on EFI using the EFI command line, available in the LoadOptions field of EFI_LOADED_IMAGE_PROTOCOL.
Signed-off-by: Ladi Prosek <[email protected]> --- src/interface/efi/efi_init.c | 92 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/interface/efi/efi_init.c b/src/interface/efi/efi_init.c index ed9707f..fb90816 100644 --- a/src/interface/efi/efi_init.c +++ b/src/interface/efi/efi_init.c @@ -21,7 +21,12 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <string.h> #include <errno.h> +#include <stdlib.h> +#include <wchar.h> +#include <ctype.h> #include <ipxe/init.h> +#include <ipxe/image.h> +#include <ipxe/script.h> #include <ipxe/efi/efi.h> #include <ipxe/efi/efi_driver.h> #include <ipxe/efi/Protocol/LoadedImage.h> @@ -240,3 +245,90 @@ static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle __unused ) { return 0; } + +/** Internal copy of the command line */ +static char *cmdline_copy; + +/** Free command line image */ +static void cmdline_image_free ( struct refcnt *refcnt ) { + struct image *image = container_of ( refcnt, struct image, refcnt ); + + DBGC ( image, "EFI freeing command line\n" ); + free ( cmdline_copy ); +} + +/** Embedded script representing the command line */ +static struct image cmdline_image = { + .refcnt = REF_INIT ( cmdline_image_free ), + .name = "<CMDLINE>", + .type = &script_image_type, +}; + +static int efi_cmdline_init ( EFI_LOADED_IMAGE_PROTOCOL *image ) { + wchar_t *load_options; + char *cmdline; + unsigned i; + int rc; + + /* Get command line */ + if ( image->LoadOptionsSize ) { + load_options = ( wchar_t * ) image->LoadOptions; + cmdline_copy = malloc ( image->LoadOptionsSize + 1 ); + if ( ! cmdline_copy ) { + DBGC ( image, "EFI could not allocate command line\n" ); + rc = -ENOMEM; + goto err_alloc_cmdline_copy; + } + + for ( i = 0 ; i < efi_loaded_image->LoadOptionsSize ; i++ ) { + wcrtomb ( cmdline_copy + i, load_options [ i ], NULL ); + } + cmdline_copy[i] = 0; + cmdline = cmdline_copy; + + /* Skip the first parameter (image name) */ + while ( isspace ( *cmdline ) ) + cmdline++; + while ( *cmdline && ! isspace ( *cmdline ) ) + cmdline++; + while ( isspace ( *cmdline ) ) + cmdline++; + + cmdline_image.len = strlen ( cmdline ); + cmdline_image.data = virt_to_user ( cmdline ); + + if ( cmdline_image.len ) { + DBGC ( image, "EFI got cmdline of length %zd\n", + cmdline_image.len ); + + if ( ( rc = register_image ( &cmdline_image ) ) != 0 ) { + DBGC ( image, "EFI could not register command " + "line: %s\n", strerror ( rc ) ); + goto err_register_image; + } + } + /* Drop our reference to the image */ + image_put ( &cmdline_image ); + } + + return 0; + + err_register_image: + image_put ( &cmdline_image ); + err_alloc_cmdline_copy: + return rc; +} + +/** + * EFI initialization that cannot be done in efi_init (e.g. because it allocates). + */ +static void efi_startup ( void ) { + if ( efi_cmdline_init ( efi_loaded_image ) != 0 ) { + /* No way to report failure */ + return; + } +} + +struct startup_fn efi_runtime_startup_fn __startup_fn ( STARTUP_NORMAL ) = { + .startup = efi_startup, +}; -- 2.9.3 _______________________________________________ ipxe-devel mailing list [email protected] https://lists.ipxe.org/mailman/listinfo.cgi/ipxe-devel

