aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/boot/compressed/misc.c
diff options
context:
space:
mode:
authorIan Campbell <ijc@hellion.org.uk>2008-02-13 15:54:58 -0500
committerIngo Molnar <mingo@elte.hu>2008-04-17 11:40:46 -0400
commit099e1377269a47ed30a00ee131001988e5bcaa9c (patch)
tree2bf2f02aa44db93a9e8b1f4ef76ac08d3a732a46 /arch/x86/boot/compressed/misc.c
parente0bf0f75bdc441abb05365abc56ee96ba44ca073 (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.c56
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
373static 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
368asmlinkage void decompress_kernel(void *rmode, memptr heap, 423asmlinkage 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}