home *** CD-ROM | disk | FTP | other *** search
- /*
- * misc.c
- *
- * This is a collection of several routines from gzip-1.0.3
- * adapted for Linux.
- *
- * malloc by Hannu Savolainen 1993
- * puts by Nick Holloway 1993
- */
-
- #include "gzip.h"
- #include "lzw.h"
-
- #include <linux/segment.h>
-
- /*
- * These are set up by the setup-routine at boot-time:
- */
-
- struct screen_info {
- unsigned char orig_x;
- unsigned char orig_y;
- unsigned char unused1[2];
- unsigned short orig_video_page;
- unsigned char orig_video_mode;
- unsigned char orig_video_cols;
- unsigned short orig_video_ega_ax;
- unsigned short orig_video_ega_bx;
- unsigned short orig_video_ega_cx;
- unsigned char orig_video_lines;
- };
-
- /*
- * This is set up by the setup-routine at boot-time
- */
- #define EXT_MEM_K (*(unsigned short *)0x90002)
- #define DRIVE_INFO (*(struct drive_info *)0x90080)
- #define SCREEN_INFO (*(struct screen_info *)0x90000)
- #define RAMDISK_SIZE (*(unsigned short *)0x901F8)
- #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
- #define AUX_DEVICE_INFO (*(unsigned char *)0x901FF)
-
- #define EOF -1
-
- DECLARE(uch, inbuf, INBUFSIZ);
- DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
- DECLARE(uch, window, WSIZE);
-
- unsigned outcnt;
- unsigned insize;
- unsigned inptr;
-
- extern char input_data[];
- extern int input_len;
-
- int input_ptr;
-
- int method, exit_code, part_nb, last_member;
- int test = 0;
- int force = 0;
- int verbose = 1;
- long bytes_in, bytes_out;
-
- char *output_data;
- unsigned long output_ptr;
-
- extern int end;
- long free_mem_ptr = (long)&end;
-
- int to_stdout = 0;
- int hard_math = 0;
-
- void (*work)(int inf, int outf);
- void makecrc(void);
-
- local int get_method(int);
-
- char *vidmem = (char *)0xb8000;
- int lines, cols;
-
- void *malloc(int size)
- {
- void *p;
-
- if (size <0) error("Malloc error\n");
- if (free_mem_ptr <= 0) error("Memory error\n");
-
- free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
-
- p = (void *)free_mem_ptr;
-
- free_mem_ptr += size;
-
- if (free_mem_ptr > 0x90000) error("\nOut of memory\n");
-
- if (p == NULL) error("malloc = NULL\n");
- return p;
- }
-
- void free(void *where)
- { /* Don't care */
- }
-
- static void scroll()
- {
- int i;
-
- memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
- for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
- vidmem[i] = ' ';
- }
-
- static void puts(char *s)
- {
- int x,y;
- char c;
-
- x = SCREEN_INFO.orig_x;
- y = SCREEN_INFO.orig_y;
-
- while ( ( c = *s++ ) != '\0' ) {
- if ( c == '\n' ) {
- x = 0;
- if ( ++y >= lines ) {
- scroll();
- y--;
- }
- } else {
- vidmem [ ( x + cols * y ) * 2 ] = c;
- if ( ++x >= cols ) {
- x = 0;
- if ( ++y >= lines ) {
- scroll();
- y--;
- }
- }
- }
- }
-
- SCREEN_INFO.orig_x = x;
- SCREEN_INFO.orig_y = y;
- }
-
- __ptr_t memset(__ptr_t s, int c, size_t n)
- {
- int i;
- char *ss = (char*)s;
-
- for (i=0;i<n;i++) ss[i] = c;
- }
-
- __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
- size_t __n)
- {
- int i;
- char *d = (char *)__dest, *s = (char *)__src;
-
- for (i=0;i<__n;i++) d[i] = s[i];
- }
-
- extern ulg crc_32_tab[]; /* crc table, defined below */
-
- /* ===========================================================================
- * Run a set of bytes through the crc shift register. If s is a NULL
- * pointer, then initialize the crc shift register contents instead.
- * Return the current crc in either case.
- */
- ulg updcrc(s, n)
- uch *s; /* pointer to bytes to pump through */
- unsigned n; /* number of bytes in s[] */
- {
- register ulg c; /* temporary variable */
-
- static ulg crc = (ulg)0xffffffffL; /* shift register contents */
-
- if (s == NULL) {
- c = 0xffffffffL;
- } else {
- c = crc;
- while (n--) {
- c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
- }
- }
- crc = c;
- return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
- }
-
- /* ===========================================================================
- * Clear input and output buffers
- */
- void clear_bufs()
- {
- outcnt = 0;
- insize = inptr = 0;
- bytes_in = bytes_out = 0L;
- }
-
- /* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
- int fill_inbuf()
- {
- int len, i;
-
- /* Read as much as possible */
- insize = 0;
- do {
- len = INBUFSIZ-insize;
- if (len > (input_len-input_ptr+1)) len=input_len-input_ptr+1;
- if (len == 0 || len == EOF) break;
-
- for (i=0;i<len;i++) inbuf[insize+i] = input_data[input_ptr+i];
- insize += len;
- input_ptr += len;
- } while (insize < INBUFSIZ);
-
- if (insize == 0) {
- error("unable to fill buffer\n");
- }
- bytes_in += (ulg)insize;
- inptr = 1;
- return inbuf[0];
- }
-
- /* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
- void flush_window()
- {
- if (outcnt == 0) return;
- updcrc(window, outcnt);
-
- memcpy(&output_data[output_ptr], (char *)window, outcnt);
-
- bytes_out += (ulg)outcnt;
- output_ptr += (ulg)outcnt;
- outcnt = 0;
- }
-
- /*
- * Code to compute the CRC-32 table. Borrowed from
- * gzip-1.0.3/makecrc.c.
- */
-
- ulg crc_32_tab[256];
-
- void
- makecrc(void)
- {
- /* Not copyrighted 1990 Mark Adler */
-
- unsigned long c; /* crc shift register */
- unsigned long e; /* polynomial exclusive-or pattern */
- int i; /* counter for all possible eight bit values */
- int k; /* byte being shifted into crc apparatus */
-
- /* terms of polynomial defining this crc (except x^32): */
- static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
-
- /* Make exclusive-or pattern from polynomial */
- e = 0;
- for (i = 0; i < sizeof(p)/sizeof(int); i++)
- e |= 1L << (31 - p[i]);
-
- crc_32_tab[0] = 0;
-
- for (i = 1; i < 256; i++)
- {
- c = 0;
- for (k = i | 256; k != 1; k >>= 1)
- {
- c = c & 1 ? (c >> 1) ^ e : c >> 1;
- if (k & 1)
- c ^= e;
- }
- crc_32_tab[i] = c;
- }
- }
-
- void error(char *x)
- {
- puts("\n\n");
- puts(x);
- puts("\n\n -- System halted");
-
- while(1); /* Halt */
- }
-
- #define STACK_SIZE (4096)
-
- long user_stack [STACK_SIZE];
-
- struct {
- long * a;
- short b;
- } stack_start = { & user_stack [STACK_SIZE] , KERNEL_DS };
-
- void decompress_kernel()
- {
- if (SCREEN_INFO.orig_video_mode == 7)
- vidmem = (char *) 0xb0000;
- else
- vidmem = (char *) 0xb8000;
-
- lines = SCREEN_INFO.orig_video_lines;
- cols = SCREEN_INFO.orig_video_cols;
-
- if (EXT_MEM_K < 1024) error("<2M of mem\n");
-
- output_data = (char *)1048576; /* Points to 1M */
- output_ptr = 0;
-
- exit_code = 0;
- test = 0;
- input_ptr = 0;
- part_nb = 0;
-
- clear_bufs();
- makecrc();
-
- puts("Uncompressing Linux...");
-
- method = get_method(0);
-
- work(0, 0);
-
- puts("done.\n");
-
- puts("Now booting the kernel\n");
- }
-
- /* ========================================================================
- * Check the magic number of the input file and update ofname if an
- * original name was given and to_stdout is not set.
- * Return the compression method, -1 for error, -2 for warning.
- * Set inptr to the offset of the next byte to be processed.
- * This function may be called repeatedly for an input file consisting
- * of several contiguous gzip'ed members.
- * IN assertions: there is at least one remaining compressed member.
- * If the member is a zip file, it must be the only one.
- */
- local int get_method(in)
- int in; /* input file descriptor */
- {
- uch flags;
- char magic[2]; /* magic header */
-
- magic[0] = (char)get_byte();
- magic[1] = (char)get_byte();
-
- method = -1; /* unknown yet */
- part_nb++; /* number of parts in gzip file */
- last_member = 0;
- /* assume multiple members in gzip file except for record oriented I/O */
-
- if (memcmp(magic, GZIP_MAGIC, 2) == 0
- || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
-
- work = unzip;
- method = (int)get_byte();
- flags = (uch)get_byte();
- if ((flags & ENCRYPTED) != 0) {
- error("Input is encrypted\n");
- exit_code = ERROR;
- return -1;
- }
- if ((flags & CONTINUATION) != 0) {
- error("Multi part input\n");
- exit_code = ERROR;
- if (force <= 1) return -1;
- }
- if ((flags & RESERVED) != 0) {
- error("Input has invalid flags\n");
- exit_code = ERROR;
- if (force <= 1) return -1;
- }
- (ulg)get_byte(); /* Get timestamp */
- ((ulg)get_byte()) << 8;
- ((ulg)get_byte()) << 16;
- ((ulg)get_byte()) << 24;
-
- (void)get_byte(); /* Ignore extra flags for the moment */
- (void)get_byte(); /* Ignore OS type for the moment */
-
- if ((flags & CONTINUATION) != 0) {
- unsigned part = (unsigned)get_byte();
- part |= ((unsigned)get_byte())<<8;
- if (verbose) {
- error("Input is not part number 1\n");
- }
- }
- if ((flags & EXTRA_FIELD) != 0) {
- unsigned len = (unsigned)get_byte();
- len |= ((unsigned)get_byte())<<8;
- while (len--) (void)get_byte();
- }
-
- /* Get original file name if it was truncated */
- if ((flags & ORIG_NAME) != 0) {
- if (to_stdout || part_nb > 1) {
- /* Discard the old name */
- while (get_byte() != 0) /* null */ ;
- } else {
- } /* to_stdout */
- } /* orig_name */
-
- /* Discard file comment if any */
- if ((flags & COMMENT) != 0) {
- while (get_byte() != 0) /* null */ ;
- }
-
- } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
- && memcmp(inbuf, PKZIP_MAGIC, 4) == 0) {
- /* To simplify the code, we support a zip file when alone only.
- * We are thus guaranteed that the entire local header fits in inbuf.
- */
- inptr = 0;
- work = unzip;
- if (check_zipfile(in) == -1) return -1;
- /* check_zipfile may get ofname from the local header */
- last_member = 1;
-
- } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
- error("packed input");
- } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {
- error("compressed input");
- last_member = 1;
- }
- if (method == -1) {
- error("Corrupted input\n");
- if (exit_code != ERROR) exit_code = part_nb == 1 ? ERROR : WARNING;
- return part_nb == 1 ? -1 : -2;
- }
- return method;
- }
-