aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/i386/boot.txt18
-rw-r--r--arch/x86/boot/Makefile14
-rw-r--r--arch/x86/boot/compressed/Makefile2
-rw-r--r--arch/x86/boot/compressed/misc.c56
-rw-r--r--arch/x86/boot/header.S6
5 files changed, 95 insertions, 1 deletions
diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt
index fc49b79bc1ab..b5f5ba1ea668 100644
--- a/Documentation/i386/boot.txt
+++ b/Documentation/i386/boot.txt
@@ -170,6 +170,8 @@ Offset Proto Name Meaning
1700238/4 2.06+ cmdline_size Maximum size of the kernel command line 1700238/4 2.06+ cmdline_size Maximum size of the kernel command line
171023C/4 2.07+ hardware_subarch Hardware subarchitecture 171023C/4 2.07+ hardware_subarch Hardware subarchitecture
1720240/8 2.07+ hardware_subarch_data Subarchitecture-specific data 1720240/8 2.07+ hardware_subarch_data Subarchitecture-specific data
1730248/4 2.08+ compressed_payload_offset
174024C/4 2.08+ compressed_payload_length
173 175
174(1) For backwards compatibility, if the setup_sects field contains 0, the 176(1) For backwards compatibility, if the setup_sects field contains 0, the
175 real value is 4. 177 real value is 4.
@@ -512,6 +514,22 @@ Protocol: 2.07+
512 514
513 A pointer to data that is specific to hardware subarch 515 A pointer to data that is specific to hardware subarch
514 516
517Field name: compressed_payload_offset
518Type: read
519Offset/size: 0x248/4
520Protocol: 2.08+
521
522 If non-zero then this field contains the offset from the end of the
523 real-mode code to the compressed payload. The compression format
524 should be determined using the standard magic number, currently only
525 gzip is used.
526
527Field name: compressed_payload_length
528Type: read
529Offset/size: 0x24c/4
530Protocol: 2.08+
531
532 The length of the compressed payload.
515 533
516**** THE KERNEL COMMAND LINE 534**** THE KERNEL COMMAND LINE
517 535
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index f88458e83ef0..9695affeb584 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -94,6 +94,20 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
94 94
95SETUP_OBJS = $(addprefix $(obj)/,$(setup-y)) 95SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
96 96
97sed-offsets := -e 's/^00*/0/' \
98 -e 's/^\([0-9a-fA-F]*\) . \(input_data\|input_data_end\)$$/\#define \2 0x\1/p'
99
100quiet_cmd_offsets = OFFSETS $@
101 cmd_offsets = $(NM) $< | sed -n $(sed-offsets) > $@
102
103$(obj)/offsets.h: $(obj)/compressed/vmlinux FORCE
104 $(call if_changed,offsets)
105
106targets += offsets.h
107
108AFLAGS_header.o += -I$(obj)
109$(obj)/header.o: $(obj)/offsets.h
110
97LDFLAGS_setup.elf := -T 111LDFLAGS_setup.elf := -T
98$(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE 112$(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE
99 $(call if_changed,ld) 113 $(call if_changed,ld)
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index d2b9f3bb87c0..92fdd35bd93e 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -22,7 +22,7 @@ $(obj)/vmlinux: $(src)/vmlinux_$(BITS).lds $(obj)/head_$(BITS).o $(obj)/misc.o $
22 $(call if_changed,ld) 22 $(call if_changed,ld)
23 @: 23 @:
24 24
25OBJCOPYFLAGS_vmlinux.bin := -O binary -R .note -R .comment -S 25OBJCOPYFLAGS_vmlinux.bin := -R .comment -S
26$(obj)/vmlinux.bin: vmlinux FORCE 26$(obj)/vmlinux.bin: vmlinux FORCE
27 $(call if_changed,objcopy) 27 $(call if_changed,objcopy)
28 28
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}
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 64ad9016585a..8471658d5534 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -22,6 +22,7 @@
22#include <asm/page.h> 22#include <asm/page.h>
23#include <asm/setup.h> 23#include <asm/setup.h>
24#include "boot.h" 24#include "boot.h"
25#include "offsets.h"
25 26
26SETUPSECTS = 4 /* default nr of setup-sectors */ 27SETUPSECTS = 4 /* default nr of setup-sectors */
27BOOTSEG = 0x07C0 /* original address of boot-sector */ 28BOOTSEG = 0x07C0 /* original address of boot-sector */
@@ -223,6 +224,11 @@ hardware_subarch: .long 0 # subarchitecture, added with 2.07
223 224
224hardware_subarch_data: .quad 0 225hardware_subarch_data: .quad 0
225 226
227compressed_payload_offset:
228 .long input_data
229compressed_payload_length:
230 .long input_data_end-input_data
231
226# End of setup header ##################################################### 232# End of setup header #####################################################
227 233
228 .section ".inittext", "ax" 234 .section ".inittext", "ax"