[ipxe-devel] win10 bootmgr

Earl Chew earl_chew at yahoo.com
Tue Oct 13 01:58:58 UTC 2015


On 11/10/2015 09:30, Earl Chew wrote:
> The approach taken in bmzip.cpp is to find the archive signatures
> "BMCI" or "BMXH" that delineate its contents, rather than find
> the signatures of the target compression format.

Here is an attempt at getting this to work. With these changes
wimboot can find win10 bootmgr.exe and I can boot successfully.

Earl


commit 54b0d6dafcb1aca5f7de676061ae66bb3bdc5d25
Author: Earl Chew <earl_chew at yahoo.com>
Date:   Sun Oct 11 19:22:39 2015 -0700

     [Makefile] Remove dependency on -liberty

     Per 40a9a0f097d87252f2b4f3cd884c9261b1d3d1e8 from ipxe.git,
     remove the now unnecessary dependency on -liberty.

     Signed-off-by: Earl Chew <earl_chew at yahoo.com>

diff --git a/src/Makefile b/src/Makefile
index bc71205..6d00713 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -142,7 +142,7 @@ lib.x86_64.a : $(OBJECTS_x86_64) 
$(OBJECTS_i386_x86_64) Makefile
  EFIRELOC_CFLAGS := -I$(BINUTILS_DIR)/include -I$(BFD_DIR)/include \
  		   -I$(ZLIB_DIR)/include -idirafter .
  EFIRELOC_LDFLAGS := -L$(BINUTILS_DIR)/lib -L$(BFD_DIR)/lib 
-L$(ZLIB_DIR)/lib \
-		    -lbfd -ldl -liberty -lz -Wl,--no-warn-search-mismatch
+		    -lbfd -ldl -lz -Wl,--no-warn-search-mismatch

  efireloc : efireloc.c Makefile
  	$(CC) $(HOST_CFLAGS) $(EFIRELOC_CFLAGS) $< $(EFIRELOC_LDFLAGS) -o $@

commit 722822c9a1d7b0669bc7f29b564e56efe9c98ac4
Author: Earl Chew <earl_chew at yahoo.com>
Date:   Sun Oct 11 22:01:56 2015 -0700

     [main] Use archive header to search for compressed image

     Signed-off-by: Earl Chew <earl_chew at yahoo.com>

diff --git a/src/main.c b/src/main.c
index a98fdd7..2c030ec 100644
--- a/src/main.c
+++ b/src/main.c
@@ -63,8 +63,13 @@ static const wchar_t bootmgr_path[] = 
L"\\Windows\\Boot\\PXE\\bootmgr.exe";
  /** bootmgr.exe file */
  static struct vdisk_file *bootmgr;

