[PATCH] ppc64 boot: remove need for imagesize.c

Compute the vmlinux size at runtime.

Use Z_FULL_FLUSH instead of Z_FINISH, to extract only the ELF header
and ELF program header.

 ->p_memsz is the required memory range for the executable, including bss
 ->p_filesz is the size of .text, .data and other runtime sections

These values must be used for the claim call.
All additional memory needed by the kernel is claimed in prom_init, remove
the extra Mb.

Pass the full memsize as target area to gunzip, otherwise not everything
will be uncompressed.

flush_cache has to flush all runtime sections, do not reduce the memrange
by the ->p_offset value because its just that: an offset.

Remove the Makefile code to produce an imagesize.c, its not needed anymore.
Remove all FORCE flags, to not rebuild the zImage if vmlinux was not changed.

Signed-off-by: Olaf Hering <olh@suse.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Anton Blanchard <anton@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Olaf Hering 2005-10-28 17:46:40 -07:00 коммит произвёл Paul Mackerras
Родитель 7054036fc5
Коммит 8a76baf020
2 изменённых файлов: 50 добавлений и 62 удалений

Просмотреть файл

@ -34,7 +34,7 @@ zliblinuxheader := zlib.h zconf.h zutil.h
$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
#$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h) #$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
src-boot := crt0.S string.S prom.c main.c imagesize.c div64.S src-boot := crt0.S string.S prom.c main.c div64.S
src-boot += $(zlib) src-boot += $(zlib)
src-boot := $(addprefix $(obj)/, $(src-boot)) src-boot := $(addprefix $(obj)/, $(src-boot))
obj-boot := $(addsuffix .o, $(basename $(src-boot))) obj-boot := $(addsuffix .o, $(basename $(src-boot)))
@ -87,7 +87,7 @@ src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section)))
gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section))) gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section)))
hostprogs-y := addnote addRamDisk hostprogs-y := addnote addRamDisk
targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd imagesize.c \ targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \
$(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \ $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
$(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \ $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
$(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \ $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
@ -100,9 +100,9 @@ quiet_cmd_ramdisk = RAMDISK $@
quiet_cmd_stripvm = STRIP $@ quiet_cmd_stripvm = STRIP $@
cmd_stripvm = $(STRIP) -s $< -o $@ cmd_stripvm = $(STRIP) -s $< -o $@
vmlinux.strip: vmlinux FORCE vmlinux.strip: vmlinux
$(call if_changed,stripvm) $(call if_changed,stripvm)
$(obj)/vmlinux.initrd: vmlinux.strip $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE $(obj)/vmlinux.initrd: vmlinux.strip $(obj)/addRamDisk $(obj)/ramdisk.image.gz
$(call if_changed,ramdisk) $(call if_changed,ramdisk)
quiet_cmd_addsection = ADDSEC $@ quiet_cmd_addsection = ADDSEC $@
@ -110,48 +110,38 @@ quiet_cmd_addsection = ADDSEC $@
--add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $@))=$(patsubst %.o,%.gz, $@) \ --add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $@))=$(patsubst %.o,%.gz, $@) \
--set-section-flags=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $@))=$(OBJCOPYFLAGS) --set-section-flags=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $@))=$(OBJCOPYFLAGS)
quiet_cmd_imagesize = GENSIZE $@
cmd_imagesize = ls -l vmlinux.strip | \
awk '{printf "/* generated -- do not edit! */\n" "unsigned long vmlinux_filesize = %d;\n", $$5}' \
> $(obj)/imagesize.c && \
$(CROSS_COMPILE)nm -n vmlinux | tail -n 1 | \
awk '{printf "unsigned long vmlinux_memsize = 0x%s;\n", substr($$1,8)}' >> $(obj)/imagesize.c
quiet_cmd_addnote = ADDNOTE $@ quiet_cmd_addnote = ADDNOTE $@
cmd_addnote = $(obj)/addnote $@ cmd_addnote = $(obj)/addnote $@
$(call gz-sec, $(required)): $(obj)/kernel-%.gz: % FORCE $(call gz-sec, $(required)): $(obj)/kernel-%.gz: %
$(call if_changed,gzip) $(call if_changed,gzip)
$(obj)/kernel-initrd.gz: $(obj)/ramdisk.image.gz $(obj)/kernel-initrd.gz: $(obj)/ramdisk.image.gz
cp -f $(obj)/ramdisk.image.gz $@ cp -f $(obj)/ramdisk.image.gz $@
$(call src-sec, $(required) $(initrd)): $(obj)/kernel-%.c: $(obj)/kernel-%.gz FORCE $(call src-sec, $(required) $(initrd)): $(obj)/kernel-%.c: $(obj)/kernel-%.gz
@touch $@ @touch $@
$(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c FORCE $(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c
$(call if_changed_dep,bootcc) $(call if_changed_dep,bootcc)
$(call cmd,addsection) $(call cmd,addsection)
$(obj)/zImage.vmode: obj-boot += $(call obj-sec, $(required)) $(obj)/zImage.vmode: obj-boot += $(call obj-sec, $(required))
$(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) FORCE $(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot)
$(call cmd,bootld,$(obj-boot)) $(call cmd,bootld,$(obj-boot))
$(obj)/zImage.initrd.vmode: obj-boot += $(call obj-sec, $(required) $(initrd)) $(obj)/zImage.initrd.vmode: obj-boot += $(call obj-sec, $(required) $(initrd))
$(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) FORCE $(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot)
$(call cmd,bootld,$(obj-boot)) $(call cmd,bootld,$(obj-boot))
$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote FORCE $(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote
@cp -f $< $@ @cp -f $< $@
$(call if_changed,addnote) $(call if_changed,addnote)
$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote FORCE $(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote
@cp -f $< $@ @cp -f $< $@
$(call if_changed,addnote) $(call if_changed,addnote)
$(obj)/imagesize.c: vmlinux.strip
$(call cmd,imagesize)
install: $(CONFIGURE) $(BOOTIMAGE) install: $(CONFIGURE) $(BOOTIMAGE)
sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" "$(BOOTIMAGE)" sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" "$(BOOTIMAGE)"

Просмотреть файл

@ -32,8 +32,6 @@ extern char _vmlinux_start[];
extern char _vmlinux_end[]; extern char _vmlinux_end[];
extern char _initrd_start[]; extern char _initrd_start[];
extern char _initrd_end[]; extern char _initrd_end[];
extern unsigned long vmlinux_filesize;
extern unsigned long vmlinux_memsize;
struct addr_range { struct addr_range {
unsigned long addr; unsigned long addr;
@ -45,6 +43,7 @@ static struct addr_range vmlinuz = {0, 0, 0};
static struct addr_range initrd = {0, 0, 0}; static struct addr_range initrd = {0, 0, 0};
static char scratch[46912]; /* scratch space for gunzip, from zlib_inflate_workspacesize() */ static char scratch[46912]; /* scratch space for gunzip, from zlib_inflate_workspacesize() */
static char elfheader[256];
typedef void (*kernel_entry_t)( unsigned long, typedef void (*kernel_entry_t)( unsigned long,
@ -78,6 +77,7 @@ static unsigned long try_claim(unsigned long size)
void start(unsigned long a1, unsigned long a2, void *promptr) void start(unsigned long a1, unsigned long a2, void *promptr)
{ {
unsigned long i; unsigned long i;
int len;
kernel_entry_t kernel_entry; kernel_entry_t kernel_entry;
Elf64_Ehdr *elf64; Elf64_Ehdr *elf64;
Elf64_Phdr *elf64ph; Elf64_Phdr *elf64ph;
@ -113,25 +113,45 @@ void start(unsigned long a1, unsigned long a2, void *promptr)
claim_base = PROG_START; claim_base = PROG_START;
#endif #endif
/* vmlinuz.addr = (unsigned long)_vmlinux_start;
* Now we try to claim some memory for the kernel itself vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
* our "vmlinux_memsize" is the memory footprint in RAM, _HOWEVER_, what
* our Makefile stuffs in is an image containing all sort of junk including /* gunzip the ELF header of the kernel */
* an ELF header. We need to do some calculations here to find the right if (*(unsigned short *)vmlinuz.addr == 0x1f8b) {
* size... In practice we add 1Mb, that is enough, but we should really len = vmlinuz.size;
* consider fixing the Makefile to put a _raw_ kernel in there ! gunzip(elfheader, sizeof(elfheader),
*/ (unsigned char *)vmlinuz.addr, &len);
vmlinux_memsize += ONE_MB; } else
printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux_memsize); memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader));
vmlinux.addr = try_claim(vmlinux_memsize);
elf64 = (Elf64_Ehdr *)elfheader;
if ( elf64->e_ident[EI_MAG0] != ELFMAG0 ||
elf64->e_ident[EI_MAG1] != ELFMAG1 ||
elf64->e_ident[EI_MAG2] != ELFMAG2 ||
elf64->e_ident[EI_MAG3] != ELFMAG3 ||
elf64->e_ident[EI_CLASS] != ELFCLASS64 ||
elf64->e_ident[EI_DATA] != ELFDATA2MSB ||
elf64->e_type != ET_EXEC ||
elf64->e_machine != EM_PPC64 )
{
printf("Error: not a valid PPC64 ELF file!\n\r");
exit();
}
elf64ph = (Elf64_Phdr *)((unsigned long)elf64 +
(unsigned long)elf64->e_phoff);
for(i=0; i < (unsigned int)elf64->e_phnum ;i++,elf64ph++) {
if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0)
break;
}
vmlinux.size = (unsigned long)elf64ph->p_filesz;
vmlinux.memsize = (unsigned long)elf64ph->p_memsz;
printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize);
vmlinux.addr = try_claim(vmlinux.memsize);
if (vmlinux.addr == 0) { if (vmlinux.addr == 0) {
printf("Can't allocate memory for kernel image !\n\r"); printf("Can't allocate memory for kernel image !\n\r");
exit(); exit();
} }
vmlinuz.addr = (unsigned long)_vmlinux_start;
vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
vmlinux.size = PAGE_ALIGN(vmlinux_filesize);
vmlinux.memsize = vmlinux_memsize;
/* /*
* Now we try to claim memory for the initrd (and copy it there) * Now we try to claim memory for the initrd (and copy it there)
@ -155,11 +175,10 @@ void start(unsigned long a1, unsigned long a2, void *promptr)
/* Eventually gunzip the kernel */ /* Eventually gunzip the kernel */
if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { if (*(unsigned short *)vmlinuz.addr == 0x1f8b) {
int len;
printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...", printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...",
vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size); vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size);
len = vmlinuz.size; len = vmlinuz.size;
gunzip((void *)vmlinux.addr, vmlinux.size, gunzip((void *)vmlinux.addr, vmlinux.memsize,
(unsigned char *)vmlinuz.addr, &len); (unsigned char *)vmlinuz.addr, &len);
printf("done 0x%lx bytes\n\r", len); printf("done 0x%lx bytes\n\r", len);
} else { } else {
@ -167,32 +186,11 @@ void start(unsigned long a1, unsigned long a2, void *promptr)
} }
/* Skip over the ELF header */ /* Skip over the ELF header */
elf64 = (Elf64_Ehdr *)vmlinux.addr;
if ( elf64->e_ident[EI_MAG0] != ELFMAG0 ||
elf64->e_ident[EI_MAG1] != ELFMAG1 ||
elf64->e_ident[EI_MAG2] != ELFMAG2 ||
elf64->e_ident[EI_MAG3] != ELFMAG3 ||
elf64->e_ident[EI_CLASS] != ELFCLASS64 ||
elf64->e_ident[EI_DATA] != ELFDATA2MSB ||
elf64->e_type != ET_EXEC ||
elf64->e_machine != EM_PPC64 )
{
printf("Error: not a valid PPC64 ELF file!\n\r");
exit();
}
elf64ph = (Elf64_Phdr *)((unsigned long)elf64 +
(unsigned long)elf64->e_phoff);
for(i=0; i < (unsigned int)elf64->e_phnum ;i++,elf64ph++) {
if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0)
break;
}
#ifdef DEBUG #ifdef DEBUG
printf("... skipping 0x%lx bytes of ELF header\n\r", printf("... skipping 0x%lx bytes of ELF header\n\r",
(unsigned long)elf64ph->p_offset); (unsigned long)elf64ph->p_offset);
#endif #endif
vmlinux.addr += (unsigned long)elf64ph->p_offset; vmlinux.addr += (unsigned long)elf64ph->p_offset;
vmlinux.size -= (unsigned long)elf64ph->p_offset;
flush_cache((void *)vmlinux.addr, vmlinux.size); flush_cache((void *)vmlinux.addr, vmlinux.size);
@ -263,7 +261,7 @@ static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
s.avail_in = *lenp - i; s.avail_in = *lenp - i;
s.next_out = dst; s.next_out = dst;
s.avail_out = dstlen; s.avail_out = dstlen;
r = zlib_inflate(&s, Z_FINISH); r = zlib_inflate(&s, Z_FULL_FLUSH);
if (r != Z_OK && r != Z_STREAM_END) { if (r != Z_OK && r != Z_STREAM_END) {
printf("inflate returned %d msg: %s\n\r", r, s.msg); printf("inflate returned %d msg: %s\n\r", r, s.msg);
exit(); exit();