Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | /* * Copyright (c) 1997 Paul Mackerras <paulus@cs.anu.edu.au> * Initial Power Macintosh COFF version. * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> * Modifications for an ELF-based IBM evaluation board version. * * Module name: main.c * * Description: * This module does most of the real work for the boot loader. It * checks the variables holding the absolute start address and size * of the Linux kernel "image" and initial RAM disk "initrd" sections * and if they are present, moves them to their "proper" locations. * * For the Linux kernel, "proper" is physical address 0x00000000. * For the RAM disk, "proper" is the image's size below the top * of physical memory. The Linux kernel may be in either raw * binary form or compressed with GNU zip (aka gzip). * * 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 "nonstdio.h" #include "zlib.h" #include "irSect.h" /* Preprocessor Defines */ #define RAM_SIZE (4 * 1024 * 1024) #define RAM_PBASE 0x00000000 #define RAM_PEND (RAM_PBASE + RAM_SIZE) #define RAM_VBASE 0xC0000000 #define RAM_VEND (RAM_VBASE + RAM_SIZE) #define RAM_START RAM_PBASE #define RAM_END RAM_PEND #define RAM_FREE (imageSect_start + imageSect_size + initrdSect_size) #define PROG_START RAM_START /* Function Macros */ #define ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1)) /* Global Variables */ /* Needed by zalloc and zfree for allocating memory */ char *avail_ram; /* Indicates start of RAM available for heap */ char *end_avail; /* Indicates end of RAM available for heap */ /* Function Prototypes */ void *zalloc(void *x, unsigned items, unsigned size); void zfree(void *x, void *addr, unsigned nb); void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp); void printf () {} void pause () {} void exit () {} void start(void) { void *options; int ns, oh, i; unsigned sa, len; void *dst; unsigned char *im; unsigned initrd_start, initrd_size; /* setup_bats(RAM_START); */ /* Init RAM disk (initrd) section */ if (initrdSect_start != 0 && (initrd_size = initrdSect_size) != 0) { initrd_start = (RAM_END - initrd_size) & ~0xFFF; printf("Initial RAM disk at 0x%08x (%u bytes)\n", initrd_start, initrd_size); memcpy((char *)initrd_start, (char *)(initrdSect_start), initrdSect_size); end_avail = (char *)initrd_start; } else { end_avail = (char *)RAM_END; } /* Linux kernel image section */ im = (unsigned char *)(imageSect_start); len = imageSect_size; dst = (void *)PROG_START; /* Check for the gzip archive magic numbers */ if (im[0] == 0x1f && im[1] == 0x8b) { /* The gunzip routine needs everything nice and aligned */ void *cp = (void *)ALIGN_UP(RAM_FREE, 8); avail_ram = (void *)(cp + ALIGN_UP(len, 8)); memcpy(cp, im, len); /* I'm not sure what the 0x200000 parameter is for, but it works. */ gunzip(dst, 0x200000, cp, &len); } else { memmove(dst, im, len); } /* flush_cache(dst, len); */ sa = (unsigned long)dst; (*(void (*)())sa)(); pause(); } void *zalloc(void *x, unsigned items, unsigned size) { void *p = avail_ram; size *= items; size = ALIGN_UP(size, 8); avail_ram += size; if (avail_ram > end_avail) { printf("oops... out of memory\n"); pause(); } return p; } void zfree(void *x, void *addr, unsigned nb) { } #define HEAD_CRC 2 #define EXTRA_FIELD 4 #define ORIG_NAME 8 #define COMMENT 0x10 #define RESERVED 0xe0 #define DEFLATED 8 void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) { z_stream s; int r, i, flags; /* skip header */ i = 10; flags = src[3]; if (src[2] != DEFLATED || (flags & RESERVED) != 0) { printf("bad gzipped data\n"); exit(); } if ((flags & EXTRA_FIELD) != 0) i = 12 + src[10] + (src[11] << 8); if ((flags & ORIG_NAME) != 0) while (src[i++] != 0) ; if ((flags & COMMENT) != 0) while (src[i++] != 0) ; if ((flags & HEAD_CRC) != 0) i += 2; if (i >= *lenp) { printf("gunzip: ran out of data in header\n"); exit(); } printf("done 1\n"); s.zalloc = zalloc; s.zfree = zfree; r = inflateInit2(&s, -MAX_WBITS); if (r != Z_OK) { printf("inflateInit2 returned %d\n", r); exit(); } s.next_in = src + i; s.avail_in = *lenp - i; s.next_out = dst; s.avail_out = dstlen; printf("doing inflate\n"); r = inflate(&s, Z_FINISH); printf("done inflate\n"); if (r != Z_OK && r != Z_STREAM_END) { printf("inflate returned %d\n", r); exit(); } *lenp = s.next_out - (unsigned char *) dst; printf("doing end\n"); inflateEnd(&s); } |