-/** Minimal length of embedded bootmgr.exe */
-#define BOOTMGR_MIN_LEN 16384
+/** bootmgr archive entry */
+struct bootmgr_entry {
+	uint32_t signature;
+	uint32_t compressed_size;
+	uint32_t uncompressed_size;
+	uint32_t offset;
+} __attribute__ (( packed ));

  /** Memory regions */
  enum {
@@ -185,18 +190,6 @@ static struct {
  };

  /**
- * Test if a paragraph is empty
- *
- * @v pgh		Paragraph
- * @ret is_empty	Paragraph is empty (all zeroes)
- */
-static int is_empty_pgh ( const void *pgh ) {
-	const uint32_t *dwords = pgh;
-
-	return ( ( dwords[0] | dwords[1] | dwords[2] | dwords[3] ) == 0 );
-}
-
-/**
   * Read from file
   *
   * @v file		Virtual file
@@ -211,6 +204,32 @@ static void read_file ( struct vdisk_file *file, 
void *data, size_t offset,
  }

  /**
+ * Find in memory buffer
+ *
+ * @v string		String to find
+ * @v data		Buffer
+ * @v len		Length
+ * @ret buffer  	Pointer to string or end of buffer
+ */
+static const void * find ( const char *text, const char *data, size_t 
len ) {
+
+	size_t offset;
+	size_t textlen;
+
+	textlen = strlen(text);
+        if ( textlen <= len) {
+		for ( offset = 0; offset < len - textlen; ++offset ) {
+			if (text[0] != data[offset] )
+				continue;
+			if (memcmp(text, data + offset, textlen))
+				continue;
+			return data + offset;
+                }
+	}
+	return data + len;
+}
+
+/**
   * Add embedded bootmgr.exe extracted from bootmgr
   *
   * @v data		File data
@@ -233,57 +252,54 @@ static struct vdisk_file * add_bootmgr ( const 
void *data, size_t len ) {
  	ssize_t ( * decompress ) ( const void *data, size_t len, void *buf );
  	ssize_t decompressed_len;
  	size_t padded_len;
+        struct bootmgr_entry bmentry;
+        const void *bmcip, *bmxhp, *bmzip;

-	/* Look for an embedded compressed bootmgr.exe on a paragraph
-	 * boundary.
+	/* Look for an embedded compressed bootmgr.exe by searching
+         * for components stored within the compressed image.
  	 */
-	for ( offset = BOOTMGR_MIN_LEN ; offset < ( len - BOOTMGR_MIN_LEN ) ;
-	      offset += 0x10 ) {
+        offset = 0;
+        if ( len <= sizeof( bmentry ) )
+		len = sizeof( bmentry );
+
+        while ( offset < len - sizeof( bmentry ) ) {

-		/* Initialise checks */
  		decompress = NULL;
-		compressed = ( data + offset );
-		compressed_len = ( len - offset );
-
-		/* Check for an embedded LZNT1-compressed bootmgr.exe.
-		 * Since there is no way for LZNT1 to compress the
-		 * initial "MZ" bytes of bootmgr.exe, we look for this
-		 * signature starting three bytes after a paragraph
-		 * boundary, with a preceding tag byte indicating that
-		 * these two bytes would indeed be uncompressed.
-		 */
-		if ( ( ( compressed[0x02] & 0x03 ) == 0x00 ) &&
-		     ( compressed[0x03] == 'M' ) &&
-		     ( compressed[0x04] == 'Z' ) ) {
+
+		bmcip = find ( "BMCI", data + offset, len - offset );
+		bmxhp = find ( "BMXH", data + offset, len - offset );
+
+		bmzip = bmcip < bmxhp ? bmcip : bmxhp;
+
+		if ( bmzip == data + len )
+			break;
+
+                memcpy( &bmentry, bmzip, sizeof( bmentry ) );
+		compressed = bmzip + bmentry.offset;
+		compressed_len = bmentry.compressed_size;
+		offset = bmzip + bmentry.offset - data;
+
+		DBG ( "...candidate bootmgr.exe 0x%lx 0x%lx 0x%lx 0x%lx\n",
+		      (unsigned long) bmentry.signature,
+		      (unsigned long) bmentry.compressed_size,
+		      (unsigned long) bmentry.uncompressed_size,
+		      (unsigned long) bmentry.offset );
+
+		if ( bmzip == bmcip ) {
  			DBG ( "...checking for LZNT1-compressed bootmgr.exe at "
  			      "+%#zx\n", offset );
  			decompress = lznt1_decompress;
-		}
-
-		/* Check for an embedded XCA-compressed bootmgr.exe.
-		 * The bytes 0x00, 'M', and 'Z' will always be
-		 * present, and so the corresponding symbols must have
-		 * a non-zero Huffman length.  The embedded image
-		 * tends to have a large block of zeroes immediately
-		 * beforehand, which we check for.  It's implausible
-		 * that the compressed data could contain substantial
-		 * runs of zeroes, so we check for that too, in order
-		 * to eliminate some common false positive matches.
-		 */
-		if ( ( ( compressed[0x00] & 0x0f ) != 0x00 ) &&
-		     ( ( compressed[0x26] & 0xf0 ) != 0x00 ) &&
-		     ( ( compressed[0x2d] & 0x0f ) != 0x00 ) &&
-		     ( is_empty_pgh ( compressed - 0x10 ) ) &&
-		     ( ! is_empty_pgh ( ( compressed + 0x400 ) ) ) &&
-		     ( ! is_empty_pgh ( ( compressed + 0x800 ) ) ) &&
-		     ( ! is_empty_pgh ( ( compressed + 0xc00 ) ) ) ) {
+                }
+		if ( bmzip == bmxhp ) {
  			DBG ( "...checking for XCA-compressed bootmgr.exe at "
  			      "+%#zx\n", offset );
  			decompress = xca_decompress;
-		}
+                }
+
+                offset -= bmentry.offset - 1;

  		/* If we have not found a possible bootmgr.exe, skip
-		 * to the next paragraph.
+		 * to the next entry.
  		 */
  		if ( ! decompress )
  			continue;
@@ -291,7 +307,8 @@ static struct vdisk_file * add_bootmgr ( const void 
*data, size_t len ) {
  		/* Find length of decompressed image */
  		decompressed_len = decompress ( compressed, compressed_len,
  						NULL );
-		if ( decompressed_len < 0 ) {
+		if ( decompressed_len < 0 ||
+		     decompressed_len - bmentry.uncompressed_size ) {
  			/* May be a false positive signature match */
  			continue;
  		}





More information about the ipxe-devel mailing list