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 | |
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>
-rw-r--r-- | Documentation/i386/boot.txt | 18 | ||||
-rw-r--r-- | arch/x86/boot/Makefile | 14 | ||||
-rw-r--r-- | arch/x86/boot/compressed/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/boot/compressed/misc.c | 56 | ||||
-rw-r--r-- | arch/x86/boot/header.S | 6 |
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 | |||
170 | 0238/4 2.06+ cmdline_size Maximum size of the kernel command line | 170 | 0238/4 2.06+ cmdline_size Maximum size of the kernel command line |
171 | 023C/4 2.07+ hardware_subarch Hardware subarchitecture | 171 | 023C/4 2.07+ hardware_subarch Hardware subarchitecture |
172 | 0240/8 2.07+ hardware_subarch_data Subarchitecture-specific data | 172 | 0240/8 2.07+ hardware_subarch_data Subarchitecture-specific data |
173 | 0248/4 2.08+ compressed_payload_offset | ||
174 | 024C/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 | ||
517 | Field name: compressed_payload_offset | ||
518 | Type: read | ||
519 | Offset/size: 0x248/4 | ||
520 | Protocol: 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 | |||
527 | Field name: compressed_payload_length | ||
528 | Type: read | ||
529 | Offset/size: 0x24c/4 | ||
530 | Protocol: 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 | ||
95 | SETUP_OBJS = $(addprefix $(obj)/,$(setup-y)) | 95 | SETUP_OBJS = $(addprefix $(obj)/,$(setup-y)) |
96 | 96 | ||
97 | sed-offsets := -e 's/^00*/0/' \ | ||
98 | -e 's/^\([0-9a-fA-F]*\) . \(input_data\|input_data_end\)$$/\#define \2 0x\1/p' | ||
99 | |||
100 | quiet_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 | |||
106 | targets += offsets.h | ||
107 | |||
108 | AFLAGS_header.o += -I$(obj) | ||
109 | $(obj)/header.o: $(obj)/offsets.h | ||
110 | |||
97 | LDFLAGS_setup.elf := -T | 111 | LDFLAGS_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 | ||
25 | OBJCOPYFLAGS_vmlinux.bin := -O binary -R .note -R .comment -S | 25 | OBJCOPYFLAGS_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 | ||
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 | } |
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 | ||
26 | SETUPSECTS = 4 /* default nr of setup-sectors */ | 27 | SETUPSECTS = 4 /* default nr of setup-sectors */ |
27 | BOOTSEG = 0x07C0 /* original address of boot-sector */ | 28 | BOOTSEG = 0x07C0 /* original address of boot-sector */ |
@@ -223,6 +224,11 @@ hardware_subarch: .long 0 # subarchitecture, added with 2.07 | |||
223 | 224 | ||
224 | hardware_subarch_data: .quad 0 | 225 | hardware_subarch_data: .quad 0 |
225 | 226 | ||
227 | compressed_payload_offset: | ||
228 | .long input_data | ||
229 | compressed_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" |