Merge with 2.3.99-pre9.
[linux-2.6/linux-mips.git] / arch / ppc / mbxboot / misc.c
blobd5a44df1ef95256a2bbaf7196b1dc6dfe528e548
1 /*
2 * misc.c
4 * $Id: misc.c,v 1.2 1999/09/14 05:55:29 dmalek Exp $
5 *
6 * Adapted for PowerPC by Gary Thomas
8 * Rewritten by Cort Dougan (cort@cs.nmt.edu)
9 * One day to be replaced by a single bootloader for chrp/prep/pmac. -- Cort
12 #include <linux/types.h>
13 #include "../coffboot/zlib.h"
14 #include "asm/residual.h"
15 #include <linux/elf.h>
16 #include <linux/config.h>
17 #include <asm/page.h>
18 #include <asm/processor.h>
19 #include <asm/mmu.h>
20 #ifdef CONFIG_8xx
21 #include <asm/mpc8xx.h>
22 #endif
23 #ifdef CONFIG_8260
24 #include <asm/mpc8260.h>
25 #endif
28 * The following references are needed to cause the linker to pull in the
29 * gzimage.o and rdimage.o files. These object files are special,
30 * since they get placed into the .gzimage and .rdimage ELF sections
31 * of the zvmlinux and zvmlinux.initrd files.
33 extern char dummy_for_gzimage;
34 extern char dummy_for_rdimage;
37 * Please send me load/board info and such data for hardware not
38 * listed here so I can keep track since things are getting tricky
39 * with the different load addrs with different firmware. This will
40 * help to avoid breaking the load/boot process.
41 * -- Cort
43 char *avail_ram;
44 char *end_avail;
46 /* See comment below.....
48 unsigned int initrd_offset, initrd_size;
50 /* Because of the limited amount of memory on embedded, it presents
51 * loading problems. The biggest is that we load this boot program
52 * into a relatively low memory address, and the Linux kernel Bss often
53 * extends into this space when it get loaded. When the kernel starts
54 * and zeros the BSS space, it also writes over the information we
55 * save here and pass to the kernel (command line and board info).
56 * On these boards, we grab some known memory holes to hold this information.
58 char cmd_buf[256];
59 char *cmd_line = cmd_buf;
61 char *root_string = "root=/dev/nfs rw";
62 char *nfsaddrs_string = "nfsaddrs=";
63 char *nfsroot_string = "nfsroot=";
64 char *defroot_string = "/sys/mbxroot";
65 char *ramroot_string = "root=/dev/ram";
66 int do_ipaddrs(char **cmd_cp, int echo);
67 void do_nfsroot(char **cmd_cp, char *dp);
68 int strncmp(const char * cs,const char * ct,size_t count);
69 char *strrchr(const char * s, int c);
71 bd_t hold_resid_buf;
72 bd_t *hold_residual = &hold_resid_buf;
73 unsigned long initrd_start = 0, initrd_end = 0;
74 char *zimage_start;
75 int zimage_size;
77 void puts(const char *);
78 void putc(const char c);
79 void puthex(unsigned long val);
80 void _bcopy(char *src, char *dst, int len);
81 void * memcpy(void * __dest, __const void * __src,
82 int __n);
83 void gunzip(void *, int, unsigned char *, int *);
85 void pause()
87 puts("pause\n");
90 void exit()
92 puts("exit\n");
93 while(1);
96 /* The MPC8xx is just the serial port.
98 tstc(void)
100 return (serial_tstc());
103 getc(void)
105 while (1) {
106 if (serial_tstc()) return (serial_getc());
110 void
111 putc(const char c)
113 serial_putchar(c);
116 void puts(const char *s)
118 char c;
120 while ( ( c = *s++ ) != '\0' ) {
121 serial_putchar(c);
122 if ( c == '\n' )
123 serial_putchar('\r');
127 void * memcpy(void * __dest, __const void * __src,
128 int __n)
130 int i;
131 char *d = (char *)__dest, *s = (char *)__src;
133 for (i=0;i<__n;i++) d[i] = s[i];
136 int memcmp(__const void * __dest, __const void * __src,
137 int __n)
139 int i;
140 char *d = (char *)__dest, *s = (char *)__src;
142 for (i=0;i<__n;i++, d++, s++)
144 if (*d != *s)
146 return (*s - *d);
149 return (0);
152 void error(char *x)
154 puts("\n\n");
155 puts(x);
156 puts("\n\n -- System halted");
158 while(1); /* Halt */
161 void *zalloc(void *x, unsigned items, unsigned size)
163 void *p = avail_ram;
165 size *= items;
166 size = (size + 7) & -8;
167 avail_ram += size;
168 if (avail_ram > end_avail) {
169 puts("oops... out of memory\n");
170 pause();
172 return p;
175 void zfree(void *x, void *addr, unsigned nb)
179 #define HEAD_CRC 2
180 #define EXTRA_FIELD 4
181 #define ORIG_NAME 8
182 #define COMMENT 0x10
183 #define RESERVED 0xe0
185 #define DEFLATED 8
188 void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
190 z_stream s;
191 int r, i, flags;
193 /* skip header */
194 i = 10;
195 flags = src[3];
196 if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
197 puts("bad gzipped data\n");
198 exit();
200 if ((flags & EXTRA_FIELD) != 0)
201 i = 12 + src[10] + (src[11] << 8);
202 if ((flags & ORIG_NAME) != 0)
203 while (src[i++] != 0)
205 if ((flags & COMMENT) != 0)
206 while (src[i++] != 0)
208 if ((flags & HEAD_CRC) != 0)
209 i += 2;
210 if (i >= *lenp) {
211 puts("gunzip: ran out of data in header\n");
212 exit();
215 s.zalloc = zalloc;
216 s.zfree = zfree;
217 r = inflateInit2(&s, -MAX_WBITS);
218 if (r != Z_OK) {
219 puts("inflateInit2 returned %d\n");
220 exit();
222 s.next_in = src + i;
223 s.avail_in = *lenp - i;
224 s.next_out = dst;
225 s.avail_out = dstlen;
226 r = inflate(&s, Z_FINISH);
227 if (r != Z_OK && r != Z_STREAM_END) {
228 puts("inflate returned %d\n");
229 exit();
231 *lenp = s.next_out - (unsigned char *) dst;
232 inflateEnd(&s);
235 unsigned char sanity[0x2000];
237 unsigned long
238 decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp)
240 int timer;
241 extern unsigned long start;
242 char *cp, ch;
243 unsigned long i;
244 char *dp;
246 #ifdef CONFIG_8260
247 /* I don't know why I didn't do it this way on the 8xx.......
249 embed_config(bp);
250 serial_init(bp);
251 #endif
253 /* These values must be variables. If not, the compiler optimizer
254 * will remove some code, causing the size of the code to vary
255 * when these values are zero. This is bad because we first
256 * compile with these zero to determine the size and offsets
257 * in an image, than compile again with these set to the proper
258 * discovered value.....Ya know, we used to read these from the
259 * header a long time ago.....
261 initrd_offset = INITRD_OFFSET;
262 initrd_size = INITRD_SIZE;
264 /* Grab some space for the command line and board info. Since
265 * we no longer use the ELF header, but it was loaded, grab
266 * that space.
268 #ifdef CONFIG_MBX
269 cmd_line = (char *)(load_addr - 0x10000);
270 #else
271 cmd_line = (char *)(0x200000);
272 #endif
273 hold_residual = (bd_t *)(cmd_line + sizeof(cmd_buf));
274 /* copy board data */
275 if (bp)
276 memcpy(hold_residual,bp,sizeof(bd_t));
278 /* Set end of memory available to us. It is always the highest
279 * memory address provided by the board information.
281 end_avail = (char *)(bp->bi_memsize);
283 puts("loaded at: "); puthex(load_addr);
284 puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
285 if ( (unsigned long)load_addr != (unsigned long)&start )
287 puts("relocated to: "); puthex((unsigned long)&start);
288 puts(" ");
289 puthex((unsigned long)((unsigned long)&start + (4*num_words)));
290 puts("\n");
293 if ( bp )
295 puts("board data at: "); puthex((unsigned long)bp);
296 puts(" ");
297 puthex((unsigned long)((unsigned long)bp + sizeof(bd_t)));
298 puts("\n");
299 puts("relocated to: ");
300 puthex((unsigned long)hold_residual);
301 puts(" ");
302 puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t)));
303 puts("\n");
306 /* we have to subtract 0x10000 here to correct for objdump including the
307 size of the elf header which we strip -- Cort */
308 zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET);
309 zimage_size = ZIMAGE_SIZE;
311 if ( initrd_offset )
312 initrd_start = load_addr - 0x10000 + initrd_offset;
313 else
314 initrd_start = 0;
315 initrd_end = initrd_size + initrd_start;
318 * setup avail_ram - this is the first part of ram usable
319 * by the uncompress code. -- Cort
321 avail_ram = (char *)PAGE_ALIGN((unsigned long)zimage_start+zimage_size);
322 if ( ((load_addr+(num_words*4)) > (unsigned long) avail_ram)
323 && (load_addr <= 0x01000000) )
324 avail_ram = (char *)(load_addr+(num_words*4));
325 if ( (((unsigned long)&start+(num_words*4)) > (unsigned long) avail_ram)
326 && (load_addr <= 0x01000000) )
327 avail_ram = (char *)((unsigned long)&start+(num_words*4));
329 /* relocate zimage */
330 puts("zimage at: "); puthex((unsigned long)zimage_start);
331 puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n");
333 * There is no reason (yet) to relocate zImage for embedded boards.
334 * To support boot from flash rom on 8xx embedded boards, I
335 * assume if zimage start is over 16M we are booting from flash.
336 * In this case, avilable ram will start just above the space we
337 * have allocated for the command buffer and board information.
339 if ((unsigned long)zimage_start > 0x01000000)
340 avail_ram = (char *)PAGE_ALIGN((unsigned long)hold_residual + sizeof(bd_t));
342 /* relocate initrd */
343 if ( initrd_start )
345 puts("initrd at: "); puthex(initrd_start);
346 puts(" "); puthex(initrd_end); puts("\n");
348 /* We only have to relocate initrd if we find it is in Flash
349 * rom. This is because the kernel thinks it can toss the
350 * pages into the free memory pool after it is done. Use
351 * the same 16M test.
353 if ((unsigned long)initrd_start > 0x01000000) {
354 memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE),
355 (void *)initrd_start,
356 initrd_size );
357 initrd_start = PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE);
358 initrd_end = initrd_start + initrd_size;
359 end_avail = (char *)initrd_start;
360 puts("relocated to: "); puthex(initrd_start);
361 puts(" "); puthex(initrd_end); puts("\n");
363 else {
364 avail_ram = (char *)PAGE_ALIGN((unsigned long)initrd_end);
369 puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" ");
370 puthex((unsigned long)end_avail); puts("\n");
372 puts("\nLinux/PPC load: ");
373 timer = 0;
374 cp = cmd_line;
376 while (timer++ < 5*1000) {
377 if (tstc()) {
378 while ((ch = getc()) != '\n' && ch != '\r') {
379 if (ch == '\b') {
380 if (cp != cmd_line) {
381 cp--;
382 puts("\b \b");
384 } else {
385 *cp++ = ch;
386 putc(ch);
389 break; /* Exit 'timer' loop */
391 udelay(1000); /* 1 msec */
393 *cp = 0;
395 /* If the command line is not filled in, we will automatically
396 * create the default boot.
398 if (cmd_line[0] == 0) {
400 /* An initrd on these boards means we booted from Flash
401 * ROM and want to use the ramdisk as the root file system.
402 * Otherwise, we perform a diskless NFS boot.
404 if (initrd_start)
405 dp = ramroot_string;
406 else
407 dp = root_string;
408 while (*dp != 0)
409 *cp++ = *dp++;
410 *cp = 0;
413 puts("\n");
415 puts("Uncompressing Linux...");
417 gunzip(0, 0x400000, zimage_start, &zimage_size);
418 puts("done.\n");
419 puts("Now booting the kernel\n");
420 return (unsigned long)hold_residual;
423 void puthex(unsigned long val)
425 unsigned char buf[10];
426 int i;
427 for (i = 7; i >= 0; i--)
429 buf[i] = "0123456789ABCDEF"[val & 0x0F];
430 val >>= 4;
432 buf[8] = '\0';
433 puts(buf);
437 * PCI/ISA I/O support
440 volatile unsigned char *ISA_io = (unsigned char *)0x80000000;
441 volatile unsigned char *ISA_mem = (unsigned char *)0xC0000000;
443 void
444 outb(int port, char val)
446 /* Ensure I/O operations complete */
447 __asm__ volatile("eieio");
448 ISA_io[port] = val;
451 unsigned char
452 inb(int port)
454 /* Ensure I/O operations complete */
455 __asm__ volatile("eieio");
456 return (ISA_io[port]);
459 unsigned long
460 local_to_PCI(unsigned long addr)
462 return ((addr & 0x7FFFFFFF) | 0x80000000);
465 void
466 _bcopy(char *src, char *dst, int len)
468 while (len--) *dst++ = *src++;