[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