Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=5bbf89fc260830f3f58b331d946a16b39ad1ca2d
Commit:     5bbf89fc260830f3f58b331d946a16b39ad1ca2d
Parent:     814a0e5cdfbd384f4bf7a8443f9c3b885f413d58
Author:     Rusty Russell <[EMAIL PROTECTED]>
AuthorDate: Mon Oct 22 11:29:56 2007 +1000
Committer:  Rusty Russell <[EMAIL PROTECTED]>
CommitDate: Tue Oct 23 15:49:57 2007 +1000

    Loading bzImage directly.
    
    Now arch/i386/boot/compressed/head.S understands the hardware_platform 
field,
    we can directly execute bzImages.  No more horrific unpacking code.
    
    Signed-off-by: Rusty Russell <[EMAIL PROTECTED]>
---
 Documentation/lguest/lguest.c |   93 +++++++++++++----------------------------
 1 files changed, 29 insertions(+), 64 deletions(-)

diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index 004c5c6..3949620 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -326,74 +326,39 @@ static unsigned long map_elf(int elf_fd, const Elf32_Ehdr 
*ehdr)
        return ehdr->e_entry;
 }
 
-/*L:160 Unfortunately the entire ELF image isn't compressed: the segments
- * which need loading are extracted and compressed raw.  This denies us the
- * information we need to make a fully-general loader. */
-static unsigned long unpack_bzimage(int fd)
-{
-       gzFile f;
-       int ret, len = 0;
-       /* A bzImage always gets loaded at physical address 1M.  This is
-        * actually configurable as CONFIG_PHYSICAL_START, but as the comment
-        * there says, "Don't change this unless you know what you are doing".
-        * Indeed. */
-       void *img = from_guest_phys(0x100000);
-
-       /* gzdopen takes our file descriptor (carefully placed at the start of
-        * the GZIP header we found) and returns a gzFile. */
-       f = gzdopen(fd, "rb");
-       /* We read it into memory in 64k chunks until we hit the end. */
-       while ((ret = gzread(f, img + len, 65536)) > 0)
-               len += ret;
-       if (ret < 0)
-               err(1, "reading image from bzImage");
-
-       verbose("Unpacked size %i addr %p\n", len, img);
-
-       /* The entry point for a bzImage is always the first byte */
-       return (unsigned long)img;
-}
-
 /*L:150 A bzImage, unlike an ELF file, is not meant to be loaded.  You're
- * supposed to jump into it and it will unpack itself.  We can't do that
- * because the Guest can't run the unpacking code, and adding features to
- * lguest kills puppies, so we don't want to.
+ * supposed to jump into it and it will unpack itself.  We used to have to
+ * perform some hairy magic because the unpacking code scared me.
  *
- * The bzImage is formed by putting the decompressing code in front of the
- * compressed kernel code.  So we can simple scan through it looking for the
- * first "gzip" header, and start decompressing from there. */
+ * Fortunately, Jeremy Fitzhardinge convinced me it wasn't that hard and wrote
+ * a small patch to jump over the tricky bits in the Guest, so now we just read
+ * the funky header so we know where in the file to load, and away we go! */
 static unsigned long load_bzimage(int fd)
 {
-       unsigned char c;
-       int state = 0;
-
-       /* GZIP header is 0x1F 0x8B <method> <flags>... <compressed-by>. */
-       while (read(fd, &c, 1) == 1) {
-               switch (state) {
-               case 0:
-                       if (c == 0x1F)
-                               state++;
-                       break;
-               case 1:
-                       if (c == 0x8B)
-                               state++;
-                       else
-                               state = 0;
-                       break;
-               case 2 ... 8:
-                       state++;
-                       break;
-               case 9:
-                       /* Seek back to the start of the gzip header. */
-                       lseek(fd, -10, SEEK_CUR);
-                       /* One final check: "compressed under UNIX". */
-                       if (c != 0x03)
-                               state = -1;
-                       else
-                               return unpack_bzimage(fd);
-               }
-       }
-       errx(1, "Could not find kernel in bzImage");
+       u8 hdr[1024];
+       int r;
+       /* Modern bzImages get loaded at 1M. */
+       void *p = from_guest_phys(0x100000);
+
+       /* Go back to the start of the file and read the header.  It should be
+        * a Linux boot header (see Documentation/i386/boot.txt) */
+       lseek(fd, 0, SEEK_SET);
+       read(fd, hdr, sizeof(hdr));
+
+       /* At offset 0x202, we expect the magic "HdrS" */
+       if (memcmp(hdr + 0x202, "HdrS", 4) != 0)
+               errx(1, "This doesn't look like a bzImage to me");
+
+       /* The byte at 0x1F1 tells us how many extra sectors of
+        * header: skip over them all. */
+       lseek(fd, (unsigned long)(hdr[0x1F1]+1) * 512, SEEK_SET);
+
+       /* Now read everything into memory. in nice big chunks. */
+       while ((r = read(fd, p, 65536)) > 0)
+               p += r;
+
+       /* Finally, 0x214 tells us where to start the kernel. */
+       return *(unsigned long *)&hdr[0x214];
 }
 
 /*L:140 Loading the kernel is easy when it's a "vmlinux", but most kernels
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to