From: Jeremy Fitzhardinge <jeremy@goop.org>
To: "Eric W. Biederman" <ebiederm@xmission.com>,
"H. Peter Anvin" <hpa@zytor.com>
Cc: lkml <linux-kernel@vger.kernel.org>,
Vivek Goyal <vgoyal@in.ibm.com>,
v12n <virtualization@lists.linux-foundation.org>
Subject: [PATCH RFC 6/7] i386: make the bzImage payload an ELF file
Date: Wed, 06 Jun 2007 15:58:43 -0700 [thread overview]
Message-ID: <20070606230922.476662240@goop.org> (raw)
In-Reply-To: 20070606225837.654272428@goop.org
[-- Attachment #1: i386-bzimage-elf-payload.patch --]
[-- Type: text/plain, Size: 10723 bytes --]
This patch makes the payload of the bzImage file an ELF file. In
other words, the bzImage is structured as follows:
- boot sector
- 16bit setup code
- ELF header
- decompressor
- compressed kernel
A bootloader may find the start of the ELF file by looking at the
setup_size entry in the boot params, and using that to find the offset
of the ELF header. The ELF Phdrs contain all the mapped memory
required to decompress and start booting the kernel.
One slightly complex part of this is that the bzImage boot_params need
to know about the internal structure of the ELF file, at least to the
extent of being able to point the core32_start entry at the ELF file's
entrypoint, so that loaders which use this field will still work.
Similarly, the ELF header needs to know how big the kernel vmlinux's
bss segment is, in order to make sure is is mapped properly.
To handle these two cases, we generate abstracted versions of the
object files which only contain the symbols we care about (generated
with objcopy --strip-all --keep-symbol=X), and then include those
symbol tables with ld -R.
Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Vivek Goyal <vgoyal@in.ibm.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
---
arch/i386/boot/Makefile | 11 ++++--
arch/i386/boot/compressed/Makefile | 29 +++++++++++++--
arch/i386/boot/compressed/elfhdr.S | 60 +++++++++++++++++++++++++++++++++
arch/i386/boot/compressed/head.S | 9 ++--
arch/i386/boot/compressed/notes.S | 7 +++
arch/i386/boot/compressed/vmlinux.lds | 24 ++++++++++---
arch/i386/boot/header.S | 7 ---
arch/i386/boot/setup.ld | 5 ++
arch/i386/kernel/head.S | 1
arch/i386/kernel/vmlinux.lds.S | 1
10 files changed, 131 insertions(+), 23 deletions(-)
===================================================================
--- a/arch/i386/boot/Makefile
+++ b/arch/i386/boot/Makefile
@@ -72,14 +72,19 @@ AFLAGS := $(CFLAGS) -D__ASSEMBLY__
SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
-LDFLAGS_setup.elf := -T
-$(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE
+$(obj)/zImage $(obj)/bzImage: \
+ LDFLAGS := \
+ -R $(obj)/compressed/blob-syms \
+ --defsym IMAGE_OFFSET=$(IMAGE_OFFSET) -T
+
+$(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) \
+ $(obj)/compressed/blob-syms FORCE
$(call if_changed,ld)
$(obj)/payload.o: EXTRA_AFLAGS := -Wa,-I$(obj)
$(obj)/payload.o: $(src)/payload.S $(obj)/blob.bin
-$(obj)/compressed/blob: FORCE
+$(obj)/compressed/blob $(obj)/compressed/blob-syms: FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@
# Set this if you want to pass append arguments to the zdisk/fdimage/isoimage kernel
===================================================================
--- a/arch/i386/boot/compressed/Makefile
+++ b/arch/i386/boot/compressed/Makefile
@@ -4,21 +4,42 @@
# create a compressed vmlinux image from the original vmlinux
#
-targets := blob vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o \
+targets := blob vmlinux.bin vmlinux.bin.gz \
+ elfhdr.o head.o misc.o notes.o piggy.o \
vmlinux.bin.all vmlinux.relocs
-LDFLAGS_blob := -T
hostprogs-y := relocs
CFLAGS := -m32 -D__KERNEL__ $(LINUX_INCLUDE) -O2 \
-fno-strict-aliasing -fPIC \
$(call cc-option,-ffreestanding) \
$(call cc-option,-fno-stack-protector)
-LDFLAGS := -m elf_i386
+LDFLAGS := -R $(obj)/vmlinux-syms --defsym IMAGE_OFFSET=$(IMAGE_OFFSET) -T
-$(obj)/blob: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
+OBJS=$(addprefix $(obj)/,elfhdr.o head.o misc.o notes.o piggy.o)
+
+$(obj)/blob: $(src)/vmlinux.lds $(obj)/vmlinux-syms $(OBJS) FORCE
$(call if_changed,ld)
@:
+
+# Generate a stripped-down object including only the symbols needed
+# so that we can get them with ld -R. Direct stderr to /dev/null to
+# shut useless warning up.
+quiet_cmd_symextract = SYMEXT $@
+ cmd_symextract = objcopy -S \
+ $(addprefix -j,$(EXTRACTSECTS)) \
+ $(addprefix -K,$(EXTRACTSYMS)) \
+ $< $@ 2>/dev/null
+
+$(obj)/blob-syms: EXTRACTSYMS := blob_entry blob_payload
+$(obj)/blob-syms: EXTRACTSECTS := .text.head .data.compressed
+$(obj)/blob-syms: $(obj)/blob FORCE
+ $(call if_changed,symextract)
+
+$(obj)/vmlinux-syms: EXTRACTSYMS := __reserved_end
+$(obj)/vmlinux-syms: EXTRACTSECTS := .bss
+$(obj)/vmlinux-syms: vmlinux FORCE
+ $(call if_changed,symextract)
$(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objcopy)
===================================================================
--- /dev/null
+++ b/arch/i386/boot/compressed/elfhdr.S
@@ -0,0 +1,60 @@
+/* DIY ELF header */
+
+#include <linux/elf.h>
+#include <asm/boot.h>
+
+.section .elfhdr,"a",@progbits
+ehdr:
+ # e_ident
+ .byte ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3
+ .byte ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_STANDALONE
+ .org ehdr + EI_NIDENT
+#ifndef CONFIG_RELOCATABLE
+ .word ET_EXEC # e_type
+#else
+ .word ET_DYN # e_type
+#endif
+ .word EM_386 # e_machine
+ .int 1 # e_version
+ .int LOAD_PHYSICAL_ADDR + blob_startup_32 - ehdr # e_entry
+ .int phdr - ehdr # e_phoff
+ .int 0 # e_shoff
+ .int 0 # e_flags
+ .word ehdr_end - ehdr # e_ehsize
+ .word phdr_size # e_phentsize
+ .word phnum # e_phnum
+ .word 40 # e_shentsize
+ .word 0 # e_shnum
+ .word 0 # e_shstrndx
+ehdr_end:
+
+phdr:
+ .int PT_LOAD # p_type
+ .int _head - ehdr # p_offset
+ .int LOAD_PHYSICAL_ADDR # p_vaddr
+ .int LOAD_PHYSICAL_ADDR # p_paddr
+ .int blob_filesz # p_filesz
+ .int blob_memsz # p_memsz
+ .int PF_R | PF_W | PF_X # p_flags
+ .int 4096 # p_align
+phdr_size = . - phdr
+
+ .int PT_NOTE # p_type
+ .int _notes - ehdr # p_offset
+ .int 0 # p_vaddr
+ .int 0 # p_paddr
+ .int blob_notesz # p_filesz
+ .int 0 # p_memsz
+ .int 0 # p_flags
+ .int 0 # p_align
+
+ .int PT_PHDR # p_type
+ .int phdr - ehdr # p_offset
+ .int LOAD_PHYSICAL_ADDR + phdr - ehdr # p_vaddr
+ .int LOAD_PHYSICAL_ADDR + phdr - ehdr # p_paddr
+ .int phdr_end - phdr # p_filesz
+ .int phdr_end - phdr # p_memsz
+ .int PF_R | PF_W | PF_X # p_flags
+ .int 0 # p_align
+phdr_end:
+phnum = (phdr_end - phdr) / phdr_size
===================================================================
--- a/arch/i386/boot/compressed/head.S
+++ b/arch/i386/boot/compressed/head.S
@@ -27,11 +27,12 @@
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/boot.h>
+#include <asm/asm-offsets.h>
.section ".text.head","ax",@progbits
- .globl startup_32
+ .globl blob_startup_32
-startup_32:
+blob_startup_32:
cld
cli
movl $(__BOOT_DS),%eax
@@ -48,7 +49,7 @@ startup_32:
* data at 0x1e4 (defined as a scratch field) are used as the stack
* for this calculation. Only 4 bytes are needed.
*/
- leal (0x1e4+4)(%esi), %esp
+ leal (BP_scratch+4)(%esi), %esp
call 1f
1: popl %ebp
subl $1b, %ebp
@@ -85,7 +86,7 @@ 1: popl %ebp
pushl %esi
leal _end(%ebp), %esi
leal _end(%ebx), %edi
- movl $(_end - startup_32), %ecx
+ movl $(_end - blob_startup_32), %ecx
std
rep
movsb
===================================================================
--- /dev/null
+++ b/arch/i386/boot/compressed/notes.S
@@ -0,0 +1,7 @@
+#include <linux/elfnote.h>
+#include <linux/elf_boot.h>
+#include <linux/utsrelease.h>
+
+ELFNOTE(ELF_NOTE_BOOT, EIN_PROGRAM_NAME, .asciz "Linux")
+ELFNOTE(ELF_NOTE_BOOT, EIN_PROGRAM_VERSION, .asciz UTS_RELEASE)
+ELFNOTE(ELF_NOTE_BOOT, EIN_ARGUMENT_STYLE, .asciz "Linux")
===================================================================
--- a/arch/i386/boot/compressed/vmlinux.lds
+++ b/arch/i386/boot/compressed/vmlinux.lds
@@ -1,18 +1,21 @@ OUTPUT_FORMAT("elf32-i386", "elf32-i386"
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_FORMAT("elf32-i386")
OUTPUT_ARCH(i386)
-ENTRY(startup_32)
+
SECTIONS
{
- /* Be careful parts of head.S assume startup_32 is at
- * address 0.
- */
+ /* make sure we don't get anything from vmlinux-syms */
+ /DISCARD/ : { */vmlinux-syms(*) }
+
. = 0 ;
.text.head : {
+ *(.elfhdr)
_head = . ;
+ blob_entry = blob_startup_32 + IMAGE_OFFSET;
*(.text.head)
_ehead = . ;
}
.data.compressed : {
+ blob_payload = input_data + IMAGE_OFFSET;
*(.data.compressed)
}
.text : {
@@ -33,6 +36,7 @@ SECTIONS
*(.data.*)
_edata = . ;
}
+ blob_filesz = . ;
.bss : {
_bss = . ;
*(.bss)
@@ -40,4 +44,14 @@ SECTIONS
*(COMMON)
_end = . ;
}
+
+ /* __reserved_end taken from vmlinux */
+ blob_memsz = __reserved_end;
+
+ .notes : {
+ _notes = . ;
+ *(.note*)
+ _notes_end = .;
+ }
+ blob_notesz = _notes_end - _notes;
}
===================================================================
--- a/arch/i386/boot/header.S
+++ b/arch/i386/boot/header.S
@@ -155,13 +155,8 @@ setup_move_size: .word _setup_size # si
# loader knows how much data behind
# us also needs to be loaded.
-code32_start: # here loaders can put a different
+code32_start: .long blob_entry # here loaders can put a different
# start address for 32-bit code.
-#ifndef __BIG_KERNEL__
- .long 0x1000 # 0x1000 = default for zImage
-#else
- .long 0x100000 # 0x100000 = default for big kernel
-#endif
ramdisk_image: .long 0 # address of loaded ramdisk image
# Here the loader puts the 32-bit
===================================================================
--- a/arch/i386/boot/setup.ld
+++ b/arch/i386/boot/setup.ld
@@ -9,6 +9,9 @@ ENTRY(_start)
SECTIONS
{
+ /* make sure we don't get anything from blob-syms */
+ /DISCARD/ : { */blob-syms(*) }
+
.bstext 0 : { *(.bstext) }
.bsdata : { *(.bsdata) }
@@ -45,7 +48,7 @@ SECTIONS
/DISCARD/ : { *(.note*) }
- . = ALIGN(512); /* align to sector size */
+ . = ALIGN(4096); /* align to page size */
_setup_size = . - _start;
_setup_sects = _setup_size / 512;
===================================================================
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -59,6 +59,7 @@ BOOTBITMAP_SIZE = LOW_PAGES / 8
BOOTBITMAP_SIZE = LOW_PAGES / 8
ALLOCATOR_SLOP = 4
+.globl INIT_MAP_BEYOND_END
INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_SIZE_asm
/*
===================================================================
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -194,6 +194,7 @@ SECTIONS
/* This is where the kernel creates the early boot page tables */
. = ALIGN(4096);
pg0 = . ;
+ __reserved_end = . + INIT_MAP_BEYOND_END - LOAD_OFFSET;
}
/* Sections to be discarded */
--
next prev parent reply other threads:[~2007-06-06 22:58 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-06-06 22:58 [PATCH RFC 0/7] proposed updates to boot protocol and paravirt booting Jeremy Fitzhardinge
2007-06-06 22:58 ` [PATCH RFC 1/7] update boot spec to 2.07 Jeremy Fitzhardinge
2007-06-06 22:58 ` [PATCH RFC 2/7] add WEAK() for creating weak asm labels Jeremy Fitzhardinge
2007-06-06 22:58 ` [PATCH RFC 3/7] allow linux/elf.h to be included in assembler Jeremy Fitzhardinge
2007-06-06 22:58 ` [PATCH RFC 4/7] define ELF notes for adding to a boot image Jeremy Fitzhardinge
2007-06-06 22:58 ` [PATCH RFC 5/7] i386: clean up bzImage generation Jeremy Fitzhardinge
2007-06-06 22:58 ` Jeremy Fitzhardinge [this message]
2007-06-06 23:41 ` [PATCH RFC 6/7] i386: make the bzImage payload an ELF file H. Peter Anvin
2007-06-06 23:56 ` Jeremy Fitzhardinge
[not found] ` <466749C8.2010700@goop.org>
2007-06-07 0:08 ` H. Peter Anvin
[not found] ` <46674C96.7090104@zytor.com>
2007-06-07 0:20 ` Jeremy Fitzhardinge
[not found] ` <46674F68.6030100@goop.org>
2007-06-07 0:42 ` H. Peter Anvin
[not found] ` <4667547B.8080502@zytor.com>
2007-06-07 1:01 ` Jeremy Fitzhardinge
2007-06-08 3:49 ` Vivek Goyal
[not found] ` <20070608034958.GA10728@in.ibm.com>
2007-06-08 4:01 ` H. Peter Anvin
2007-06-07 1:47 ` Rob Landley
[not found] ` <200706062147.21225.rob@landley.net>
2007-06-07 1:54 ` H. Peter Anvin
2007-06-07 16:08 ` Rob Landley
[not found] ` <200706071208.04777.rob@landley.net>
2007-06-07 16:14 ` H. Peter Anvin
2007-06-06 22:58 ` [PATCH RFC 7/7] i386: paravirt boot sequence Jeremy Fitzhardinge
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070606230922.476662240@goop.org \
--to=jeremy@goop.org \
--cc=ebiederm@xmission.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=vgoyal@in.ibm.com \
--cc=virtualization@lists.linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).