linux/arch/cris/arch-v32/boot/compressed/misc.c
<<
>>
Prefs
   1/*
   2 * misc.c
   3 *
   4 * $Id: misc.c,v 1.8 2005/04/24 18:34:29 starvik 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 * adaptation 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 transceiver. */
 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 transceiver 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