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 <mach/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);
 220
 221extern char input_data[];
 222extern char input_data_end[];
 223
 224static uch *output_data;
 225static ulg output_ptr;
 226static ulg bytes_out;
 227
 228static void error(char *m);
 229
 230static void putstr(const char *);
 231
 232extern int end;
 233static ulg free_mem_ptr;
 234static ulg free_mem_end_ptr;
 235
 236#ifdef STANDALONE_DEBUG
 237#define NO_INFLATE_MALLOC
 238#endif
 239
 240#define ARCH_HAS_DECOMP_WDOG
 241
 242#include "../../../../lib/inflate.c"
 243
 244/* ===========================================================================
 245 * Fill the input buffer. This is called only when the buffer is empty
 246 * and at least one byte is really needed.
 247 */
 248int fill_inbuf(void)
 249{
 250        if (insize != 0)
 251                error("ran out of input data");
 252
 253        inbuf = input_data;
 254        insize = &input_data_end[0] - &input_data[0];
 255
 256        inptr = 1;
 257        return inbuf[0];
 258}
 259
 260/* ===========================================================================
 261 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
 262 * (Used for the decompressed data only.)
 263 */
 264void flush_window(void)
 265{
 266        ulg c = crc;
 267        unsigned n;
 268        uch *in, *out, ch;
 269
 270        in = window;
 271        out = &output_data[output_ptr];
 272        for (n = 0; n < outcnt; n++) {
 273                ch = *out++ = *in++;
 274                c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
 275        }
 276        crc = c;
 277        bytes_out += (ulg)outcnt;
 278        output_ptr += (ulg)outcnt;
 279        outcnt = 0;
 280        putstr(".");
 281}
 282
 283#ifndef arch_error
 284#define arch_error(x)
 285#endif
 286
 287static void error(char *x)
 288{
 289        arch_error(x);
 290
 291        putstr("\n\n");
 292        putstr(x);
 293        putstr("\n\n -- System halted");
 294
 295        while(1);       /* Halt */
 296}
 297
 298#ifndef STANDALONE_DEBUG
 299
 300ulg
 301decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
 302                  int arch_id)
 303{
 304        output_data             = (uch *)output_start;  /* Points to kernel start */
 305        free_mem_ptr            = free_mem_ptr_p;
 306        free_mem_end_ptr        = free_mem_ptr_end_p;
 307        __machine_arch_type     = arch_id;
 308
 309        arch_decomp_setup();
 310
 311        makecrc();
 312        putstr("Uncompressing Linux...");
 313        gunzip();
 314        putstr(" done, booting the kernel.\n");
 315        return output_ptr;
 316}
 317#else
 318
 319char output_buffer[1500*1024];
 320
 321int main()
 322{
 323        output_data = output_buffer;
 324
 325        makecrc();
 326        putstr("Uncompressing Linux...");
 327        gunzip();
 328        putstr("done.\n");
 329        return 0;
 330}
 331#endif
 332        
 333
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.