aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/lguest/lguest.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2007-10-21 21:29:56 -0400
committerRusty Russell <rusty@rustcorp.com.au>2007-10-23 01:49:57 -0400
commit5bbf89fc260830f3f58b331d946a16b39ad1ca2d (patch)
tree7b5401eefe9239cd84bf843fd8d8e8bcc79f26cd /Documentation/lguest/lguest.c
parent814a0e5cdfbd384f4bf7a8443f9c3b885f413d58 (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>
Diffstat (limited to 'Documentation/lguest/lguest.c')
-rw-r--r--Documentation/lguest/lguest.c93
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. */
332static 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! */
365static unsigned long load_bzimage(int fd) 336static 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