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

Reply via email to