2 * Originally adapted by Gary Thomas. Much additional work by
3 * Cort Dougan <cort@fsmlabs.com>. On top of that still more work by
4 * Dan Malek <dmalek@jlc.net>.
6 * Currently maintained by: Tom Rini <trini@kernel.crashing.org>
9 #include <linux/types.h>
10 #include <linux/string.h>
11 #include <asm/bootinfo.h>
14 #include <asm/residual.h>
15 #if defined(CONFIG_4xx)
16 #include <asm/ibm4xx.h>
17 #elif defined(CONFIG_8xx)
18 #include <asm/mpc8xx.h>
19 #elif defined(CONFIG_8260)
20 #include <asm/mpc8260.h>
25 /* The linker tells us where the image is. */
26 extern char __image_begin
, __image_end
;
27 extern char __ramdisk_begin
, __ramdisk_end
;
30 /* Because of the limited amount of memory on embedded, it presents
31 * loading problems. The biggest is that we load this boot program
32 * into a relatively low memory address, and the Linux kernel Bss often
33 * extends into this space when it get loaded. When the kernel starts
34 * and zeros the BSS space, it also writes over the information we
35 * save here and pass to the kernel (usually board info).
36 * On these boards, we grab some known memory holes to hold this information.
39 char *cmd_line
= cmd_buf
;
44 /* This is for 4xx treeboot. It provides a place for the bootrom
45 * give us a pointer to a rom environment command line.
47 char *bootrom_cmdline
= "";
49 /* This is the default cmdline that will be given to the user at boot time..
50 * If none was specified at compile time, we'll give it one that should work.
52 #ifdef CONFIG_CMDLINE_BOOL
53 char compiled_string
[] = CONFIG_CMDLINE
;
55 char ramroot_string
[] = "root=/dev/ram";
56 char netroot_string
[] = "root=/dev/nfs rw ip=on";
58 /* Serial port to use. */
59 unsigned long com_port
;
61 /* We need to make sure that this is before the images to ensure
62 * that it's in a mapped location. - Tom */
63 bd_t hold_resid_buf
__attribute__ ((__section__ (".data.boot")));
64 bd_t
*hold_residual
= &hold_resid_buf
;
66 extern unsigned long serial_init(int chan
, bd_t
*bp
);
67 extern void serial_close(unsigned long com_port
);
68 extern unsigned long start
;
69 extern void flush_instruction_cache(void);
70 extern void gunzip(void *, int, unsigned char *, int *);
71 extern void embed_config(bd_t
**bp
);
73 /* Weak function for boards which don't need to build the
74 * board info struct because they are using PPCBoot/U-Boot.
76 void __attribute__ ((weak
))
77 embed_config(bd_t
**bdp
)
82 load_kernel(unsigned long load_addr
, int num_words
, unsigned long cksum
, bd_t
*bp
)
85 int timer
= 0, zimage_size
;
86 unsigned long initrd_size
;
88 /* First, capture the embedded board information. Then
89 * initialize the serial console port.
92 #if defined(CONFIG_SERIAL_CPM_CONSOLE) || \
93 defined(CONFIG_SERIAL_8250_CONSOLE) || \
94 defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
95 com_port
= serial_init(0, bp
);
98 /* Grab some space for the command line and board info. Since
99 * we no longer use the ELF header, but it was loaded, grab
103 /* Because of the way the MBX loads the ELF image, we can't
104 * tell where we started. We read a magic variable from the NVRAM
105 * that gives us the intermediate buffer load address.
107 load_addr
= *(uint
*)0xfa000020;
108 load_addr
+= 0x10000; /* Skip ELF header */
110 /* copy board data */
112 memcpy(hold_residual
,bp
,sizeof(bd_t
));
114 /* Set end of memory available to us. It is always the highest
115 * memory address provided by the board information.
117 end_avail
= (char *)(bp
->bi_memsize
);
119 puts("\nloaded at: "); puthex(load_addr
);
120 puts(" "); puthex((unsigned long)(load_addr
+ (4*num_words
))); puts("\n");
121 if ( (unsigned long)load_addr
!= (unsigned long)&start
) {
122 puts("relocated to: "); puthex((unsigned long)&start
);
124 puthex((unsigned long)((unsigned long)&start
+ (4*num_words
)));
129 puts("board data at: "); puthex((unsigned long)bp
);
131 puthex((unsigned long)((unsigned long)bp
+ sizeof(bd_t
)));
132 puts("\nrelocated to: ");
133 puthex((unsigned long)hold_residual
);
135 puthex((unsigned long)((unsigned long)hold_residual
+ sizeof(bd_t
)));
140 * We link ourself to an arbitrary low address. When we run, we
141 * relocate ourself to that address. __image_being points to
142 * the part of the image where the zImage is. -- Tom
144 zimage_start
= (char *)(unsigned long)(&__image_begin
);
145 zimage_size
= (unsigned long)(&__image_end
) -
146 (unsigned long)(&__image_begin
);
148 initrd_size
= (unsigned long)(&__ramdisk_end
) -
149 (unsigned long)(&__ramdisk_begin
);
152 * The zImage and initrd will be between start and _end, so they've
153 * already been moved once. We're good to go now. -- Tom
155 puts("zimage at: "); puthex((unsigned long)zimage_start
);
156 puts(" "); puthex((unsigned long)(zimage_size
+zimage_start
));
161 puthex((unsigned long)(&__ramdisk_begin
));
162 puts(" "); puthex((unsigned long)(&__ramdisk_end
));puts("\n");
166 * setup avail_ram - this is the first part of ram usable
167 * by the uncompress code. Anything after this program in RAM
168 * is now fair game. -- Tom
170 avail_ram
= (char *)PAGE_ALIGN((unsigned long)_end
);
172 puts("avail ram: "); puthex((unsigned long)avail_ram
); puts(" ");
173 puthex((unsigned long)end_avail
); puts("\n");
174 puts("\nLinux/PPC load: ");
176 /* This is where we try and pick the right command line for booting.
177 * If we were given one at compile time, use it. It Is Right.
178 * If we weren't, see if we have a ramdisk. If so, thats root.
179 * When in doubt, give them the netroot (root=/dev/nfs rw) -- Tom
181 #ifdef CONFIG_CMDLINE_BOOL
182 memcpy (cmd_line
, compiled_string
, sizeof(compiled_string
));
185 memcpy (cmd_line
, ramroot_string
, sizeof(ramroot_string
));
187 memcpy (cmd_line
, netroot_string
, sizeof(netroot_string
));
191 while (timer
++ < 5*1000) {
193 while ((ch
= getc()) != '\n' && ch
!= '\r') {
194 if (ch
== '\b' || ch
== '\177') {
195 if (cp
!= cmd_line
) {
199 } else if (ch
== '\030' /* ^x */
200 || ch
== '\025') { /* ^u */
201 while (cp
!= cmd_line
) {
210 break; /* Exit 'timer' loop */
212 udelay(1000); /* 1 msec */
215 puts("\nUncompressing Linux...");
217 gunzip(0, 0x400000, zimage_start
, &zimage_size
);
218 flush_instruction_cache();
221 struct bi_record
*rec
;
222 unsigned long initrd_loc
= 0;
223 unsigned long rec_loc
= _ALIGN((unsigned long)(zimage_size
) +
224 (1 << 20) - 1, (1 << 20));
225 rec
= (struct bi_record
*)rec_loc
;
227 /* We need to make sure that the initrd and bi_recs do not
230 initrd_loc
= (unsigned long)(&__ramdisk_begin
);
231 /* If the bi_recs are in the middle of the current
232 * initrd, move the initrd to the next MB
234 if ((rec_loc
> initrd_loc
) &&
235 ((initrd_loc
+ initrd_size
)
237 initrd_loc
= _ALIGN((unsigned long)(zimage_size
)
238 + (2 << 20) - 1, (2 << 20));
239 memmove((void *)initrd_loc
, &__ramdisk_begin
,
241 puts("initrd moved: "); puthex(initrd_loc
);
242 puts(" "); puthex(initrd_loc
+ initrd_size
);
248 rec
->size
= sizeof(struct bi_record
);
249 rec
= (struct bi_record
*)((unsigned long)rec
+ rec
->size
);
251 rec
->tag
= BI_CMD_LINE
;
252 memcpy( (char *)rec
->data
, cmd_line
, strlen(cmd_line
)+1);
253 rec
->size
= sizeof(struct bi_record
) + strlen(cmd_line
) + 1;
254 rec
= (struct bi_record
*)((unsigned long)rec
+ rec
->size
);
257 rec
->tag
= BI_INITRD
;
258 rec
->data
[0] = initrd_loc
;
259 rec
->data
[1] = initrd_size
;
260 rec
->size
= sizeof(struct bi_record
) + 2 *
261 sizeof(unsigned long);
262 rec
= (struct bi_record
*)((unsigned long)rec
+
267 rec
->size
= sizeof(struct bi_record
);
268 rec
= (struct bi_record
*)((unsigned long)rec
+ rec
->size
);
270 puts("Now booting the kernel\n");
271 #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
272 serial_close(com_port
);
275 return (unsigned long)hold_residual
;