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

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