home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / arch / i386 / boot / compressed / misc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-19  |  9.2 KB  |  419 lines

  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)
  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)
  116. {    /* Don't care */
  117. }
  118.  
  119. static void scroll()
  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)
  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)
  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,
  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)
  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()
  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()
  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()
  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)
  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)
  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()
  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)
  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. }
  419.