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