root/arch/i386/boot/compressed/misc.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. malloc
  2. free
  3. scroll
  4. puts
  5. memset
  6. memcpy
  7. updcrc
  8. clear_bufs
  9. fill_inbuf
  10. flush_window
  11. makecrc
  12. error
  13. decompress_kernel
  14. get_method

   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  * puts by Nick Holloway 1993
   9  */
  10 
  11 #include "gzip.h"
  12 #include "lzw.h"
  13 
  14 #include <asm/segment.h>
  15 
  16 /*
  17  * These are set up by the setup-routine at boot-time:
  18  */
  19 
  20 struct screen_info {
  21         unsigned char  orig_x;
  22         unsigned char  orig_y;
  23         unsigned char  unused1[2];
  24         unsigned short orig_video_page;
  25         unsigned char  orig_video_mode;
  26         unsigned char  orig_video_cols;
  27         unsigned short orig_video_ega_ax;
  28         unsigned short orig_video_ega_bx;
  29         unsigned short orig_video_ega_cx;
  30         unsigned char  orig_video_lines;
  31 };
  32 
  33 /*
  34  * This is set up by the setup-routine at boot-time
  35  */
  36 #define EXT_MEM_K (*(unsigned short *)0x90002)
  37 #define DRIVE_INFO (*(struct drive_info *)0x90080)
  38 #define SCREEN_INFO (*(struct screen_info *)0x90000)
  39 #define RAMDISK_SIZE (*(unsigned short *)0x901F8)
  40 #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
  41 #define AUX_DEVICE_INFO (*(unsigned char *)0x901FF)
  42 
  43 #define EOF -1
  44 
  45 DECLARE(uch, inbuf, INBUFSIZ);
  46 DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
  47 DECLARE(uch, window, WSIZE);
  48 
  49 unsigned outcnt;
  50 unsigned insize;
  51 unsigned inptr;
  52 
  53 extern char input_data[];
  54 extern int input_len;
  55 
  56 int input_ptr;
  57 
  58 int method, exit_code, part_nb, last_member;
  59 int test = 0;
  60 int force = 0;
  61 int verbose = 1;
  62 long bytes_in, bytes_out;
  63 
  64 char *output_data;
  65 unsigned long output_ptr;
  66 
  67 extern int end;
  68 long free_mem_ptr = (long)&end;
  69 
  70 int to_stdout = 0;
  71 int hard_math = 0;
  72 
  73 void (*work)(int inf, int outf);
  74 void makecrc(void);
  75 
  76 local int get_method(int);
  77 
  78 char *vidmem = (char *)0xb8000;
  79 int lines, cols;
  80 
  81 static void puts(const char *);
  82 
  83 void *malloc(int size)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85         void *p;
  86 
  87         if (size <0) error("Malloc error\n");
  88         if (free_mem_ptr <= 0) error("Memory error\n");
  89 
  90    while(1) {
  91         free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
  92 
  93         p = (void *)free_mem_ptr;
  94         free_mem_ptr += size;
  95 
  96         /*
  97          * The part of the compressed kernel which has already been expanded
  98          * is no longer needed. Therefore we can reuse it for malloc.
  99          * With bigger kernels, this is necessary.
 100          */
 101           
 102         if (free_mem_ptr < (long)&end) {
 103                 if (free_mem_ptr > (long)&input_data[input_ptr])
 104                         error("\nOut of memory\n");
 105 
 106                 return p;
 107         }
 108         if (free_mem_ptr < 0x90000)
 109         return p;
 110         puts("large kernel, low 1M tight...");
 111         free_mem_ptr = (long)input_data;
 112         }
 113 }
 114 
 115 void free(void *where)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {       /* Don't care */
 117 }
 118 
 119 static void scroll()
     /* [previous][next][first][last][top][bottom][index][help] */
 120 {
 121         int i;
 122 
 123         memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
 124         for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
 125                 vidmem[i] = ' ';
 126 }
 127 
 128 static void puts(const char *s)
     /* [previous][next][first][last][top][bottom][index][help] */
 129 {
 130         int x,y;
 131         char c;
 132 
 133         x = SCREEN_INFO.orig_x;
 134         y = SCREEN_INFO.orig_y;
 135 
 136         while ( ( c = *s++ ) != '\0' ) {
 137                 if ( c == '\n' ) {
 138                         x = 0;
 139                         if ( ++y >= lines ) {
 140                                 scroll();
 141                                 y--;
 142                         }
 143                 } else {
 144                         vidmem [ ( x + cols * y ) * 2 ] = c; 
 145                         if ( ++x >= cols ) {
 146                                 x = 0;
 147                                 if ( ++y >= lines ) {
 148                                         scroll();
 149                                         y--;
 150                                 }
 151                         }
 152                 }
 153         }
 154 
 155         SCREEN_INFO.orig_x = x;
 156         SCREEN_INFO.orig_y = y;
 157 }
 158 
 159 __ptr_t memset(__ptr_t s, int c, size_t n)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161         int i;
 162         char *ss = (char*)s;
 163 
 164         for (i=0;i<n;i++) ss[i] = c;
 165 }
 166 
 167 __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
     /* [previous][next][first][last][top][bottom][index][help] */
 168                             size_t __n)
 169 {
 170         int i;
 171         char *d = (char *)__dest, *s = (char *)__src;
 172 
 173         for (i=0;i<__n;i++) d[i] = s[i];
 174 }
 175 
 176 extern ulg crc_32_tab[];   /* crc table, defined below */
 177 
 178 /* ===========================================================================
 179  * Run a set of bytes through the crc shift register.  If s is a NULL
 180  * pointer, then initialize the crc shift register contents instead.
 181  * Return the current crc in either case.
 182  */
 183 ulg updcrc(s, n)
     /* [previous][next][first][last][top][bottom][index][help] */
 184     uch *s;                 /* pointer to bytes to pump through */
 185     unsigned n;             /* number of bytes in s[] */
 186 {
 187     register ulg c;         /* temporary variable */
 188 
 189     static ulg crc = (ulg)0xffffffffL; /* shift register contents */
 190 
 191     if (s == NULL) {
 192         c = 0xffffffffL;
 193     } else {
 194         c = crc;
 195         while (n--) {
 196             c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
 197         }
 198     }
 199     crc = c;
 200     return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
 201 }
 202 
 203 /* ===========================================================================
 204  * Clear input and output buffers
 205  */
 206 void clear_bufs()
     /* [previous][next][first][last][top][bottom][index][help] */
 207 {
 208     outcnt = 0;
 209     insize = inptr = 0;
 210     bytes_in = bytes_out = 0L;
 211 }
 212 
 213 /* ===========================================================================
 214  * Fill the input buffer. This is called only when the buffer is empty
 215  * and at least one byte is really needed.
 216  */
 217 int fill_inbuf()
     /* [previous][next][first][last][top][bottom][index][help] */
 218 {
 219     int len, i;
 220 
 221     /* Read as much as possible */
 222     insize = 0;
 223     do {
 224         len = INBUFSIZ-insize;
 225         if (len > (input_len-input_ptr+1)) len=input_len-input_ptr+1;
 226         if (len == 0 || len == EOF) break;
 227 
 228         for (i=0;i<len;i++) inbuf[insize+i] = input_data[input_ptr+i];
 229         insize += len;
 230         input_ptr += len;
 231     } while (insize < INBUFSIZ);
 232 
 233     if (insize == 0) {
 234         error("unable to fill buffer\n");
 235     }
 236     bytes_in += (ulg)insize;
 237     inptr = 1;
 238     return inbuf[0];
 239 }
 240 
 241 /* ===========================================================================
 242  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
 243  * (Used for the decompressed data only.)
 244  */
 245 void flush_window()
     /* [previous][next][first][last][top][bottom][index][help] */
 246 {
 247     if (outcnt == 0) return;
 248     updcrc(window, outcnt);
 249 
 250     memcpy(&output_data[output_ptr], (char *)window, outcnt);
 251 
 252     bytes_out += (ulg)outcnt;
 253     output_ptr += (ulg)outcnt;
 254     outcnt = 0;
 255 }
 256 
 257 /*
 258  * Code to compute the CRC-32 table. Borrowed from 
 259  * gzip-1.0.3/makecrc.c.
 260  */
 261 
 262 ulg crc_32_tab[256];
 263 
 264 void
 265 makecrc(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 266 {
 267 /* Not copyrighted 1990 Mark Adler      */
 268 
 269   unsigned long c;      /* crc shift register */
 270   unsigned long e;      /* polynomial exclusive-or pattern */
 271   int i;                /* counter for all possible eight bit values */
 272   int k;                /* byte being shifted into crc apparatus */
 273 
 274   /* terms of polynomial defining this crc (except x^32): */
 275   static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
 276 
 277   /* Make exclusive-or pattern from polynomial */
 278   e = 0;
 279   for (i = 0; i < sizeof(p)/sizeof(int); i++)
 280     e |= 1L << (31 - p[i]);
 281 
 282   crc_32_tab[0] = 0;
 283 
 284   for (i = 1; i < 256; i++)
 285   {
 286     c = 0;
 287     for (k = i | 256; k != 1; k >>= 1)
 288     {
 289       c = c & 1 ? (c >> 1) ^ e : c >> 1;
 290       if (k & 1)
 291         c ^= e;
 292     }
 293     crc_32_tab[i] = c;
 294   }
 295 }
 296 
 297 void error(char *x)
     /* [previous][next][first][last][top][bottom][index][help] */
 298 {
 299         puts("\n\n");
 300         puts(x);
 301         puts("\n\n -- System halted");
 302 
 303         while(1);       /* Halt */
 304 }
 305 
 306 #define STACK_SIZE (4096)
 307 
 308 long user_stack [STACK_SIZE];
 309 
 310 struct {
 311         long * a;
 312         short b;
 313         } stack_start = { & user_stack [STACK_SIZE] , KERNEL_DS };
 314 
 315 void decompress_kernel()
     /* [previous][next][first][last][top][bottom][index][help] */
 316 {
 317         if (SCREEN_INFO.orig_video_mode == 7)
 318                 vidmem = (char *) 0xb0000;
 319         else
 320                 vidmem = (char *) 0xb8000;
 321 
 322         lines = SCREEN_INFO.orig_video_lines;
 323         cols = SCREEN_INFO.orig_video_cols;
 324 
 325         if (EXT_MEM_K < 1024) error("<2M of mem\n");
 326 
 327         output_data = (char *)0x100000; /* Points to 1M */
 328         output_ptr = 0;
 329 
 330         exit_code = 0;
 331         test = 0;
 332         input_ptr = 0;
 333         part_nb = 0;
 334 
 335         clear_bufs();
 336         makecrc();
 337 
 338         puts("Uncompressing Linux...");
 339 
 340         method = get_method(0);
 341 
 342         work(0, 0);
 343 
 344         puts("done.\n");
 345 
 346         puts("Now booting the kernel\n");
 347 }
 348 
 349 /* ========================================================================
 350  * Check the magic number of the input file and update ofname if an
 351  * original name was given and to_stdout is not set.
 352  * Return the compression method, -1 for error, -2 for warning.
 353  * Set inptr to the offset of the next byte to be processed.
 354  * This function may be called repeatedly for an input file consisting
 355  * of several contiguous gzip'ed members.
 356  * IN assertions: there is at least one remaining compressed member.
 357  *   If the member is a zip file, it must be the only one.
 358  */
 359 local int get_method(in)
     /* [previous][next][first][last][top][bottom][index][help] */
 360     int in;        /* input file descriptor */
 361 {
 362     uch flags;
 363     char magic[2]; /* magic header */
 364 
 365     magic[0] = (char)get_byte();
 366     magic[1] = (char)get_byte();
 367 
 368     method = -1;                 /* unknown yet */
 369     part_nb++;                   /* number of parts in gzip file */
 370     last_member = 0;
 371     /* assume multiple members in gzip file except for record oriented I/O */
 372 
 373     if (memcmp(magic, GZIP_MAGIC, 2) == 0
 374         || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
 375 
 376         work = unzip;
 377         method = (int)get_byte();
 378         flags  = (uch)get_byte();
 379         if ((flags & ENCRYPTED) != 0)
 380             error("Input is encrypted\n");
 381         if ((flags & CONTINUATION) != 0)
 382                error("Multi part input\n");
 383         if ((flags & RESERVED) != 0) {
 384             error("Input has invalid flags\n");
 385             exit_code = ERROR;
 386             if (force <= 1) return -1;
 387         }
 388         (ulg)get_byte();        /* Get timestamp */
 389         ((ulg)get_byte()) << 8;
 390         ((ulg)get_byte()) << 16;
 391         ((ulg)get_byte()) << 24;
 392 
 393         (void)get_byte();  /* Ignore extra flags for the moment */
 394         (void)get_byte();  /* Ignore OS type for the moment */
 395 
 396         if ((flags & EXTRA_FIELD) != 0) {
 397             unsigned len = (unsigned)get_byte();
 398             len |= ((unsigned)get_byte())<<8;
 399             while (len--) (void)get_byte();
 400         }
 401 
 402         /* Get original file name if it was truncated */
 403         if ((flags & ORIG_NAME) != 0) {
 404             if (to_stdout || part_nb > 1) {
 405                 /* Discard the old name */
 406                 while (get_byte() != 0) /* null */ ;
 407             } else {
 408             } /* to_stdout */
 409         } /* orig_name */
 410 
 411         /* Discard file comment if any */
 412         if ((flags & COMMENT) != 0) {
 413             while (get_byte() != 0) /* null */ ;
 414         }
 415     } else
 416         error("unknown compression method");
 417     return method;
 418 }

/* [previous][next][first][last][top][bottom][index][help] */