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 <[email protected]>
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 <[email protected]>

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 <[email protected]>
Date:   Sun Oct 11 22:01:56 2015 -0700

    [main] Use archive header to search for compressed image

    Signed-off-by: Earl Chew <[email protected]>

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;
                }


_______________________________________________
ipxe-devel mailing list
[email protected]
https://lists.ipxe.org/mailman/listinfo.cgi/ipxe-devel

Reply via email to