diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2007-10-21 21:29:56 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2007-10-23 01:49:57 -0400 |
commit | 5bbf89fc260830f3f58b331d946a16b39ad1ca2d (patch) | |
tree | 7b5401eefe9239cd84bf843fd8d8e8bcc79f26cd | |
parent | 814a0e5cdfbd384f4bf7a8443f9c3b885f413d58 (diff) |
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>
-rw-r--r-- | 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 004c5c6aba6a..3949620e42fa 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) | |||
326 | return ehdr->e_entry; | 326 | return ehdr->e_entry; |
327 | } | 327 | } |
328 | 328 | ||
329 | /*L:160 Unfortunately the entire ELF image isn't compressed: the segments | ||
330 | * which need loading are extracted and compressed raw. This denies us the | ||
331 | * information we need to make a fully-general loader. */ | ||
332 | static unsigned long unpack_bzimage(int fd) | ||
333 | { | ||
334 | gzFile f; | ||
335 | int ret, len = 0; | ||
336 | /* A bzImage always gets loaded at physical address 1M. This is | ||
337 | * actually configurable as CONFIG_PHYSICAL_START, but as the comment | ||
338 | * there says, "Don't change this unless you know what you are doing". | ||
339 | * Indeed. */ | ||
340 | void *img = from_guest_phys(0x100000); | ||
341 | |||
342 | /* gzdopen takes our file descriptor (carefully placed at the start of | ||
343 | * the GZIP header we found) and returns a gzFile. */ | ||
344 | f = gzdopen(fd, "rb"); | ||
345 | /* We read it into memory in 64k chunks until we hit the end. */ | ||
346 | while ((ret = gzread(f, img + len, 65536)) > 0) | ||
347 | len += ret; | ||
348 | if (ret < 0) | ||
349 | err(1, "reading image from bzImage"); | ||
350 | |||
351 | verbose("Unpacked size %i addr %p\n", len, img); | ||
352 | |||
353 | /* The entry point for a bzImage is always the first byte */ | ||
354 | return (unsigned long)img; | ||
355 | } | ||
356 | |||
357 | /*L:150 A bzImage, unlike an ELF file, is not meant to be loaded. You're | 329 | /*L:150 A bzImage, unlike an ELF file, is not meant to be loaded. You're |
358 | * supposed to jump into it and it will unpack itself. We can't do that | 330 | * supposed to jump into it and it will unpack itself. We used to have to |
359 | * because the Guest can't run the unpacking code, and adding features to | 331 | * perform some hairy magic because the unpacking code scared me. |
360 | * lguest kills puppies, so we don't want to. | ||
361 | * | 332 | * |
362 | * The bzImage is formed by putting the decompressing code in front of the | 333 | * Fortunately, Jeremy Fitzhardinge convinced me it wasn't that hard and wrote |
363 | * compressed kernel code. So we can simple scan through it looking for the | 334 | * a small patch to jump over the tricky bits in the Guest, so now we just read |
364 | * first "gzip" header, and start decompressing from there. */ | 335 | * the funky header so we know where in the file to load, and away we go! */ |
365 | static unsigned long load_bzimage(int fd) | 336 | static unsigned long load_bzimage(int fd) |
366 | { | 337 | { |
367 | unsigned char c; | 338 | u8 hdr[1024]; |
368 | int state = 0; | 339 | int r; |
369 | 340 | /* Modern bzImages get loaded at 1M. */ | |
370 | /* GZIP header is 0x1F 0x8B <method> <flags>... <compressed-by>. */ | 341 | void *p = from_guest_phys(0x100000); |
371 | while (read(fd, &c, 1) == 1) { | 342 | |
372 | switch (state) { | 343 | /* Go back to the start of the file and read the header. It should be |
373 | case 0: | 344 | * a Linux boot header (see Documentation/i386/boot.txt) */ |
374 | if (c == 0x1F) | 345 | lseek(fd, 0, SEEK_SET); |
375 | state++; | 346 | read(fd, hdr, sizeof(hdr)); |
376 | break; | 347 | |
377 | case 1: | 348 | /* At offset 0x202, we expect the magic "HdrS" */ |
378 | if (c == 0x8B) | 349 | if (memcmp(hdr + 0x202, "HdrS", 4) != 0) |
379 | state++; | 350 | errx(1, "This doesn't look like a bzImage to me"); |
380 | else | 351 | |
381 | state = 0; | 352 | /* The byte at 0x1F1 tells us how many extra sectors of |
382 | break; | 353 | * header: skip over them all. */ |
383 | case 2 ... 8: | 354 | lseek(fd, (unsigned long)(hdr[0x1F1]+1) * 512, SEEK_SET); |
384 | state++; | 355 | |
385 | break; | 356 | /* Now read everything into memory. in nice big chunks. */ |
386 | case 9: | 357 | while ((r = read(fd, p, 65536)) > 0) |
387 | /* Seek back to the start of the gzip header. */ | 358 | p += r; |
388 | lseek(fd, -10, SEEK_CUR); | 359 | |
389 | /* One final check: "compressed under UNIX". */ | 360 | /* Finally, 0x214 tells us where to start the kernel. */ |
390 | if (c != 0x03) | 361 | return *(unsigned long *)&hdr[0x214]; |
391 | state = -1; | ||
392 | else | ||
393 | return unpack_bzimage(fd); | ||
394 | } | ||
395 | } | ||
396 | errx(1, "Could not find kernel in bzImage"); | ||
397 | } | 362 | } |
398 | 363 | ||
399 | /*L:140 Loading the kernel is easy when it's a "vmlinux", but most kernels | 364 | /*L:140 Loading the kernel is easy when it's a "vmlinux", but most kernels |