|  | /* | 
|  | * 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) | 
|  |  | 
|  | static char scratch[SCRATCH_SIZE];	/* 128k of scratch space for gunzip */ | 
|  |  | 
|  | 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(); | 
|  | } |