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 <rusty@rustcorp.com.au>
This commit is contained in:
parent
814a0e5cdf
commit
5bbf89fc26
|
@ -326,74 +326,39 @@ static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr)
|
||||||
return ehdr->e_entry;
|
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
|
/*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
|
* supposed to jump into it and it will unpack itself. We used to have to
|
||||||
* because the Guest can't run the unpacking code, and adding features to
|
* perform some hairy magic because the unpacking code scared me.
|
||||||
* lguest kills puppies, so we don't want to.
|
|
||||||
*
|
*
|
||||||
* The bzImage is formed by putting the decompressing code in front of the
|
* Fortunately, Jeremy Fitzhardinge convinced me it wasn't that hard and wrote
|
||||||
* compressed kernel code. So we can simple scan through it looking for the
|
* a small patch to jump over the tricky bits in the Guest, so now we just read
|
||||||
* first "gzip" header, and start decompressing from there. */
|
* the funky header so we know where in the file to load, and away we go! */
|
||||||
static unsigned long load_bzimage(int fd)
|
static unsigned long load_bzimage(int fd)
|
||||||
{
|
{
|
||||||
unsigned char c;
|
u8 hdr[1024];
|
||||||
int state = 0;
|
int r;
|
||||||
|
/* Modern bzImages get loaded at 1M. */
|
||||||
|
void *p = from_guest_phys(0x100000);
|
||||||
|
|
||||||
/* GZIP header is 0x1F 0x8B <method> <flags>... <compressed-by>. */
|
/* Go back to the start of the file and read the header. It should be
|
||||||
while (read(fd, &c, 1) == 1) {
|
* a Linux boot header (see Documentation/i386/boot.txt) */
|
||||||
switch (state) {
|
lseek(fd, 0, SEEK_SET);
|
||||||
case 0:
|
read(fd, hdr, sizeof(hdr));
|
||||||
if (c == 0x1F)
|
|
||||||
state++;
|
/* At offset 0x202, we expect the magic "HdrS" */
|
||||||
break;
|
if (memcmp(hdr + 0x202, "HdrS", 4) != 0)
|
||||||
case 1:
|
errx(1, "This doesn't look like a bzImage to me");
|
||||||
if (c == 0x8B)
|
|
||||||
state++;
|
/* The byte at 0x1F1 tells us how many extra sectors of
|
||||||
else
|
* header: skip over them all. */
|
||||||
state = 0;
|
lseek(fd, (unsigned long)(hdr[0x1F1]+1) * 512, SEEK_SET);
|
||||||
break;
|
|
||||||
case 2 ... 8:
|
/* Now read everything into memory. in nice big chunks. */
|
||||||
state++;
|
while ((r = read(fd, p, 65536)) > 0)
|
||||||
break;
|
p += r;
|
||||||
case 9:
|
|
||||||
/* Seek back to the start of the gzip header. */
|
/* Finally, 0x214 tells us where to start the kernel. */
|
||||||
lseek(fd, -10, SEEK_CUR);
|
return *(unsigned long *)&hdr[0x214];
|
||||||
/* One final check: "compressed under UNIX". */
|
|
||||||
if (c != 0x03)
|
|
||||||
state = -1;
|
|
||||||
else
|
|
||||||
return unpack_bzimage(fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
errx(1, "Could not find kernel in bzImage");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*L:140 Loading the kernel is easy when it's a "vmlinux", but most kernels
|
/*L:140 Loading the kernel is easy when it's a "vmlinux", but most kernels
|
||||||
|
|
Loading…
Reference in a new issue