[ipxe-devel] [PATCH] [efi] Use EFI command line as script
Ladi Prosek
lprosek at redhat.com
Fri Sep 8 12:00:29 UTC 2017
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 <lprosek at redhat.com>
---
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
More information about the ipxe-devel
mailing list