[ipxe-devel] [PATCH] wimboot syslinux kludge 3/4: support for cpio initrd for efi

Friedemann Gerold f.gerold at b-c-s.de
Fri Nov 2 14:25:06 UTC 2018


When syslinux starts wimboot as a linux kernel, the filesyststem
comes in as a cpio initrd instead of being available as efi filesystem
protocol. This patch changes efimain to save a pointer to the
initrd when coming from efi_linuxenty() and extracts the initrd
as a cpio archive just as with legacy. The patch depends on the
previous patch that added the common read_mem_file() function to
vdisk.c.

The cpio file handler efi_add_file() has been added.

The patching logic from efi_extract() file loop body is moved in a
common addfile() function in efifile.c to be shared by efi_extract()
and efi_add_file().

helper function isbootmgfw() is added to deal with the byte string
vs wide string comparsion of efi_bootarch().

added strlen(name) > 4 check before testing the file extension.

Signed-off-by: Friedemann Gerold <f.gerold at b-c-s.de>
---
--- wimboot/src/efimain.c.1	2018-11-02 13:43:01.737251269 +0100
+++ wimboot/src/efimain.c	2018-11-02 13:43:10.549294966 +0100
@@ -32,6 +32,15 @@
  #include "efiblock.h"
  #include "efiboot.h"

+#include "string.h"
+#include "cpio.h"
+
+/** initrd */
+void *initrd;
+
+/** Length of initrd */
+size_t initrd_len;
+
  /**
   * Process command line
   *
@@ -88,8 +97,13 @@
  	/* Process command line */
  	efi_cmdline ( loaded.image );

-	/* Extract files from file system */
-	efi_extract ( loaded.image->DeviceHandle );
+	if(initrd_len){
+		/* Extract files from initrd (syslinux) */
+		cpio_extract ( initrd, initrd_len, efi_add_file );
+	} else {
+		/* Extract files from file system */
+		efi_extract ( loaded.image->DeviceHandle );
+	}

  	/* Install virtual disk */
  	efi_install ( &vdisk, &vpartition );
@@ -112,6 +126,11 @@
  	memset(_bss, 0, _ebss-_bss);
  #endif

+	if(bp){
+		initrd = (void*)(intptr_t)bp[0x218/4];
+		initrd_len = (size_t)bp[0x21c/4];
+	}
+
  	efi_main(image_handle, systab);
  }

--- wimbootorig/src/efifile.c	2018-11-02 12:29:14.343297008 +0100
+++ wimboot/src/efifile.c	2018-11-02 15:15:03.640632910 +0100
@@ -117,6 +117,61 @@
  	}
  }

+static int
+isbootmgfw( const char *name)
+{
+	char bootarch[32];
+
+	if (strcasecmp(name, "bootmgfw.efi") == 0)
+		return 1;
+	snprintf ( bootarch, sizeof ( bootarch ), "%ls", efi_bootarch() );
+	return strcasecmp(name, bootarch) == 0;
+}
+
+static int
+addfile( const char *name, void *data, size_t len,  void ( * read ) ( struct vdisk_file *file,
+                                                       void *data,
+                                                       size_t offset,
+                                                       size_t len ) ) {
+	struct vdisk_file *vfile;
+
+	vfile = vdisk_add_file ( name, data, len, read );
+
+        /* Check for special-case files */
+	if ( isbootmgfw( name ) ) {
+		DBG ( "...found bootmgfw.efi file %s\n", name );
+		bootmgfw = vfile;
+	} else if ( strcasecmp ( name, "BCD" ) == 0 ) {
+		DBG ( "...found BCD\n" );
+		vdisk_patch_file ( vfile, efi_patch_bcd );
+	} else if ( strlen( name ) > 4 && strcasecmp ( ( name + ( strlen ( name ) - 4 ) ), ".wim" ) == 0 ) {
+		DBG ( "...found WIM file %s\n", name );
+		vdisk_patch_file ( vfile, patch_wim );
+		if ( ( ! bootmgfw ) &&
+		     ( bootmgfw = wim_add_file ( vfile, cmdline_index,
+                                                         bootmgfw_path,
+                                                         efi_bootarch() ) ) ) {
+			DBG ( "...extracted %ls\n", bootmgfw_path );
+		}
+	}
+	return 0;
+}
+
+/**
+ * File handler
+ *
+ * @v name              File name
+ * @v data              File data
+ * @v len               Length
+ * @ret rc              Return status code
+ */
+int
+efi_add_file ( const char *name, void *data, size_t len)
+{
+	return addfile(name, data, len, read_mem_file);
+}
+
+
  /**
   * Extract files from EFI file system
   *
@@ -133,7 +188,6 @@
  		CHAR16 name[ VDISK_NAME_LEN + 1 /* WNUL */ ];
  	} __attribute__ (( packed )) info;
  	char name[ VDISK_NAME_LEN + 1 /* NUL */ ];
-	struct vdisk_file *vfile;
  	EFI_FILE_PROTOCOL *root;
  	EFI_FILE_PROTOCOL *file;
  	UINTN size;
@@ -186,28 +240,7 @@

  		/* Add file */
  		snprintf ( name, sizeof ( name ), "%ls", wname );
-		vfile = vdisk_add_file ( name, file, info.file.FileSize,
-					 efi_read_file );
-
-		/* Check for special-case files */
-		if ( ( wcscasecmp ( wname, efi_bootarch() ) == 0 ) ||
-		     ( wcscasecmp ( wname, L"bootmgfw.efi" ) == 0 ) ) {
-			DBG ( "...found bootmgfw.efi file %ls\n", wname );
-			bootmgfw = vfile;
-		} else if ( wcscasecmp ( wname, L"BCD" ) == 0 ) {
-			DBG ( "...found BCD\n" );
-			vdisk_patch_file ( vfile, efi_patch_bcd );
-		} else if ( wcscasecmp ( ( wname + ( wcslen ( wname ) - 4 ) ),
-					 L".wim" ) == 0 ) {
-			DBG ( "...found WIM file %ls\n", wname );
-			vdisk_patch_file ( vfile, patch_wim );
-			if ( ( ! bootmgfw ) &&
-			     ( bootmgfw = wim_add_file ( vfile, cmdline_index,
-							 bootmgfw_path,
-							 efi_bootarch() ) ) ) {
-				DBG ( "...extracted %ls\n", bootmgfw_path );
-			}
-		}
+		addfile(name, file, info.file.FileSize, efi_read_file);
  	}

  	/* Check that we have a boot file */




More information about the ipxe-devel mailing list