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