| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (C) Paul Mackerras 1997. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version | 
					
						
							|  |  |  |  * 2 of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #include <linux/string.h>
 | 
					
						
							|  |  |  | #include "nonstdio.h"
 | 
					
						
							|  |  |  | #include "of1275.h"
 | 
					
						
							|  |  |  | #include <asm/processor.h>
 | 
					
						
							|  |  |  | #include <asm/page.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Passed from the linker */ | 
					
						
							|  |  |  | extern char __image_begin, __image_end; | 
					
						
							|  |  |  | extern char __ramdisk_begin, __ramdisk_end; | 
					
						
							|  |  |  | extern char _start, _end; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern unsigned int heap_max; | 
					
						
							|  |  |  | extern void flush_cache(void *, unsigned long); | 
					
						
							|  |  |  | extern void gunzip(void *, int, unsigned char *, int *); | 
					
						
							|  |  |  | extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach, | 
					
						
							|  |  |  | 		unsigned int progend); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char *avail_ram; | 
					
						
							|  |  |  | char *begin_avail, *end_avail; | 
					
						
							|  |  |  | char *avail_high; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define RAM_START	0x00000000
 | 
					
						
							|  |  |  | #define RAM_END		(64<<20)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define BOOT_START	((unsigned long)_start)
 | 
					
						
							|  |  |  | #define BOOT_END	((unsigned long)(_end + 0xFFF) & ~0xFFF)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define RAM_FREE	((unsigned long)(_end+0x1000)&~0xFFF)
 | 
					
						
							|  |  |  | #define PROG_START	0x00010000
 | 
					
						
							|  |  |  | #define PROG_SIZE	0x007f0000 /* 8MB */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SCRATCH_SIZE	(128 << 10)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-06-25 14:59:21 -07:00
										 |  |  | static char scratch[SCRATCH_SIZE];	/* 128k of scratch space for gunzip */ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef void (*kernel_start_t)(int, int, void *, unsigned int, unsigned int); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | boot(int a1, int a2, void *prom) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned sa, len; | 
					
						
							|  |  |  |     void *dst; | 
					
						
							|  |  |  |     unsigned char *im; | 
					
						
							|  |  |  |     unsigned int initrd_size, initrd_start; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     printf("chrpboot starting: loaded at 0x%p\n\r", &_start); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     initrd_size = &__ramdisk_end - &__ramdisk_begin; | 
					
						
							|  |  |  |     if (initrd_size) { | 
					
						
							|  |  |  | 	initrd_start = (RAM_END - initrd_size) & ~0xFFF; | 
					
						
							|  |  |  | 	a1 = initrd_start; | 
					
						
							|  |  |  | 	a2 = initrd_size; | 
					
						
							|  |  |  | 	claim(initrd_start, RAM_END - initrd_start, 0); | 
					
						
							|  |  |  | 	printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r", | 
					
						
							|  |  |  | 	       initrd_start, &__ramdisk_begin, initrd_size); | 
					
						
							|  |  |  | 	memcpy((char *)initrd_start, &__ramdisk_begin, initrd_size); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  | 	initrd_start = 0; | 
					
						
							|  |  |  | 	initrd_size = 0; | 
					
						
							|  |  |  | 	a2 = 0xdeadbeef; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     im = &__image_begin; | 
					
						
							|  |  |  |     len = &__image_end - &__image_begin; | 
					
						
							|  |  |  |     /* claim 4MB starting at PROG_START */ | 
					
						
							|  |  |  |     claim(PROG_START, PROG_SIZE - PROG_START, 0); | 
					
						
							|  |  |  |     dst = (void *) PROG_START; | 
					
						
							|  |  |  |     if (im[0] == 0x1f && im[1] == 0x8b) { | 
					
						
							|  |  |  | 	avail_ram = scratch; | 
					
						
							|  |  |  | 	begin_avail = avail_high = avail_ram; | 
					
						
							|  |  |  | 	end_avail = scratch + sizeof(scratch); | 
					
						
							|  |  |  | 	printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); | 
					
						
							|  |  |  | 	gunzip(dst, 0x400000, im, &len); | 
					
						
							|  |  |  | 	printf("done %u bytes\n\r", len); | 
					
						
							|  |  |  | 	printf("%u bytes of heap consumed, max in use %u\n\r", | 
					
						
							|  |  |  | 	       avail_high - begin_avail, heap_max); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  | 	memmove(dst, im, len); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     flush_cache(dst, len); | 
					
						
							|  |  |  |     make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_chrp, | 
					
						
							|  |  |  | 		    (PROG_START + PROG_SIZE)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sa = PROG_START; | 
					
						
							|  |  |  |     printf("start address = 0x%x\n\r", sa); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     (*(kernel_start_t)sa)(a1, a2, prom, initrd_start, initrd_size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     printf("returned?\n\r"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pause(); | 
					
						
							|  |  |  | } |