linux/arch/arm/boot/compressed/misc.c
<<
>>
Prefs
   1/*
   2 * misc.c
   3 * 
   4 * This is a collection of several routines from gzip-1.0.3 
   5 * adapted for Linux.
   6 *
   7 * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
   8 *
   9 * Modified for ARM Linux by Russell King
  10 *
  11 * Nicolas Pitre <nico@visuaide.com>  1999/04/14 :
  12 *  For this code to run directly from Flash, all constant variables must
  13 *  be marked with 'const' and all other variables initialized at run-time 
  14 *  only.  This way all non constant variables will end up in the bss segment,
  15 *  which should point to addresses in RAM and cleared to 0 on start.
  16 *  This allows for a much quicker boot time.
  17 */
  18
  19unsigned int __machine_arch_type;
  20
  21#include <linux/compiler.h>     /* for inline */
  22#include <linux/types.h>        /* for size_t */
  23#include <linux/stddef.h>       /* for NULL */
  24#include <asm/string.h>
  25
  26#ifdef STANDALONE_DEBUG
  27#define putstr printf
  28#else
  29
  30static void putstr(const char *ptr);
  31
  32#include <mach/uncompress.h>
  33
  34#ifdef CONFIG_DEBUG_ICEDCC
  35
  36#ifdef CONFIG_CPU_V6
  37
  38static void icedcc_putc(int ch)
  39{
  40        int status, i = 0x4000000;
  41
  42        do {
  43                if (--i < 0)
  44                        return;
  45
  46                asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status));
  47        } while (status & (1 << 29));
  48
  49        asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch));
  50}
  51#elif defined(CONFIG_CPU_XSCALE)
  52
  53static void icedcc_putc(int ch)
  54{
  55        int status, i = 0x4000000;
  56
  57        do {
  58                if (--i < 0)
  59                        return;
  60
  61                asm volatile ("mrc p14, 0, %0, c14, c0, 0" : "=r" (status));
  62        } while (status & (1 << 28));
  63
  64        asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch));
  65}
  66
  67#else
  68
  69static void icedcc_putc(int ch)
  70{
  71        int status, i = 0x4000000;
  72
  73        do {
  74                if (--i < 0)
  75                        return;
  76
  77                asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
  78        } while (status & 2);
  79
  80        asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
  81}
  82
  83#endif
  84
  85#define putc(ch)        icedcc_putc(ch)
  86#define flush() do { } while (0)
  87#endif
  88
  89static void putstr(const char *ptr)
  90{
  91        char c;
  92
  93        while ((c = *ptr++) != '\0') {
  94                if (c == '\n')
  95                        putc('\r');
  96                putc(c);
  97        }
  98
  99        flush();
 100}
 101
 102#endif
 103
 104#define __ptr_t void *
 105
 106#define memzero(s,n) __memzero(s,n)
 107
 108/*
 109 * Optimised C version of memzero for the ARM.
 110 */
 111void __memzero (__ptr_t s, size_t n)
 112{
 113        union { void *vp; unsigned long *ulp; unsigned char *ucp; } u;
 114        int i;
 115
 116        u.vp = s;
 117
 118        for (i = n >> 5; i > 0; i--) {
 119                *u.ulp++ = 0;
 120                *u.ulp++ = 0;
 121                *u.ulp++ = 0;
 122                *u.ulp++ = 0;
 123                *u.ulp++ = 0;
 124                *u.ulp++ = 0;
 125                *u.ulp++ = 0;
 126                *u.ulp++ = 0;
 127        }
 128
 129        if (n & 1 << 4) {
 130                *u.ulp++ = 0;
 131                *u.ulp++ = 0;
 132                *u.ulp++ = 0;
 133                *u.ulp++ = 0;
 134        }
 135
 136        if (n & 1 << 3) {
 137                *u.ulp++ = 0;
 138                *u.ulp++ = 0;
 139        }
 140
 141        if (n & 1 << 2)
 142                *u.ulp++ = 0;
 143
 144        if (n & 1 << 1) {
 145                *u.ucp++ = 0;
 146                *u.ucp++ = 0;
 147        }
 148
 149        if (n & 1)
 150                *u.ucp++ = 0;
 151}
 152
 153static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
 154                            size_t __n)
 155{
 156        int i = 0;
 157        unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
 158
 159        for (i = __n >> 3; i > 0; i--) {
 160                *d++ = *s++;
 161                *d++ = *s++;
 162                *d++ = *s++;
 163                *d++ = *s++;
 164                *d++ = *s++;
 165                *d++ = *s++;
 166                *d++ = *s++;
 167                *d++ = *s++;
 168        }
 169
 170        if (__n & 1 << 2) {
 171                *d++ = *s++;
 172                *d++ = *s++;
 173                *d++ = *s++;
 174                *d++ = *s++;
 175        }
 176
 177        if (__n & 1 << 1) {
 178                *d++ = *s++;
 179                *d++ = *s++;
 180        }
 181
 182        if (__n & 1)
 183                *d++ = *s++;
 184
 185        return __dest;
 186}
 187
 188/*
 189 * gzip delarations
 190 */
 191#define OF(args)  args
 192#define STATIC static
 193
 194typedef unsigned char  uch;
 195typedef unsigned short ush;
 196typedef unsigned long  ulg;
 197
 198#define WSIZE 0x8000            /* Window size must be at least 32k, */
 199                                /* and a power of two */
 200
 201static uch *inbuf;              /* input buffer */
 202static uch window[WSIZE];       /* Sliding window buffer */
 203
 204static unsigned insize;         /* valid bytes in inbuf */
 205static unsigned inptr;          /* index of next byte to be processed in inbuf */
 206static unsigned outcnt;         /* bytes in output buffer */
 207
 208/* gzip flag byte */
 209#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
 210#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
 211#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
 212#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
 213#define COMMENT      0x10 /* bit 4 set: file comment present */
 214#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
 215#define RESERVED     0xC0 /* bit 6,7:   reserved */
 216
 217#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
 218
 219/* Diagnostic functions */
 220#ifdef DEBUG
 221#  define Assert(cond,msg) {if(!(cond)) error(msg);}
 222#  define Trace(x) fprintf x
 223#  define Tracev(x) {if (verbose) fprintf x ;}
 224#  define Tracevv(x) {if (verbose>1) fprintf x ;}
 225#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
 226#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
 227#else
 228#  define Assert(cond,msg)
 229#  define Trace(x)
 230#  define Tracev(x)
 231#  define Tracevv(x)
 232#  define Tracec(c,x)
 233#  define Tracecv(c,x)
 234#endif
 235
 236static int  fill_inbuf(void);
 237static void flush_window(void);
 238static void error(char *m);
 239
 240extern char input_data[];
 241extern char input_data_end[];
 242
 243static uch *output_data;
 244static ulg output_ptr;
 245static ulg bytes_out;
 246
 247static void error(char *m);
 248
 249static void putstr(const char *);
 250
 251extern int end;
 252static ulg free_mem_ptr;
 253static ulg free_mem_end_ptr;
 254
 255#ifdef STANDALONE_DEBUG
 256#define NO_INFLATE_MALLOC
 257#endif
 258
 259#define ARCH_HAS_DECOMP_WDOG
 260
 261#include "../../../../lib/inflate.c"
 262
 263/* ===========================================================================
 264 * Fill the input buffer. This is called only when the buffer is empty
 265 * and at least one byte is really needed.
 266 */
 267int fill_inbuf(void)
 268{
 269        if (insize != 0)
 270                error("ran out of input data");
 271
 272        inbuf = input_data;
 273        insize = &input_data_end[0] - &input_data[0];
 274
 275        inptr = 1;
 276        return inbuf[0];
 277}
 278
 279/* ===========================================================================
 280 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
 281 * (Used for the decompressed data only.)
 282 */
 283void flush_window(void)
 284{
 285        ulg c = crc;
 286        unsigned n;
 287        uch *in, *out, ch;
 288
 289        in = window;
 290        out = &output_data[output_ptr];
 291        for (n = 0; n < outcnt; n++) {
 292                ch = *out++ = *in++;
 293                c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
 294        }
 295        crc = c;
 296        bytes_out += (ulg)outcnt;
 297        output_ptr += (ulg)outcnt;
 298        outcnt = 0;
 299        putstr(".");
 300}
 301
 302#ifndef arch_error
 303#define arch_error(x)
 304#endif
 305
 306static void error(char *x)
 307{
 308        arch_error(x);
 309
 310        putstr("\n\n");
 311        putstr(x);
 312        putstr("\n\n -- System halted");
 313
 314        while(1);       /* Halt */
 315}
 316
 317#ifndef STANDALONE_DEBUG
 318
 319ulg
 320decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
 321                  int arch_id)
 322{
 323        output_data             = (uch *)output_start;  /* Points to kernel start */
 324        free_mem_ptr            = free_mem_ptr_p;
 325        free_mem_end_ptr        = free_mem_ptr_end_p;
 326        __machine_arch_type     = arch_id;
 327
 328        arch_decomp_setup();
 329
 330        makecrc();
 331        putstr("Uncompressing Linux...");
 332        gunzip();
 333        putstr(" done, booting the kernel.\n");
 334        return output_ptr;
 335}
 336#else
 337
 338char output_buffer[1500*1024];
 339
 340int main()
 341{
 342        output_data = output_buffer;
 343
 344        makecrc();
 345        putstr("Uncompressing Linux...");
 346        gunzip();
 347        putstr("done.\n");
 348        return 0;
 349}
 350#endif
 351        
 352