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

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