linux-old/arch/x86_64/boot/compressed/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 and Matthias Urlichs 1994
   8 * puts by Nick Holloway 1993, better puts by Martin Mares 1995
   9 * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  10 */
  11
  12#include "miscsetup.h"
  13#include <asm/io.h>
  14
  15/*
  16 * gzip declarations
  17 */
  18
  19#define OF(args)  args
  20#define STATIC static
  21
  22#undef memset
  23#undef memcpy
  24#define memzero(s, n)     memset ((s), 0, (n))
  25
  26typedef unsigned char  uch;
  27typedef unsigned short ush;
  28typedef unsigned long  ulg;
  29
  30#define WSIZE 0x8000            /* Window size must be at least 32k, */
  31                                /* and a power of two */
  32
  33static uch *inbuf;           /* input buffer */
  34static uch window[WSIZE];    /* Sliding window buffer */
  35
  36static unsigned insize = 0;  /* valid bytes in inbuf */
  37static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
  38static unsigned outcnt = 0;  /* bytes in output buffer */
  39
  40/* gzip flag byte */
  41#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
  42#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
  43#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
  44#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
  45#define COMMENT      0x10 /* bit 4 set: file comment present */
  46#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
  47#define RESERVED     0xC0 /* bit 6,7:   reserved */
  48
  49#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
  50                
  51/* Diagnostic functions */
  52#ifdef DEBUG
  53#  define Assert(cond,msg) {if(!(cond)) error(msg);}
  54#  define Trace(x) fprintf x
  55#  define Tracev(x) {if (verbose) fprintf x ;}
  56#  define Tracevv(x) {if (verbose>1) fprintf x ;}
  57#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
  58#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
  59#else
  60#  define Assert(cond,msg)
  61#  define Trace(x)
  62#  define Tracev(x)
  63#  define Tracevv(x)
  64#  define Tracec(c,x)
  65#  define Tracecv(c,x)
  66#endif
  67
  68static int  fill_inbuf(void);
  69static void flush_window(void);
  70static void error(char *m);
  71static void gzip_mark(void **);
  72static void gzip_release(void **);
  73  
  74/*
  75 * This is set up by the setup-routine at boot-time
  76 */
  77static unsigned char *real_mode; /* Pointer to real-mode data */
  78
  79#define EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
  80#ifndef STANDARD_MEMORY_BIOS_CALL
  81#define ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
  82#endif
  83#define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
  84
  85extern char input_data[];
  86extern int input_len;
  87
  88static long bytes_out = 0;
  89static uch *output_data;
  90static unsigned long output_ptr = 0;
  91
  92 
  93static void *malloc(int size);
  94static void free(void *where);
  95static void error(char *m);
  96static void gzip_mark(void **);
  97static void gzip_release(void **);
  98 
  99static void putstr(const char *);
 100  
 101extern int end;
 102static long free_mem_ptr = (long)&end;
 103static long free_mem_end_ptr;
 104
 105#define INPLACE_MOVE_ROUTINE  0x1000
 106#define LOW_BUFFER_START      0x2000
 107#define LOW_BUFFER_MAX       0x90000
 108#define HEAP_SIZE             0x3000
 109static unsigned int low_buffer_end, low_buffer_size;
 110static int high_loaded =0;
 111static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
 112
 113static char *vidmem = (char *)0xb8000;
 114static int vidport;
 115static int lines, cols;
 116
 117#include "../../../../lib/inflate.c"
 118
 119static void *malloc(int size)
 120{
 121        void *p;
 122
 123        if (size <0) error("Malloc error\n");
 124        if (free_mem_ptr <= 0) error("Memory error\n");
 125
 126        free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
 127
 128        p = (void *)free_mem_ptr;
 129        free_mem_ptr += size;
 130
 131        if (free_mem_ptr >= free_mem_end_ptr)
 132                error("\nOut of memory\n");
 133
 134        return p;
 135}
 136
 137static void free(void *where)
 138{       /* Don't care */
 139}
 140
 141static void gzip_mark(void **ptr)
 142{
 143        *ptr = (void *) free_mem_ptr;
 144}
 145
 146static void gzip_release(void **ptr)
 147{
 148        free_mem_ptr = (long) *ptr;
 149}
 150 
 151static void scroll(void)
 152{
 153        int i;
 154
 155        memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
 156        for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
 157                vidmem[i] = ' ';
 158}
 159
 160static void putstr(const char *s)
 161{
 162        int x,y,pos;
 163        char c;
 164
 165        x = SCREEN_INFO.orig_x;
 166        y = SCREEN_INFO.orig_y;
 167
 168        while ( ( c = *s++ ) != '\0' ) {
 169                if ( c == '\n' ) {
 170                        x = 0;
 171                        if ( ++y >= lines ) {
 172                                scroll();
 173                                y--;
 174                        }
 175                } else {
 176                        vidmem [ ( x + cols * y ) * 2 ] = c; 
 177                        if ( ++x >= cols ) {
 178                                x = 0;
 179                                if ( ++y >= lines ) {
 180                                        scroll();
 181                                        y--;
 182                                }
 183                        }
 184                }
 185        }
 186
 187        SCREEN_INFO.orig_x = x;
 188        SCREEN_INFO.orig_y = y;
 189
 190        pos = (x + cols * y) * 2;       /* Update cursor position */
 191        outb_p(14, vidport);
 192        outb_p(0xff & (pos >> 9), vidport+1);
 193        outb_p(15, vidport);
 194        outb_p(0xff & (pos >> 1), vidport+1);
 195}
 196
 197void* memset(void* s, int c, size_t n)
 198{
 199        int i;
 200        char *ss = (char*)s;
 201
 202        for (i=0;i<n;i++) ss[i] = c;
 203        return s;
 204}
 205
 206void* memcpy(void* __dest, __const void* __src,
 207                            size_t __n)
 208{
 209        int i;
 210        char *d = (char *)__dest, *s = (char *)__src;
 211
 212        for (i=0;i<__n;i++) d[i] = s[i];
 213        return __dest;
 214}
 215
 216/* ===========================================================================
 217 * Fill the input buffer. This is called only when the buffer is empty
 218 * and at least one byte is really needed.
 219 */
 220static int fill_inbuf(void)
 221{
 222        if (insize != 0) {
 223                error("ran out of input data\n");
 224        }
 225
 226        inbuf = input_data;
 227        insize = input_len;
 228        inptr = 1;
 229        return inbuf[0];
 230}
 231
 232/* ===========================================================================
 233 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
 234 * (Used for the decompressed data only.)
 235 */
 236static void flush_window_low(void)
 237{
 238    ulg c = crc;         /* temporary variable */
 239    unsigned n;
 240    uch *in, *out, ch;
 241    
 242    in = window;
 243    out = &output_data[output_ptr]; 
 244    for (n = 0; n < outcnt; n++) {
 245            ch = *out++ = *in++;
 246            c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
 247    }
 248    crc = c;
 249    bytes_out += (ulg)outcnt;
 250    output_ptr += (ulg)outcnt;
 251    outcnt = 0;
 252}
 253
 254static void flush_window_high(void)
 255{
 256    ulg c = crc;         /* temporary variable */
 257    unsigned n;
 258    uch *in,  ch;
 259    in = window;
 260    for (n = 0; n < outcnt; n++) {
 261        ch = *output_data++ = *in++;
 262        if ((ulg)output_data == low_buffer_end) output_data=high_buffer_start;
 263        c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
 264    }
 265    crc = c;
 266    bytes_out += (ulg)outcnt;
 267    outcnt = 0;
 268}
 269
 270static void flush_window(void)
 271{
 272        if (high_loaded) flush_window_high();
 273        else flush_window_low();
 274}
 275
 276static void error(char *x)
 277{
 278        putstr("\n\n");
 279        putstr(x);
 280        putstr("\n\n -- System halted");
 281
 282        while(1);
 283}
 284
 285void setup_normal_output_buffer(void)
 286{
 287#ifdef STANDARD_MEMORY_BIOS_CALL
 288        if (EXT_MEM_K < 1024) error("Less than 2MB of memory.\n");
 289#else
 290        if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory.\n");
 291#endif
 292        output_data = (char *)0x100000; /* Points to 1M */
 293        free_mem_end_ptr = (long)real_mode;
 294}
 295
 296struct moveparams {
 297        uch *low_buffer_start;  int lcount;
 298        uch *high_buffer_start; int hcount;
 299};
 300
 301void setup_output_buffer_if_we_run_high(struct moveparams *mv)
 302{
 303        high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE);
 304#ifdef STANDARD_MEMORY_BIOS_CALL
 305        if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory.\n");
 306#else
 307        if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory.\n");
 308#endif  
 309        mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START;
 310        low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
 311          ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff;
 312        low_buffer_size = low_buffer_end - LOW_BUFFER_START;
 313        high_loaded = 1;
 314        free_mem_end_ptr = (long)high_buffer_start;
 315        if ( (0x100000 + low_buffer_size) > ((ulg)high_buffer_start)) {
 316                high_buffer_start = (uch *)(0x100000 + low_buffer_size);
 317                mv->hcount = 0; /* say: we need not to move high_buffer */
 318        }
 319        else mv->hcount = -1;
 320        mv->high_buffer_start = high_buffer_start;
 321}
 322
 323void close_output_buffer_if_we_run_high(struct moveparams *mv)
 324{
 325        if (bytes_out > low_buffer_size) {
 326                mv->lcount = low_buffer_size;
 327                if (mv->hcount)
 328                        mv->hcount = bytes_out - low_buffer_size;
 329        } else {
 330                mv->lcount = bytes_out;
 331                mv->hcount = 0;
 332        }
 333}
 334
 335int decompress_kernel(struct moveparams *mv, void *rmode)
 336{
 337        real_mode = rmode;
 338
 339        if (SCREEN_INFO.orig_video_mode == 7) {
 340                vidmem = (char *) 0xb0000;
 341                vidport = 0x3b4;
 342        } else {
 343                vidmem = (char *) 0xb8000;
 344                vidport = 0x3d4;
 345        }
 346
 347        lines = SCREEN_INFO.orig_video_lines;
 348        cols = SCREEN_INFO.orig_video_cols;
 349
 350        if (free_mem_ptr < 0x100000) setup_normal_output_buffer();
 351        else setup_output_buffer_if_we_run_high(mv);
 352
 353        makecrc();
 354        putstr(".\nDecompressing Linux...");
 355        gunzip();
 356        putstr("done.\nBooting the kernel.\n");
 357        if (high_loaded) close_output_buffer_if_we_run_high(mv);
 358        return high_loaded;
 359}
 360
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.