diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/boot/Makefile | 6 | ||||
-rw-r--r-- | arch/powerpc/boot/crt0.S | 32 | ||||
-rw-r--r-- | arch/powerpc/boot/main.c | 18 | ||||
-rw-r--r-- | arch/powerpc/boot/of.c | 6 | ||||
-rw-r--r-- | arch/powerpc/boot/ops.h | 12 | ||||
-rwxr-xr-x | arch/powerpc/boot/wrapper | 6 | ||||
-rw-r--r-- | arch/powerpc/boot/zImage.coff.lds.S | 3 | ||||
-rw-r--r-- | arch/powerpc/boot/zImage.lds.S | 1 |
8 files changed, 61 insertions, 23 deletions
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 3628d8681844..b1fc029e5ea7 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -40,11 +40,11 @@ zliblinuxheader := zlib.h zconf.h zutil.h $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \ $(addprefix $(obj)/,$(zlibheader)) -src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ +src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ ns16550.c serial.c simple_alloc.c div64.S util.S \ gunzip_util.c $(zlib) src-plat := of.c -src-boot := crt0.S $(src-wlib) $(src-plat) empty.c +src-boot := $(src-wlib) $(src-plat) empty.c src-boot := $(addprefix $(obj)/, $(src-boot)) obj-boot := $(addsuffix .o, $(basename $(src-boot))) @@ -97,7 +97,7 @@ $(obj)/wrapper.a: $(obj-wlib) hostprogs-y := addnote addRamDisk hack-coff mktree -extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ +extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ $(obj)/zImage.lds $(obj)/zImage.coff.lds wrapper :=$(srctree)/$(src)/wrapper diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S index 70e65b13e033..3dc8d8f78499 100644 --- a/arch/powerpc/boot/crt0.S +++ b/arch/powerpc/boot/crt0.S @@ -16,6 +16,7 @@ _zimage_start_opd: .long _zimage_start, 0, 0, 0 + .weak _zimage_start .globl _zimage_start _zimage_start: /* Work out the offset between the address we were linked at @@ -44,7 +45,7 @@ _zimage_start: addi r9,r9,4 bdnz 2b - /* Do a cache flush for our text, in case OF didn't */ + /* Do a cache flush for our text, in case the loader didn't */ 3: lis r9,_start@ha addi r9,r9,_start@l add r9,r0,r9 @@ -59,6 +60,31 @@ _zimage_start: sync isync - mr r6,r1 - b start + /* Clear the BSS */ + lis r9,__bss_start@ha + addi r9,r9,__bss_start@l + lis r8,_end@ha + addi r8,r8,_end@l + li r0,0 +5: stw r0,0(r9) + addi r9,r9,4 + cmplw cr0,r9,r8 + blt 5b + /* Possibly set up a custom stack */ +.weak _platform_stack_top + lis r8,_platform_stack_top@ha + addi r8,r8,_platform_stack_top@l + cmpwi r8,0 + beq 6f + lwz r1,0(r8) + li r0,0 + stwu r0,-16(r1) /* establish a stack frame */ +6: + + /* Call platform_init() */ + bl platform_init + + /* Call start */ + mr r3,r1 + b start diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index 05de6cfafeeb..8a60e13777d7 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c @@ -254,21 +254,15 @@ static void set_cmdline(char *buf) struct platform_ops platform_ops; struct dt_ops dt_ops; struct console_ops console_ops; +struct loader_info loader_info; -void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) +void start(void *sp) { struct addr_range vmlinux, initrd; kernel_entry_t kentry; char cmdline[COMMAND_LINE_SIZE]; unsigned long ft_addr = 0; - memset(__bss_start, 0, _end - __bss_start); - memset(&platform_ops, 0, sizeof(platform_ops)); - memset(&dt_ops, 0, sizeof(dt_ops)); - memset(&console_ops, 0, sizeof(console_ops)); - - if (platform_init(promptr, _dtb_start, _dtb_end)) - exit(); if (console_ops.open && (console_ops.open() < 0)) exit(); if (platform_ops.fixups) @@ -278,7 +272,8 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) _start, sp); vmlinux = prep_kernel(); - initrd = prep_initrd(vmlinux, a1, a2); + initrd = prep_initrd(vmlinux, loader_info.initrd_addr, + loader_info.initrd_size); /* If cmdline came from zimage wrapper or if we can edit the one * in the dt, print it out and edit it, if possible. @@ -298,7 +293,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) if (ft_addr) printf(" flat tree at 0x%lx\n\r", ft_addr); else - printf(" using OF tree (promptr=%p)\n\r", promptr); + printf(" using OF tree (promptr=%p)\n\r", loader_info.promptr); if (console_ops.close) console_ops.close(); @@ -307,7 +302,8 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) if (ft_addr) kentry(ft_addr, 0, NULL); else - kentry((unsigned long)initrd.addr, initrd.size, promptr); + kentry((unsigned long)initrd.addr, initrd.size, + loader_info.promptr); /* console closed so printf below may not work */ printf("Error: Linux kernel returned to zImage boot wrapper!\n\r"); diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c index 044f34770b96..c6f0d9701485 100644 --- a/arch/powerpc/boot/of.c +++ b/arch/powerpc/boot/of.c @@ -267,7 +267,7 @@ static void of_console_write(char *buf, int len) call_prom("write", 3, 1, of_stdout_handle, buf, len); } -int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end) +void platform_init(unsigned long a1, unsigned long a2, void *promptr) { platform_ops.image_hdr = of_image_hdr; platform_ops.malloc = of_try_claim; @@ -282,5 +282,7 @@ int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end) console_ops.write = of_console_write; prom = (int (*)(void *))promptr; - return 0; + loader_info.promptr = promptr; + loader_info.initrd_addr = a1; + loader_info.initrd_size = a2; } diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index fa62ff223e70..cad4eee599fb 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h @@ -59,7 +59,13 @@ struct serial_console_data { void (*close)(void); }; -int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end); +struct loader_info { + void *promptr; + unsigned long initrd_addr, initrd_size; +}; +extern struct loader_info loader_info; + +void start(void *sp); int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device); int serial_console_init(void); int ns16550_console_init(void *devp, struct serial_console_data *scdp); @@ -100,4 +106,8 @@ static inline void exit(void) for(;;); } +#define BSS_STACK(size) \ + static char _bss_stack[size]; \ + void *_platform_stack_top = _bss_stack + sizeof(_bss_stack); + #endif /* _PPC_BOOT_OPS_H_ */ diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index 024e4d425c59..157d8c89e138 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper @@ -191,7 +191,7 @@ fi if [ "$platform" != "miboot" ]; then ${CROSS}ld -m elf32ppc -T $lds -o "$ofile" \ - $object/crt0.o $platformo $tmp $object/wrapper.a + $platformo $tmp $object/wrapper.a rm $tmp fi @@ -201,7 +201,9 @@ pseries|chrp) $object/addnote "$ofile" ;; pmaccoff) - ${CROSS}objcopy -O aixcoff-rs6000 --set-start 0x500000 "$ofile" + entry=`objdump -f "$ofile" | grep '^start address ' | \ + cut -d' ' -f3` + ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile" $object/hack-coff "$ofile" ;; esac diff --git a/arch/powerpc/boot/zImage.coff.lds.S b/arch/powerpc/boot/zImage.coff.lds.S index a360905e5428..fe87a90ce7f1 100644 --- a/arch/powerpc/boot/zImage.coff.lds.S +++ b/arch/powerpc/boot/zImage.coff.lds.S @@ -1,5 +1,6 @@ OUTPUT_ARCH(powerpc:common) -ENTRY(_start) +ENTRY(_zimage_start_opd) +EXTERN(_zimage_start_opd) SECTIONS { . = (5*1024*1024); diff --git a/arch/powerpc/boot/zImage.lds.S b/arch/powerpc/boot/zImage.lds.S index 4be3c6414b04..f6e380fdb388 100644 --- a/arch/powerpc/boot/zImage.lds.S +++ b/arch/powerpc/boot/zImage.lds.S @@ -1,5 +1,6 @@ OUTPUT_ARCH(powerpc:common) ENTRY(_zimage_start) +EXTERN(_zimage_start) SECTIONS { . = (4*1024*1024); |