diff options
author | Ian Campbell <ijc@hellion.org.uk> | 2008-02-13 15:54:58 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-17 11:40:46 -0400 |
commit | 099e1377269a47ed30a00ee131001988e5bcaa9c (patch) | |
tree | 2bf2f02aa44db93a9e8b1f4ef76ac08d3a732a46 /arch/x86/boot/compressed/misc.c | |
parent | e0bf0f75bdc441abb05365abc56ee96ba44ca073 (diff) |
x86: use ELF format in compressed images.
Signed-off-by: Ian Campbell <ijc@hellion.org.uk>
Cc: Ian Campbell <ijc@hellion.org.uk>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: virtualization@lists.linux-foundation.org
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: virtualization@lists.linux-foundation.org
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/boot/compressed/misc.c')
-rw-r--r-- | arch/x86/boot/compressed/misc.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 8182e32c1b42..69aec2f4155d 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c | |||
@@ -15,6 +15,10 @@ | |||
15 | * we just keep it from happening | 15 | * we just keep it from happening |
16 | */ | 16 | */ |
17 | #undef CONFIG_PARAVIRT | 17 | #undef CONFIG_PARAVIRT |
18 | #ifdef CONFIG_X86_32 | ||
19 | #define _ASM_DESC_H_ 1 | ||
20 | #endif | ||
21 | |||
18 | #ifdef CONFIG_X86_64 | 22 | #ifdef CONFIG_X86_64 |
19 | #define _LINUX_STRING_H_ 1 | 23 | #define _LINUX_STRING_H_ 1 |
20 | #define __LINUX_BITMAP_H 1 | 24 | #define __LINUX_BITMAP_H 1 |
@@ -22,6 +26,7 @@ | |||
22 | 26 | ||
23 | #include <linux/linkage.h> | 27 | #include <linux/linkage.h> |
24 | #include <linux/screen_info.h> | 28 | #include <linux/screen_info.h> |
29 | #include <linux/elf.h> | ||
25 | #include <asm/io.h> | 30 | #include <asm/io.h> |
26 | #include <asm/page.h> | 31 | #include <asm/page.h> |
27 | #include <asm/boot.h> | 32 | #include <asm/boot.h> |
@@ -365,6 +370,56 @@ static void error(char *x) | |||
365 | asm("hlt"); | 370 | asm("hlt"); |
366 | } | 371 | } |
367 | 372 | ||
373 | static void parse_elf(void *output) | ||
374 | { | ||
375 | #ifdef CONFIG_X86_64 | ||
376 | Elf64_Ehdr ehdr; | ||
377 | Elf64_Phdr *phdrs, *phdr; | ||
378 | #else | ||
379 | Elf32_Ehdr ehdr; | ||
380 | Elf32_Phdr *phdrs, *phdr; | ||
381 | #endif | ||
382 | void *dest; | ||
383 | int i; | ||
384 | |||
385 | memcpy(&ehdr, output, sizeof(ehdr)); | ||
386 | if(ehdr.e_ident[EI_MAG0] != ELFMAG0 || | ||
387 | ehdr.e_ident[EI_MAG1] != ELFMAG1 || | ||
388 | ehdr.e_ident[EI_MAG2] != ELFMAG2 || | ||
389 | ehdr.e_ident[EI_MAG3] != ELFMAG3) | ||
390 | { | ||
391 | error("Kernel is not a valid ELF file"); | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | putstr("Parsing ELF... "); | ||
396 | |||
397 | phdrs = malloc(sizeof(*phdrs) * ehdr.e_phnum); | ||
398 | if (!phdrs) | ||
399 | error("Failed to allocate space for phdrs"); | ||
400 | |||
401 | memcpy(phdrs, output + ehdr.e_phoff, sizeof(*phdrs) * ehdr.e_phnum); | ||
402 | |||
403 | for (i=0; i<ehdr.e_phnum; i++) { | ||
404 | phdr = &phdrs[i]; | ||
405 | |||
406 | switch (phdr->p_type) { | ||
407 | case PT_LOAD: | ||
408 | #ifdef CONFIG_RELOCATABLE | ||
409 | dest = output; | ||
410 | dest += (phdr->p_paddr - LOAD_PHYSICAL_ADDR); | ||
411 | #else | ||
412 | dest = (void*)(phdr->p_paddr); | ||
413 | #endif | ||
414 | memcpy(dest, | ||
415 | output + phdr->p_offset, | ||
416 | phdr->p_filesz); | ||
417 | break; | ||
418 | default: /* Ignore other PT_* */ break; | ||
419 | } | ||
420 | } | ||
421 | } | ||
422 | |||
368 | asmlinkage void decompress_kernel(void *rmode, memptr heap, | 423 | asmlinkage void decompress_kernel(void *rmode, memptr heap, |
369 | uch *input_data, unsigned long input_len, | 424 | uch *input_data, unsigned long input_len, |
370 | uch *output) | 425 | uch *output) |
@@ -408,6 +463,7 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap, | |||
408 | makecrc(); | 463 | makecrc(); |
409 | putstr("\nDecompressing Linux... "); | 464 | putstr("\nDecompressing Linux... "); |
410 | gunzip(); | 465 | gunzip(); |
466 | parse_elf(output); | ||
411 | putstr("done.\nBooting the kernel.\n"); | 467 | putstr("done.\nBooting the kernel.\n"); |
412 | return; | 468 | return; |
413 | } | 469 | } |