1/* 2 * misc.c 3 * 4 * $Id: misc.c,v 1.1.1.1 2007/08/03 18:51:41 Exp $ 5 * 6 * This is a collection of several routines from gzip-1.0.3 7 * adapted for Linux. 8 * 9 * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 10 * puts by Nick Holloway 1993, better puts by Martin Mares 1995 11 * adoptation for Linux/CRIS Axis Communications AB, 1999 12 * 13 */ 14 15/* where the piggybacked kernel image expects itself to live. 16 * it is the same address we use when we network load an uncompressed 17 * image into DRAM, and it is the address the kernel is linked to live 18 * at by vmlinux.lds.S 19 */ 20 21#define KERNEL_LOAD_ADR 0x40004000 22 23 24#include <linux/types.h> 25#include <asm/arch/hwregs/reg_rdwr.h> 26#include <asm/arch/hwregs/reg_map.h> 27#include <asm/arch/hwregs/ser_defs.h> 28 29/* 30 * gzip declarations 31 */ 32 33#define OF(args) args 34#define STATIC static 35 36void* memset(void* s, int c, size_t n); 37void* memcpy(void* __dest, __const void* __src, 38 size_t __n); 39 40#define memzero(s, n) memset ((s), 0, (n)) 41 42 43typedef unsigned char uch; 44typedef unsigned short ush; 45typedef unsigned long ulg; 46 47#define WSIZE 0x8000 /* Window size must be at least 32k, */ 48 /* and a power of two */ 49 50static uch *inbuf; /* input buffer */ 51static uch window[WSIZE]; /* Sliding window buffer */ 52 53unsigned inptr = 0; /* index of next byte to be processed in inbuf 54 * After decompression it will contain the 55 * compressed size, and head.S will read it. 56 */ 57 58static unsigned outcnt = 0; /* bytes in output buffer */ 59 60/* gzip flag byte */ 61#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 62#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ 63#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 64#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 65#define COMMENT 0x10 /* bit 4 set: file comment present */ 66#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ 67#define RESERVED 0xC0 /* bit 6,7: reserved */ 68 69#define get_byte() inbuf[inptr++] 70 71/* Diagnostic functions */ 72#ifdef DEBUG 73# define Assert(cond,msg) {if(!(cond)) error(msg);} 74# define Trace(x) fprintf x 75# define Tracev(x) {if (verbose) fprintf x ;} 76# define Tracevv(x) {if (verbose>1) fprintf x ;} 77# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} 78# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} 79#else 80# define Assert(cond,msg) 81# define Trace(x) 82# define Tracev(x) 83# define Tracevv(x) 84# define Tracec(c,x) 85# define Tracecv(c,x) 86#endif 87 88static int fill_inbuf(void); 89static void flush_window(void); 90static void error(char *m); 91static void gzip_mark(void **); 92static void gzip_release(void **); 93 94extern char *input_data; /* lives in head.S */ 95 96static long bytes_out = 0; 97static uch *output_data; 98static unsigned long output_ptr = 0; 99 100static void *malloc(int size); 101static void free(void *where); 102static void error(char *m); 103static void gzip_mark(void **); 104static void gzip_release(void **); 105 106static void puts(const char *); 107 108/* the "heap" is put directly after the BSS ends, at end */ 109 110extern int _end; 111static long free_mem_ptr = (long)&_end; 112 113#include "../../../../../lib/inflate.c" 114 115static void *malloc(int size) 116{ 117 void *p; 118 119 if (size <0) error("Malloc error"); 120 121 free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ 122 123 p = (void *)free_mem_ptr; 124 free_mem_ptr += size; 125 126 return p; 127} 128 129static void free(void *where) 130{ /* Don't care */ 131} 132 133static void gzip_mark(void **ptr) 134{ 135 *ptr = (void *) free_mem_ptr; 136} 137 138static void gzip_release(void **ptr) 139{ 140 free_mem_ptr = (long) *ptr; 141} 142 143/* decompressor info and error messages to serial console */ 144 145static inline void 146serout(const char *s, reg_scope_instances regi_ser) 147{ 148 reg_ser_rs_stat_din rs; 149 reg_ser_rw_dout dout = {.data = *s}; 150 151 do { 152 rs = REG_RD(ser, regi_ser, rs_stat_din); 153 } 154 while (!rs.tr_rdy);/* Wait for tranceiver. */ 155 156 REG_WR(ser, regi_ser, rw_dout, dout); 157} 158 159static void 160puts(const char *s) 161{ 162#ifndef CONFIG_ETRAX_DEBUG_PORT_NULL 163 while (*s) { 164#ifdef CONFIG_ETRAX_DEBUG_PORT0 165 serout(s, regi_ser0); 166#endif 167#ifdef CONFIG_ETRAX_DEBUG_PORT1 168 serout(s, regi_ser1); 169#endif 170#ifdef CONFIG_ETRAX_DEBUG_PORT2 171 serout(s, regi_ser2); 172#endif 173#ifdef CONFIG_ETRAX_DEBUG_PORT3 174 serout(s, regi_ser3); 175#endif 176 *s++; 177 } 178/* CONFIG_ETRAX_DEBUG_PORT_NULL */ 179#endif 180} 181 182void* 183memset(void* s, int c, size_t n) 184{ 185 int i; 186 char *ss = (char*)s; 187 188 for (i=0;i<n;i++) ss[i] = c; 189} 190 191void* 192memcpy(void* __dest, __const void* __src, 193 size_t __n) 194{ 195 int i; 196 char *d = (char *)__dest, *s = (char *)__src; 197 198 for (i=0;i<__n;i++) d[i] = s[i]; 199} 200 201/* =========================================================================== 202 * Write the output window window[0..outcnt-1] and update crc and bytes_out. 203 * (Used for the decompressed data only.) 204 */ 205 206static void 207flush_window() 208{ 209 ulg c = crc; /* temporary variable */ 210 unsigned n; 211 uch *in, *out, ch; 212 213 in = window; 214 out = &output_data[output_ptr]; 215 for (n = 0; n < outcnt; n++) { 216 ch = *out++ = *in++; 217 c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); 218 } 219 crc = c; 220 bytes_out += (ulg)outcnt; 221 output_ptr += (ulg)outcnt; 222 outcnt = 0; 223} 224 225static void 226error(char *x) 227{ 228 puts("\n\n"); 229 puts(x); 230 puts("\n\n -- System halted\n"); 231 232 while(1); /* Halt */ 233} 234 235void 236setup_normal_output_buffer() 237{ 238 output_data = (char *)KERNEL_LOAD_ADR; 239} 240 241static inline void 242serial_setup(reg_scope_instances regi_ser) 243{ 244 reg_ser_rw_xoff xoff; 245 reg_ser_rw_tr_ctrl tr_ctrl; 246 reg_ser_rw_rec_ctrl rec_ctrl; 247 reg_ser_rw_tr_baud_div tr_baud; 248 reg_ser_rw_rec_baud_div rec_baud; 249 250 /* Turn off XOFF. */ 251 xoff = REG_RD(ser, regi_ser, rw_xoff); 252 253 xoff.chr = 0; 254 xoff.automatic = regk_ser_no; 255 256 REG_WR(ser, regi_ser, rw_xoff, xoff); 257 258 /* Set baudrate and stopbits. */ 259 tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl); 260 rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl); 261 tr_baud = REG_RD(ser, regi_ser, rw_tr_baud_div); 262 rec_baud = REG_RD(ser, regi_ser, rw_rec_baud_div); 263 264 tr_ctrl.stop_bits = 1; /* 2 stop bits. */ 265 266 /* 267 * The baudrate setup is a bit fishy, but in the end the tranceiver is 268 * set to 4800 and the receiver to 115200. The magic value is 269 * 29.493 MHz. 270 */ 271 tr_ctrl.base_freq = regk_ser_f29_493; 272 rec_ctrl.base_freq = regk_ser_f29_493; 273 tr_baud.div = (29493000 / 8) / 4800; 274 rec_baud.div = (29493000 / 8) / 115200; 275 276 REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl); 277 REG_WR(ser, regi_ser, rw_tr_baud_div, tr_baud); 278 REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl); 279 REG_WR(ser, regi_ser, rw_rec_baud_div, rec_baud); 280} 281 282void 283decompress_kernel() 284{ 285 char revision; 286 287 /* input_data is set in head.S */ 288 inbuf = input_data; 289 290#ifdef CONFIG_ETRAX_DEBUG_PORT0 291 serial_setup(regi_ser0); 292#endif 293#ifdef CONFIG_ETRAX_DEBUG_PORT1 294 serial_setup(regi_ser1); 295#endif 296#ifdef CONFIG_ETRAX_DEBUG_PORT2 297 serial_setup(regi_ser2); 298#endif 299#ifdef CONFIG_ETRAX_DEBUG_PORT3 300 serial_setup(regi_ser3); 301#endif 302 303 setup_normal_output_buffer(); 304 305 makecrc(); 306 307 __asm__ volatile ("move $vr,%0" : "=rm" (revision)); 308 if (revision < 32) 309 { 310 puts("You need an ETRAX FS to run Linux 2.6/crisv32.\n"); 311 while(1); 312 } 313 314 puts("Uncompressing Linux...\n"); 315 gunzip(); 316 puts("Done. Now booting the kernel.\n"); 317} 318