os/linux-2.6-tag--devboard-R2_10-4/arch/cris/arch-v32/boot/compressed/misc.c

Go to the documentation of this file.
00001 /*
00002  * misc.c
00003  *
00004  * $Id: misc.c,v 1.1.1.1 2008/11/27 20:04:00 elphel Exp $
00005  * 
00006  * This is a collection of several routines from gzip-1.0.3 
00007  * adapted for Linux.
00008  *
00009  * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
00010  * puts by Nick Holloway 1993, better puts by Martin Mares 1995
00011  * adoptation for Linux/CRIS Axis Communications AB, 1999
00012  * 
00013  */
00014 
00015 /* where the piggybacked kernel image expects itself to live.
00016  * it is the same address we use when we network load an uncompressed
00017  * image into DRAM, and it is the address the kernel is linked to live
00018  * at by vmlinux.lds.S
00019  */
00020 
00021 #define KERNEL_LOAD_ADR 0x40004100
00022 
00023 #include <linux/types.h>
00024 #include <asm/arch/hwregs/reg_rdwr.h>
00025 #include <asm/arch/hwregs/reg_map.h>
00026 #include <asm/arch/hwregs/ser_defs.h>
00027 #include <asm/arch/hwregs/pinmux_defs.h>
00028 
00029 /*
00030  * gzip declarations
00031  */
00032 
00033 #define OF(args)  args
00034 #define STATIC static
00035 
00036 void* memset(void* s, int c, size_t n);
00037 void* memcpy(void* __dest, __const void* __src,
00038              size_t __n);
00039 
00040 #define memzero(s, n)     memset ((s), 0, (n))
00041 
00042 
00043 typedef unsigned char  uch;
00044 typedef unsigned short ush;
00045 typedef unsigned long  ulg;
00046 
00047 #define WSIZE 0x8000            /* Window size must be at least 32k, */
00048                                 /* and a power of two */
00049 
00050 static uch *inbuf;           /* input buffer */
00051 static uch window[WSIZE];    /* Sliding window buffer */
00052 
00053 unsigned inptr = 0;     /* index of next byte to be processed in inbuf
00054                          * After decompression it will contain the
00055                          * compressed size, and head.S will read it.
00056                          */
00057 
00058 static unsigned outcnt = 0;  /* bytes in output buffer */
00059 
00060 /* gzip flag byte */
00061 #define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
00062 #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
00063 #define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
00064 #define ORIG_NAME    0x08 /* bit 3 set: original file name present */
00065 #define COMMENT      0x10 /* bit 4 set: file comment present */
00066 #define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
00067 #define RESERVED     0xC0 /* bit 6,7:   reserved */
00068 
00069 #define get_byte() inbuf[inptr++]       
00070         
00071 /* Diagnostic functions */
00072 #ifdef DEBUG
00073 #  define Assert(cond,msg) {if(!(cond)) error(msg);}
00074 #  define Trace(x) fprintf x
00075 #  define Tracev(x) {if (verbose) fprintf x ;}
00076 #  define Tracevv(x) {if (verbose>1) fprintf x ;}
00077 #  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
00078 #  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
00079 #else
00080 #  define Assert(cond,msg)
00081 #  define Trace(x)
00082 #  define Tracev(x)
00083 #  define Tracevv(x)
00084 #  define Tracec(c,x)
00085 #  define Tracecv(c,x)
00086 #endif
00087 
00088 static int  fill_inbuf(void);
00089 static void flush_window(void);
00090 static void error(char *m);
00091 static void gzip_mark(void **);
00092 static void gzip_release(void **);
00093 
00094 extern char *input_data;  /* lives in head.S */
00095 
00096 static long bytes_out = 0;
00097 static uch *output_data;
00098 static unsigned long output_ptr = 0;
00099  
00100 static void *malloc(int size);
00101 static void free(void *where);
00102 static void error(char *m);
00103 static void gzip_mark(void **);
00104 static void gzip_release(void **);
00105  
00106 static void puts(const char *);
00107 
00108 /* the "heap" is put directly after the BSS ends, at end */
00109   
00110 extern int _end;
00111 static long free_mem_ptr = (long)&_end;
00112  
00113 #include "../../../../../lib/inflate.c"
00114 
00115 static void *malloc(int size)
00116 {
00117         void *p;
00118 
00119         if (size <0) error("Malloc error");
00120 
00121         free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
00122 
00123         p = (void *)free_mem_ptr;
00124         free_mem_ptr += size;
00125 
00126         return p;
00127 }
00128 
00129 static void free(void *where)
00130 {       /* Don't care */
00131 }
00132 
00133 static void gzip_mark(void **ptr)
00134 {
00135         *ptr = (void *) free_mem_ptr;
00136 }
00137 
00138 static void gzip_release(void **ptr)
00139 {
00140         free_mem_ptr = (long) *ptr;
00141 }
00142 
00143 /* decompressor info and error messages to serial console */
00144 
00145 static inline void
00146 serout(const char *s, reg_scope_instances regi_ser)
00147 {
00148         reg_ser_rs_stat_din rs;
00149         reg_ser_rw_dout dout = {.data = *s};
00150 
00151         do {
00152                 rs = REG_RD(ser, regi_ser, rs_stat_din);
00153         }
00154         while (!rs.tr_rdy);/* Wait for tranceiver. */
00155         
00156         REG_WR(ser, regi_ser, rw_dout, dout);
00157 }
00158 
00159 static void
00160 puts(const char *s)
00161 {
00162 #ifndef CONFIG_ETRAX_DEBUG_PORT_NULL
00163         while (*s) {
00164 #ifdef CONFIG_ETRAX_DEBUG_PORT0
00165                 serout(s, regi_ser0);
00166 #endif
00167 #ifdef CONFIG_ETRAX_DEBUG_PORT1
00168                 serout(s, regi_ser1);
00169 #endif
00170 #ifdef CONFIG_ETRAX_DEBUG_PORT2
00171                 serout(s, regi_ser2);
00172 #endif
00173 #ifdef CONFIG_ETRAX_DEBUG_PORT3
00174                 serout(s, regi_ser3);
00175 #endif
00176                 *s++;
00177         }
00178 /* CONFIG_ETRAX_DEBUG_PORT_NULL */
00179 #endif
00180 }
00181 
00182 void*
00183 memset(void* s, int c, size_t n)
00184 {
00185         int i;
00186         char *ss = (char*)s;
00187 
00188         for (i=0;i<n;i++) ss[i] = c;
00189 }
00190 
00191 void*
00192 memcpy(void* __dest, __const void* __src,
00193                             size_t __n)
00194 {
00195         int i;
00196         char *d = (char *)__dest, *s = (char *)__src;
00197 
00198         for (i=0;i<__n;i++) d[i] = s[i];
00199 }
00200 
00201 /* ===========================================================================
00202  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
00203  * (Used for the decompressed data only.)
00204  */
00205 
00206 static void
00207 flush_window()
00208 {
00209     ulg c = crc;         /* temporary variable */
00210     unsigned n;
00211     uch *in, *out, ch;
00212     
00213     in = window;
00214     out = &output_data[output_ptr]; 
00215     for (n = 0; n < outcnt; n++) {
00216             ch = *out++ = *in++;
00217             c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
00218     }
00219     crc = c;
00220     bytes_out += (ulg)outcnt;
00221     output_ptr += (ulg)outcnt;
00222     outcnt = 0;
00223 }
00224 
00225 static void
00226 error(char *x)
00227 {
00228         puts("\r\n\n");
00229         puts(x);
00230         puts("\r\n\n -- System halted\n");
00231 
00232         while(1);       /* Halt */
00233 }
00234 
00235 void
00236 setup_normal_output_buffer()
00237 {
00238         output_data = (char *)KERNEL_LOAD_ADR;
00239 }
00240 
00241 static inline void
00242 serial_setup(reg_scope_instances regi_ser)
00243 {
00244         reg_ser_rw_xoff xoff;
00245         reg_ser_rw_tr_ctrl tr_ctrl;
00246         reg_ser_rw_rec_ctrl rec_ctrl;
00247         reg_ser_rw_tr_baud_div tr_baud;
00248         reg_ser_rw_rec_baud_div rec_baud;
00249         
00250         /* Turn off XOFF. */
00251         xoff = REG_RD(ser, regi_ser, rw_xoff);
00252         
00253         xoff.chr = 0;
00254         xoff.automatic = regk_ser_no;
00255         
00256         REG_WR(ser, regi_ser, rw_xoff, xoff);
00257 
00258         /* Set baudrate and stopbits. */
00259         tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl);
00260         rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl);
00261         tr_baud = REG_RD(ser, regi_ser, rw_tr_baud_div);
00262         rec_baud = REG_RD(ser, regi_ser, rw_rec_baud_div);
00263         
00264         tr_ctrl.stop_bits = 1;  /* 2 stop bits. */
00265         tr_ctrl.en = 1; /* enable transmitter */
00266         rec_ctrl.en = 1; /* enabler receiver */
00267         
00268         /* 
00269          * The baudrate setup used to be a bit fishy, but now transmitter and
00270          * receiver are both set to the intended baud rate, 115200.
00271          * The magic value is 29.493 MHz.
00272          */
00273         tr_ctrl.base_freq = regk_ser_f29_493;
00274         rec_ctrl.base_freq = regk_ser_f29_493;
00275         tr_baud.div = (29493000 / 8) / 115200;
00276         rec_baud.div = (29493000 / 8) / 115200;
00277         
00278         REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
00279         REG_WR(ser, regi_ser, rw_tr_baud_div, tr_baud);
00280         REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
00281         REG_WR(ser, regi_ser, rw_rec_baud_div, rec_baud);
00282 }
00283 
00284 void
00285 decompress_kernel()
00286 {
00287         char revision;
00288         reg_pinmux_rw_hwprot hwprot;
00289         
00290         /* input_data is set in head.S */
00291         inbuf = input_data;
00292         
00293         hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
00294 #ifdef CONFIG_ETRAX_DEBUG_PORT0
00295         serial_setup(regi_ser0);
00296 #endif
00297 #ifdef CONFIG_ETRAX_DEBUG_PORT1
00298         hwprot.ser1 = regk_pinmux_yes;
00299         serial_setup(regi_ser1);
00300 #endif
00301 #ifdef CONFIG_ETRAX_DEBUG_PORT2
00302         hwprot.ser2 = regk_pinmux_yes;
00303         serial_setup(regi_ser2);
00304 #endif
00305 #ifdef CONFIG_ETRAX_DEBUG_PORT3
00306         hwprot.ser3 = regk_pinmux_yes;
00307         serial_setup(regi_ser3);
00308 #endif
00309         REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
00310 
00311         setup_normal_output_buffer();
00312 
00313         makecrc();
00314 
00315         __asm__ volatile ("move $vr,%0" : "=rm" (revision));
00316         if (revision < 32)
00317         {
00318                 puts("You need an ETRAX FS to run Linux 2.6/crisv32.\r\n");
00319                 while(1);
00320         }
00321 
00322         puts("Uncompressing Linux...\r\n");
00323         gunzip();
00324         puts("Done. Now booting the kernel.\r\n");
00325 }

Generated on Fri Nov 28 00:06:23 2008 for elphel by  doxygen 1.5.1