aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2007-03-04 22:24:52 -0500
committerPaul Mackerras <paulus@samba.org>2007-03-12 22:35:03 -0400
commitcd197ffcf10bcc1a260efe5c09a3188fd9228c83 (patch)
tree280d1c3026b263fbdb95961ae77efb79739e8daf
parent79c8541924a220964f9f2cbed31eaa9fdb042eab (diff)
[POWERPC] zImage: Cleanup and improve zImage entry point
This patch re-organises the way the zImage wrapper code is entered, to allow more flexibility on platforms with unusual entry conditions. After this patch, a platform .o file has two options: 1) It can define a _zimage_start, in which case the platform code gets control from the very beginning of execution. In this case the platform code is responsible for relocating the zImage if necessary, clearing the BSS, performing any platform specific initialization, and finally calling start() to load and enter the kernel. 2) It can define platform_init(). In this case the generic crt0.S handles initial entry, and calls platform_init() before calling start(). The signature of platform_init() is changed, however, to take up to 5 parameters (in r3..r7) as they come from the platform's initial loader, instead of a fixed set of parameters based on OF's usage. When using the generic crt0.S, the platform .o can optionally supply a custom stack to use, using the BSS_STACK() macro. If this is not supplied, the crt0.S will assume that the loader has supplied a usable stack. In either case, the platform code communicates information to the generic code (specifically, a PROM pointer for OF systems, and/or an initrd image address supplied by the bootloader) via a global structure "loader_info". In addition the wrapper script is rearranged to ensure that the platform .o is always linked first. This means that platforms where the zImage entry point is at a fixed address or offset, rather than being encoded in the binary header can be supported using option (1). Signed-off-by: David Gibson <dwg@au1.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/boot/Makefile6
-rw-r--r--arch/powerpc/boot/crt0.S32
-rw-r--r--arch/powerpc/boot/main.c18
-rw-r--r--arch/powerpc/boot/of.c6
-rw-r--r--arch/powerpc/boot/ops.h12
-rwxr-xr-xarch/powerpc/boot/wrapper6
-rw-r--r--arch/powerpc/boot/zImage.coff.lds.S3
-rw-r--r--arch/powerpc/boot/zImage.lds.S1
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
40$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \ 40$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \
41 $(addprefix $(obj)/,$(zlibheader)) 41 $(addprefix $(obj)/,$(zlibheader))
42 42
43src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ 43src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
44 ns16550.c serial.c simple_alloc.c div64.S util.S \ 44 ns16550.c serial.c simple_alloc.c div64.S util.S \
45 gunzip_util.c $(zlib) 45 gunzip_util.c $(zlib)
46src-plat := of.c 46src-plat := of.c
47src-boot := crt0.S $(src-wlib) $(src-plat) empty.c 47src-boot := $(src-wlib) $(src-plat) empty.c
48 48
49src-boot := $(addprefix $(obj)/, $(src-boot)) 49src-boot := $(addprefix $(obj)/, $(src-boot))
50obj-boot := $(addsuffix .o, $(basename $(src-boot))) 50obj-boot := $(addsuffix .o, $(basename $(src-boot)))
@@ -97,7 +97,7 @@ $(obj)/wrapper.a: $(obj-wlib)
97 97
98hostprogs-y := addnote addRamDisk hack-coff mktree 98hostprogs-y := addnote addRamDisk hack-coff mktree
99 99
100extra-y := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ 100extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
101 $(obj)/zImage.lds $(obj)/zImage.coff.lds 101 $(obj)/zImage.lds $(obj)/zImage.coff.lds
102 102
103wrapper :=$(srctree)/$(src)/wrapper 103wrapper :=$(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 @@
16_zimage_start_opd: 16_zimage_start_opd:
17 .long _zimage_start, 0, 0, 0 17 .long _zimage_start, 0, 0, 0
18 18
19 .weak _zimage_start
19 .globl _zimage_start 20 .globl _zimage_start
20_zimage_start: 21_zimage_start:
21 /* Work out the offset between the address we were linked at 22 /* Work out the offset between the address we were linked at
@@ -44,7 +45,7 @@ _zimage_start:
44 addi r9,r9,4 45 addi r9,r9,4
45 bdnz 2b 46 bdnz 2b
46 47
47 /* Do a cache flush for our text, in case OF didn't */ 48 /* Do a cache flush for our text, in case the loader didn't */
483: lis r9,_start@ha 493: lis r9,_start@ha
49 addi r9,r9,_start@l 50 addi r9,r9,_start@l
50 add r9,r0,r9 51 add r9,r0,r9
@@ -59,6 +60,31 @@ _zimage_start:
59 sync 60 sync
60 isync 61 isync
61 62
62 mr r6,r1 63 /* Clear the BSS */
63 b start 64 lis r9,__bss_start@ha
65 addi r9,r9,__bss_start@l
66 lis r8,_end@ha
67 addi r8,r8,_end@l
68 li r0,0
695: stw r0,0(r9)
70 addi r9,r9,4
71 cmplw cr0,r9,r8
72 blt 5b
64 73
74 /* Possibly set up a custom stack */
75.weak _platform_stack_top
76 lis r8,_platform_stack_top@ha
77 addi r8,r8,_platform_stack_top@l
78 cmpwi r8,0
79 beq 6f
80 lwz r1,0(r8)
81 li r0,0
82 stwu r0,-16(r1) /* establish a stack frame */
836:
84
85 /* Call platform_init() */
86 bl platform_init
87
88 /* Call start */
89 mr r3,r1
90 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)
254struct platform_ops platform_ops; 254struct platform_ops platform_ops;
255struct dt_ops dt_ops; 255struct dt_ops dt_ops;
256struct console_ops console_ops; 256struct console_ops console_ops;
257struct loader_info loader_info;
257 258
258void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) 259void start(void *sp)
259{ 260{
260 struct addr_range vmlinux, initrd; 261 struct addr_range vmlinux, initrd;
261 kernel_entry_t kentry; 262 kernel_entry_t kentry;
262 char cmdline[COMMAND_LINE_SIZE]; 263 char cmdline[COMMAND_LINE_SIZE];
263 unsigned long ft_addr = 0; 264 unsigned long ft_addr = 0;
264 265
265 memset(__bss_start, 0, _end - __bss_start);
266 memset(&platform_ops, 0, sizeof(platform_ops));
267 memset(&dt_ops, 0, sizeof(dt_ops));
268 memset(&console_ops, 0, sizeof(console_ops));
269
270 if (platform_init(promptr, _dtb_start, _dtb_end))
271 exit();
272 if (console_ops.open && (console_ops.open() < 0)) 266 if (console_ops.open && (console_ops.open() < 0))
273 exit(); 267 exit();
274 if (platform_ops.fixups) 268 if (platform_ops.fixups)
@@ -278,7 +272,8 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
278 _start, sp); 272 _start, sp);
279 273
280 vmlinux = prep_kernel(); 274 vmlinux = prep_kernel();
281 initrd = prep_initrd(vmlinux, a1, a2); 275 initrd = prep_initrd(vmlinux, loader_info.initrd_addr,
276 loader_info.initrd_size);
282 277
283 /* If cmdline came from zimage wrapper or if we can edit the one 278 /* If cmdline came from zimage wrapper or if we can edit the one
284 * in the dt, print it out and edit it, if possible. 279 * 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)
298 if (ft_addr) 293 if (ft_addr)
299 printf(" flat tree at 0x%lx\n\r", ft_addr); 294 printf(" flat tree at 0x%lx\n\r", ft_addr);
300 else 295 else
301 printf(" using OF tree (promptr=%p)\n\r", promptr); 296 printf(" using OF tree (promptr=%p)\n\r", loader_info.promptr);
302 297
303 if (console_ops.close) 298 if (console_ops.close)
304 console_ops.close(); 299 console_ops.close();
@@ -307,7 +302,8 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
307 if (ft_addr) 302 if (ft_addr)
308 kentry(ft_addr, 0, NULL); 303 kentry(ft_addr, 0, NULL);
309 else 304 else
310 kentry((unsigned long)initrd.addr, initrd.size, promptr); 305 kentry((unsigned long)initrd.addr, initrd.size,
306 loader_info.promptr);
311 307
312 /* console closed so printf below may not work */ 308 /* console closed so printf below may not work */
313 printf("Error: Linux kernel returned to zImage boot wrapper!\n\r"); 309 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)
267 call_prom("write", 3, 1, of_stdout_handle, buf, len); 267 call_prom("write", 3, 1, of_stdout_handle, buf, len);
268} 268}
269 269
270int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end) 270void platform_init(unsigned long a1, unsigned long a2, void *promptr)
271{ 271{
272 platform_ops.image_hdr = of_image_hdr; 272 platform_ops.image_hdr = of_image_hdr;
273 platform_ops.malloc = of_try_claim; 273 platform_ops.malloc = of_try_claim;
@@ -282,5 +282,7 @@ int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end)
282 console_ops.write = of_console_write; 282 console_ops.write = of_console_write;
283 283
284 prom = (int (*)(void *))promptr; 284 prom = (int (*)(void *))promptr;
285 return 0; 285 loader_info.promptr = promptr;
286 loader_info.initrd_addr = a1;
287 loader_info.initrd_size = a2;
286} 288}
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 {
59 void (*close)(void); 59 void (*close)(void);
60}; 60};
61 61
62int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end); 62struct loader_info {
63 void *promptr;
64 unsigned long initrd_addr, initrd_size;
65};
66extern struct loader_info loader_info;
67
68void start(void *sp);
63int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device); 69int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
64int serial_console_init(void); 70int serial_console_init(void);
65int ns16550_console_init(void *devp, struct serial_console_data *scdp); 71int ns16550_console_init(void *devp, struct serial_console_data *scdp);
@@ -100,4 +106,8 @@ static inline void exit(void)
100 for(;;); 106 for(;;);
101} 107}
102 108
109#define BSS_STACK(size) \
110 static char _bss_stack[size]; \
111 void *_platform_stack_top = _bss_stack + sizeof(_bss_stack);
112
103#endif /* _PPC_BOOT_OPS_H_ */ 113#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
191 191
192if [ "$platform" != "miboot" ]; then 192if [ "$platform" != "miboot" ]; then
193 ${CROSS}ld -m elf32ppc -T $lds -o "$ofile" \ 193 ${CROSS}ld -m elf32ppc -T $lds -o "$ofile" \
194 $object/crt0.o $platformo $tmp $object/wrapper.a 194 $platformo $tmp $object/wrapper.a
195 rm $tmp 195 rm $tmp
196fi 196fi
197 197
@@ -201,7 +201,9 @@ pseries|chrp)
201 $object/addnote "$ofile" 201 $object/addnote "$ofile"
202 ;; 202 ;;
203pmaccoff) 203pmaccoff)
204 ${CROSS}objcopy -O aixcoff-rs6000 --set-start 0x500000 "$ofile" 204 entry=`objdump -f "$ofile" | grep '^start address ' | \
205 cut -d' ' -f3`
206 ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile"
205 $object/hack-coff "$ofile" 207 $object/hack-coff "$ofile"
206 ;; 208 ;;
207esac 209esac
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 @@
1OUTPUT_ARCH(powerpc:common) 1OUTPUT_ARCH(powerpc:common)
2ENTRY(_start) 2ENTRY(_zimage_start_opd)
3EXTERN(_zimage_start_opd)
3SECTIONS 4SECTIONS
4{ 5{
5 . = (5*1024*1024); 6 . = (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 @@
1OUTPUT_ARCH(powerpc:common) 1OUTPUT_ARCH(powerpc:common)
2ENTRY(_zimage_start) 2ENTRY(_zimage_start)
3EXTERN(_zimage_start)
3SECTIONS 4SECTIONS
4{ 5{
5 . = (4*1024*1024); 6 . = (4*1024*1024);