From 7054036fc526b741ba90ff1d077ac900362f30ed Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Fri, 28 Oct 2005 17:46:38 -0700 Subject: [PATCH] ppc64 boot: remove zlib Switch ppc64 to the in-kernel zlib, it has less bugs than the current one. The code in arch/ppc64/boot is compiled as 32bit, so it can not use the includes from include/asm. Copy all zlib related header files and convert them with sed. Reduce the scratch size to 47k, check possible changes at runtime. Signed-off-by: Olaf Hering Cc: Benjamin Herrenschmidt Cc: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/ppc64/boot/main.c | 82 ++++++++------------------------------------------ 1 file changed, 12 insertions(+), 70 deletions(-) (limited to 'arch/ppc64/boot/main.c') diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c index f7ec19a2d0b0..0b95ccfb143c 100644 --- a/arch/ppc64/boot/main.c +++ b/arch/ppc64/boot/main.c @@ -26,12 +26,6 @@ extern void flush_cache(void *, unsigned long); #define RAM_END (512<<20) // Fixme: use OF */ #define ONE_MB 0x100000 -static char *avail_ram; -static char *begin_avail, *end_avail; -static char *avail_high; -static unsigned int heap_use; -static unsigned int heap_max; - extern char _start[]; extern char _end[]; extern char _vmlinux_start[]; @@ -50,7 +44,8 @@ static struct addr_range vmlinux = {0, 0, 0}; static struct addr_range vmlinuz = {0, 0, 0}; static struct addr_range initrd = {0, 0, 0}; -static char scratch[128<<10]; /* 128kB of scratch space for gunzip */ +static char scratch[46912]; /* scratch space for gunzip, from zlib_inflate_workspacesize() */ + typedef void (*kernel_entry_t)( unsigned long, unsigned long, @@ -161,17 +156,12 @@ void start(unsigned long a1, unsigned long a2, void *promptr) /* Eventually gunzip the kernel */ if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { int len; - avail_ram = scratch; - begin_avail = avail_high = avail_ram; - end_avail = scratch + sizeof(scratch); printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...", vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size); len = vmlinuz.size; gunzip((void *)vmlinux.addr, vmlinux.size, (unsigned char *)vmlinuz.addr, &len); printf("done 0x%lx bytes\n\r", len); - printf("0x%x bytes of heap consumed, max in use 0x%x\n\r", - (unsigned)(avail_high - begin_avail), heap_max); } else { memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size); } @@ -225,64 +215,12 @@ void start(unsigned long a1, unsigned long a2, void *promptr) exit(); } -struct memchunk { - unsigned int size; - unsigned int pad; - struct memchunk *next; -}; - -static struct memchunk *freechunks; - -void *zalloc(void *x, unsigned items, unsigned size) -{ - void *p; - struct memchunk **mpp, *mp; - - size *= items; - size = _ALIGN(size, sizeof(struct memchunk)); - heap_use += size; - if (heap_use > heap_max) - heap_max = heap_use; - for (mpp = &freechunks; (mp = *mpp) != 0; mpp = &mp->next) { - if (mp->size == size) { - *mpp = mp->next; - return mp; - } - } - p = avail_ram; - avail_ram += size; - if (avail_ram > avail_high) - avail_high = avail_ram; - if (avail_ram > end_avail) { - printf("oops... out of memory\n\r"); - pause(); - } - return p; -} - -void zfree(void *x, void *addr, unsigned nb) -{ - struct memchunk *mp = addr; - - nb = _ALIGN(nb, sizeof(struct memchunk)); - heap_use -= nb; - if (avail_ram == addr + nb) { - avail_ram = addr; - return; - } - mp->size = nb; - mp->next = freechunks; - freechunks = mp; -} - #define HEAD_CRC 2 #define EXTRA_FIELD 4 #define ORIG_NAME 8 #define COMMENT 0x10 #define RESERVED 0xe0 -#define DEFLATED 8 - static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) { z_stream s; @@ -291,7 +229,7 @@ static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) /* skip header */ i = 10; flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { + if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) { printf("bad gzipped data\n\r"); exit(); } @@ -310,9 +248,13 @@ static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) exit(); } - s.zalloc = zalloc; - s.zfree = zfree; - r = inflateInit2(&s, -MAX_WBITS); + if (zlib_inflate_workspacesize() > sizeof(scratch)) { + printf("gunzip needs more mem\n"); + exit(); + } + memset(&s, 0, sizeof(s)); + s.workspace = scratch; + r = zlib_inflateInit2(&s, -MAX_WBITS); if (r != Z_OK) { printf("inflateInit2 returned %d\n\r", r); exit(); @@ -321,12 +263,12 @@ static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) s.avail_in = *lenp - i; s.next_out = dst; s.avail_out = dstlen; - r = inflate(&s, Z_FINISH); + r = zlib_inflate(&s, Z_FINISH); if (r != Z_OK && r != Z_STREAM_END) { printf("inflate returned %d msg: %s\n\r", r, s.msg); exit(); } *lenp = s.next_out - (unsigned char *) dst; - inflateEnd(&s); + zlib_inflateEnd(&s); } -- cgit v1.2.3 From 8a76baf02006c945fa4a2a01a58848cb38777697 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Fri, 28 Oct 2005 17:46:40 -0700 Subject: [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 Cc: Benjamin Herrenschmidt Cc: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/ppc64/boot/main.c | 80 ++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 41 deletions(-) (limited to 'arch/ppc64/boot/main.c') diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c index 0b95ccfb143c..7485dcbf80bc 100644 --- a/arch/ppc64/boot/main.c +++ b/arch/ppc64/boot/main.c @@ -32,8 +32,6 @@ extern char _vmlinux_start[]; extern char _vmlinux_end[]; extern char _initrd_start[]; extern char _initrd_end[]; -extern unsigned long vmlinux_filesize; -extern unsigned long vmlinux_memsize; struct addr_range { unsigned long addr; @@ -45,6 +43,7 @@ static struct addr_range vmlinuz = {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 elfheader[256]; 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) { unsigned long i; + int len; kernel_entry_t kernel_entry; Elf64_Ehdr *elf64; Elf64_Phdr *elf64ph; @@ -113,25 +113,45 @@ void start(unsigned long a1, unsigned long a2, void *promptr) claim_base = PROG_START; #endif - /* - * Now we try to claim some memory for the kernel itself - * our "vmlinux_memsize" is the memory footprint in RAM, _HOWEVER_, what - * our Makefile stuffs in is an image containing all sort of junk including - * an ELF header. We need to do some calculations here to find the right - * size... In practice we add 1Mb, that is enough, but we should really - * consider fixing the Makefile to put a _raw_ kernel in there ! - */ - vmlinux_memsize += ONE_MB; - printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux_memsize); - vmlinux.addr = try_claim(vmlinux_memsize); + vmlinuz.addr = (unsigned long)_vmlinux_start; + vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); + + /* gunzip the ELF header of the kernel */ + if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { + len = vmlinuz.size; + gunzip(elfheader, sizeof(elfheader), + (unsigned char *)vmlinuz.addr, &len); + } else + memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader)); + + 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) { printf("Can't allocate memory for kernel image !\n\r"); 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) @@ -155,11 +175,10 @@ void start(unsigned long a1, unsigned long a2, void *promptr) /* Eventually gunzip the kernel */ if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { - int len; printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...", vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size); len = vmlinuz.size; - gunzip((void *)vmlinux.addr, vmlinux.size, + gunzip((void *)vmlinux.addr, vmlinux.memsize, (unsigned char *)vmlinuz.addr, &len); printf("done 0x%lx bytes\n\r", len); } else { @@ -167,32 +186,11 @@ void start(unsigned long a1, unsigned long a2, void *promptr) } /* 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 printf("... skipping 0x%lx bytes of ELF header\n\r", (unsigned long)elf64ph->p_offset); #endif vmlinux.addr += (unsigned long)elf64ph->p_offset; - vmlinux.size -= (unsigned long)elf64ph->p_offset; 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.next_out = dst; 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) { printf("inflate returned %d msg: %s\n\r", r, s.msg); exit(); -- cgit v1.2.3 From 6bcc20b5ade6c8e9d9a0767090c65024047d91c4 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Fri, 28 Oct 2005 17:46:41 -0700 Subject: [PATCH] ppc64 boot: move gunzip function before use Move the gunzip function up. Signed-off-by: Olaf Hering Cc: Benjamin Herrenschmidt Cc: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/ppc64/boot/main.c | 115 ++++++++++++++++++++++++------------------------- 1 file changed, 57 insertions(+), 58 deletions(-) (limited to 'arch/ppc64/boot/main.c') diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c index 7485dcbf80bc..d039c47f8e5a 100644 --- a/arch/ppc64/boot/main.c +++ b/arch/ppc64/boot/main.c @@ -17,7 +17,6 @@ #include "prom.h" #include "zlib.h" -static void gunzip(void *, int, unsigned char *, int *); extern void flush_cache(void *, unsigned long); @@ -56,6 +55,63 @@ typedef void (*kernel_entry_t)( unsigned long, static unsigned long claim_base; +#define HEAD_CRC 2 +#define EXTRA_FIELD 4 +#define ORIG_NAME 8 +#define COMMENT 0x10 +#define RESERVED 0xe0 + +static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) +{ + z_stream s; + int r, i, flags; + + /* skip header */ + i = 10; + flags = src[3]; + if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) { + printf("bad gzipped data\n\r"); + exit(); + } + if ((flags & EXTRA_FIELD) != 0) + i = 12 + src[10] + (src[11] << 8); + if ((flags & ORIG_NAME) != 0) + while (src[i++] != 0) + ; + if ((flags & COMMENT) != 0) + while (src[i++] != 0) + ; + if ((flags & HEAD_CRC) != 0) + i += 2; + if (i >= *lenp) { + printf("gunzip: ran out of data in header\n\r"); + exit(); + } + + if (zlib_inflate_workspacesize() > sizeof(scratch)) { + printf("gunzip needs more mem\n"); + exit(); + } + memset(&s, 0, sizeof(s)); + s.workspace = scratch; + r = zlib_inflateInit2(&s, -MAX_WBITS); + if (r != Z_OK) { + printf("inflateInit2 returned %d\n\r", r); + exit(); + } + s.next_in = src + i; + s.avail_in = *lenp - i; + s.next_out = dst; + s.avail_out = dstlen; + r = zlib_inflate(&s, Z_FULL_FLUSH); + if (r != Z_OK && r != Z_STREAM_END) { + printf("inflate returned %d msg: %s\n\r", r, s.msg); + exit(); + } + *lenp = s.next_out - (unsigned char *) dst; + zlib_inflateEnd(&s); +} + static unsigned long try_claim(unsigned long size) { unsigned long addr = 0; @@ -213,60 +269,3 @@ void start(unsigned long a1, unsigned long a2, void *promptr) exit(); } -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) -{ - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) { - printf("bad gzipped data\n\r"); - exit(); - } - if ((flags & EXTRA_FIELD) != 0) - i = 12 + src[10] + (src[11] << 8); - if ((flags & ORIG_NAME) != 0) - while (src[i++] != 0) - ; - if ((flags & COMMENT) != 0) - while (src[i++] != 0) - ; - if ((flags & HEAD_CRC) != 0) - i += 2; - if (i >= *lenp) { - printf("gunzip: ran out of data in header\n\r"); - exit(); - } - - if (zlib_inflate_workspacesize() > sizeof(scratch)) { - printf("gunzip needs more mem\n"); - exit(); - } - memset(&s, 0, sizeof(s)); - s.workspace = scratch; - r = zlib_inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - printf("inflateInit2 returned %d\n\r", r); - exit(); - } - s.next_in = src + i; - s.avail_in = *lenp - i; - s.next_out = dst; - s.avail_out = dstlen; - r = zlib_inflate(&s, Z_FULL_FLUSH); - if (r != Z_OK && r != Z_STREAM_END) { - printf("inflate returned %d msg: %s\n\r", r, s.msg); - exit(); - } - *lenp = s.next_out - (unsigned char *) dst; - zlib_inflateEnd(&s); -} - -- cgit v1.2.3 From 9b0cbe97566dd7123eee0462d91703434fe61090 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Fri, 28 Oct 2005 17:46:45 -0700 Subject: [PATCH] ppc64 boot: use memset to clear bss Use memset to clear bss, instead of own version. Signed-off-by: Olaf Hering Cc: Benjamin Herrenschmidt Cc: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/ppc64/boot/main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/ppc64/boot/main.c') diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c index d039c47f8e5a..c2c1f3309113 100644 --- a/arch/ppc64/boot/main.c +++ b/arch/ppc64/boot/main.c @@ -26,6 +26,7 @@ extern void flush_cache(void *, unsigned long); #define ONE_MB 0x100000 extern char _start[]; +extern char __bss_start[]; extern char _end[]; extern char _vmlinux_start[]; extern char _vmlinux_end[]; @@ -138,6 +139,8 @@ void start(unsigned long a1, unsigned long a2, void *promptr) Elf64_Ehdr *elf64; Elf64_Phdr *elf64ph; + memset(__bss_start, 0, _end - __bss_start); + prom = (int (*)(void *)) promptr; chosen_handle = finddevice("/chosen"); if (chosen_handle == (void *) -1) -- cgit v1.2.3 From afbe8c4bb0155f533d6e57edd269c93e2f23c2fa Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Fri, 28 Oct 2005 17:46:47 -0700 Subject: [PATCH] ppc64 boot: remove global initializers No need to initialize global variables. Signed-off-by: Olaf Hering Cc: Benjamin Herrenschmidt Cc: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/ppc64/boot/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/ppc64/boot/main.c') diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c index c2c1f3309113..3304ed34c44b 100644 --- a/arch/ppc64/boot/main.c +++ b/arch/ppc64/boot/main.c @@ -38,9 +38,9 @@ struct addr_range { unsigned long size; unsigned long memsize; }; -static struct addr_range vmlinux = {0, 0, 0}; -static struct addr_range vmlinuz = {0, 0, 0}; -static struct addr_range initrd = {0, 0, 0}; +static struct addr_range vmlinux; +static struct addr_range vmlinuz; +static struct addr_range initrd; static char scratch[46912]; /* scratch space for gunzip, from zlib_inflate_workspacesize() */ static char elfheader[256]; -- cgit v1.2.3 From 7e658118faa9faf71f8a8295cdaeb7ca71c04672 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Fri, 28 Oct 2005 17:46:50 -0700 Subject: [PATCH] ppc64 boot: print firmware provided stackpointer Show firmware provided stackpointer during boot. This helps to find the "taboo" areas on the various boards. claim tends to fail for these memory areas, but some jokers return success anyway. Use %p to print the load address, its a pointer. Signed-off-by: Olaf Hering Cc: Benjamin Herrenschmidt Cc: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/ppc64/boot/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/ppc64/boot/main.c') diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c index 3304ed34c44b..c1dc876bccab 100644 --- a/arch/ppc64/boot/main.c +++ b/arch/ppc64/boot/main.c @@ -131,7 +131,7 @@ static unsigned long try_claim(unsigned long size) return addr; } -void start(unsigned long a1, unsigned long a2, void *promptr) +void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) { unsigned long i; int len; @@ -151,7 +151,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr) if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4) exit(); - printf("\n\rzImage starting: loaded at 0x%lx\n\r", (unsigned long) _start); + printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp); /* * The first available claim_base must be above the end of the -- cgit v1.2.3