Beispiel #1
0
/* Release everything, including the underlying file object.  */
static grub_err_t
grub_gzio_close (grub_file_t file)
{
  grub_gzio_t gzio = file->data;

  grub_file_close (gzio->file);
  huft_free (gzio->tl);
  huft_free (gzio->td);
  grub_free (gzio);

  /* No need to close the same device twice.  */
  file->device = 0;

  return grub_errno;
}
Beispiel #2
0
static void
initialize_tables (grub_gzio_t gzio)
{
    gzio->saved_offset = 0;
    gzio_seek (gzio, gzio->data_offset);

    /* Initialize the bit buffer.  */
    gzio->bk = 0;
    gzio->bb = 0;

    /* Reset partial decompression code.  */
    gzio->last_block = 0;
    gzio->block_len = 0;

    /* Reset memory allocation stuff.  */
    huft_free (gzio->tl);
    huft_free (gzio->td);
}
Beispiel #3
0
static void
init_fixed_block (grub_file_t file)
{
  int i;			/* temporary variable */
  unsigned l[288];		/* length list for huft_build */
  grub_gzio_t gzio = file->data;

  /* set up literal table */
  for (i = 0; i < 144; i++)
    l[i] = 8;
  for (; i < 256; i++)
    l[i] = 9;
  for (; i < 280; i++)
    l[i] = 7;
  for (; i < 288; i++)		/* make a complete, but wrong code set */
    l[i] = 8;
  gzio->bl = 7;
  if (huft_build (l, 288, 257, cplens, cplext, &gzio->tl, &gzio->bl) != 0)
    {
      if (grub_errno == GRUB_ERR_NONE)
	grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
		    "failed in building a Huffman code table");
      return;
    }

  /* set up distance table */
  for (i = 0; i < 30; i++)	/* make an incomplete code set */
    l[i] = 5;
  gzio->bd = 5;
  if (huft_build (l, 30, 0, cpdist, cpdext, &gzio->td, &gzio->bd) > 1)
    {
      if (grub_errno == GRUB_ERR_NONE)
	grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
		    "failed in building a Huffman code table");
      huft_free (gzio->tl);
      gzio->tl = 0;
      return;
    }

  /* indicate we're now working on a block */
  gzio->code_state = 0;
  gzio->block_len++;
}
Beispiel #4
0
static void
init_dynamic_block (grub_file_t file)
{
  int i;			/* temporary variables */
  unsigned j;
  unsigned l;			/* last length */
  unsigned m;			/* mask for bit lengths table */
  unsigned n;			/* number of lengths to get */
  unsigned nb;			/* number of bit length codes */
  unsigned nl;			/* number of literal/length codes */
  unsigned nd;			/* number of distance codes */
  unsigned ll[286 + 30];	/* literal/length and distance code lengths */
  register ulg b;		/* bit buffer */
  register unsigned k;		/* number of bits in bit buffer */
  grub_gzio_t gzio = file->data;

  /* make local bit buffer */
  b = gzio->bb;
  k = gzio->bk;

  /* read in table lengths */
  NEEDBITS (5);
  nl = 257 + ((unsigned) b & 0x1f);	/* number of literal/length codes */
  DUMPBITS (5);
  NEEDBITS (5);
  nd = 1 + ((unsigned) b & 0x1f);	/* number of distance codes */
  DUMPBITS (5);
  NEEDBITS (4);
  nb = 4 + ((unsigned) b & 0xf);	/* number of bit length codes */
  DUMPBITS (4);
  if (nl > 286 || nd > 30)
    {
      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too much data");
      return;
    }

  /* read in bit-length-code lengths */
  for (j = 0; j < nb; j++)
    {
      NEEDBITS (3);
      ll[bitorder[j]] = (unsigned) b & 7;
      DUMPBITS (3);
    }
  for (; j < 19; j++)
    ll[bitorder[j]] = 0;

  /* build decoding table for trees--single level, 7 bit lookup */
  gzio->bl = 7;
  if (huft_build (ll, 19, 19, NULL, NULL, &gzio->tl, &gzio->bl) != 0)
    {
      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
		  "failed in building a Huffman code table");
      return;
    }

  /* read in literal and distance code lengths */
  n = nl + nd;
  m = mask_bits[gzio->bl];
  i = l = 0;
  while ((unsigned) i < n)
    {
      NEEDBITS ((unsigned) gzio->bl);
      j = (gzio->td = gzio->tl + ((unsigned) b & m))->b;
      DUMPBITS (j);
      j = gzio->td->v.n;
      if (j < 16)		/* length of code in bits (0..15) */
	ll[i++] = l = j;	/* save last length in l */
      else if (j == 16)		/* repeat last length 3 to 6 times */
	{
	  NEEDBITS (2);
	  j = 3 + ((unsigned) b & 3);
	  DUMPBITS (2);
	  if ((unsigned) i + j > n)
	    {
	      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
	      return;
	    }
	  while (j--)
	    ll[i++] = l;
	}
      else if (j == 17)		/* 3 to 10 zero length codes */
	{
	  NEEDBITS (3);
	  j = 3 + ((unsigned) b & 7);
	  DUMPBITS (3);
	  if ((unsigned) i + j > n)
	    {
	      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
	      return;
	    }
	  while (j--)
	    ll[i++] = 0;
	  l = 0;
	}
      else
	/* j == 18: 11 to 138 zero length codes */
	{
	  NEEDBITS (7);
	  j = 11 + ((unsigned) b & 0x7f);
	  DUMPBITS (7);
	  if ((unsigned) i + j > n)
	    {
	      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
	      return;
	    }
	  while (j--)
	    ll[i++] = 0;
	  l = 0;
	}
    }

  /* free decoding table for trees */
  huft_free (gzio->tl);
  gzio->td = 0;
  gzio->tl = 0;

  /* restore the global bit buffer */
  gzio->bb = b;
  gzio->bk = k;

  /* build the decoding tables for literal/length and distance codes */
  gzio->bl = lbits;
  if (huft_build (ll, nl, 257, cplens, cplext, &gzio->tl, &gzio->bl) != 0)
    {
      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
		  "failed in building a Huffman code table");
      return;
    }
  gzio->bd = dbits;
  if (huft_build (ll + nl, nd, 0, cpdist, cpdext, &gzio->td, &gzio->bd) != 0)
    {
      huft_free (gzio->tl);
      gzio->tl = 0;
      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
		  "failed in building a Huffman code table");
      return;
    }

  /* indicate we're now working on a block */
  gzio->code_state = 0;
  gzio->block_len++;
}
Beispiel #5
0
static int
huft_build (unsigned *b,	/* code lengths in bits (all assumed <= BMAX) */
	    unsigned n,		/* number of codes (assumed <= N_MAX) */
	    unsigned s,		/* number of simple-valued codes (0..s-1) */
	    ush * d,		/* list of base values for non-simple codes */
	    ush * e,		/* list of extra bits for non-simple codes */
	    struct huft **t,	/* result: starting table */
	    int *m)		/* maximum lookup bits, returns actual */
{
  unsigned a;			/* counter for codes of length k */
  unsigned c[BMAX + 1];		/* bit length count table */
  unsigned f;			/* i repeats in table every f entries */
  int g;			/* maximum code length */
  int h;			/* table level */
  register unsigned i;		/* counter, current code */
  register unsigned j;		/* counter */
  register int k;		/* number of bits in current code */
  int l;			/* bits per table (returned in m) */
  register unsigned *p;		/* pointer into c[], b[], or v[] */
  register struct huft *q;	/* points to current table */
  struct huft r;		/* table entry for structure assignment */
  struct huft *u[BMAX];		/* table stack */
  unsigned v[N_MAX];		/* values in order of bit length */
  register int w;		/* bits before this table == (l * h) */
  unsigned x[BMAX + 1];		/* bit offsets, then code stack */
  unsigned *xp;			/* pointer into x */
  int y;			/* number of dummy codes added */
  unsigned z;			/* number of entries in current table */

  /* Generate counts for each bit length */
  grub_memset ((char *) c, 0, sizeof (c));
  p = b;
  i = n;
  do
    {
      c[*p]++;			/* assume all entries <= BMAX */
      p++;			/* Can't combine with above line (Solaris bug) */
    }
  while (--i);
  if (c[0] == n)		/* null input--all zero length codes */
    {
      *t = (struct huft *) NULL;
      *m = 0;
      return 0;
    }

  /* Find minimum and maximum length, bound *m by those */
  l = *m;
  for (j = 1; j <= BMAX; j++)
    if (c[j])
      break;
  k = j;			/* minimum code length */
  if ((unsigned) l < j)
    l = j;
  for (i = BMAX; i; i--)
    if (c[i])
      break;
  g = i;			/* maximum code length */
  if ((unsigned) l > i)
    l = i;
  *m = l;

  /* Adjust last length count to fill out codes, if needed */
  for (y = 1 << j; j < i; j++, y <<= 1)
    if ((y -= c[j]) < 0)
      return 2;			/* bad input: more codes than bits */
  if ((y -= c[i]) < 0)
    return 2;
  c[i] += y;

  /* Generate starting offsets into the value table for each length */
  x[1] = j = 0;
  p = c + 1;
  xp = x + 2;
  while (--i)
    {				/* note that i == g from above */
      *xp++ = (j += *p++);
    }

  /* Make a table of values in order of bit lengths */
  p = b;
  i = 0;
  do
    {
      if ((j = *p++) != 0)
	v[x[j]++] = i;
    }
  while (++i < n);

  /* Generate the Huffman codes and for each, make the table entries */
  x[0] = i = 0;			/* first Huffman code is zero */
  p = v;			/* grab values in bit order */
  h = -1;			/* no tables yet--level -1 */
  w = -l;			/* bits decoded == (l * h) */
  u[0] = (struct huft *) NULL;	/* just to keep compilers happy */
  q = (struct huft *) NULL;	/* ditto */
  z = 0;			/* ditto */

  /* go through the bit lengths (k already is bits in shortest code) */
  for (; k <= g; k++)
    {
      a = c[k];
      while (a--)
	{
	  /* here i is the Huffman code of length k bits for value *p */
	  /* make tables up to required level */
	  while (k > w + l)
	    {
	      h++;
	      w += l;		/* previous table always l bits */

	      /* compute minimum size table less than or equal to l bits */
	      z = (z = (unsigned) (g - w)) > (unsigned) l ? (unsigned) l : z;	/* upper limit on table size */
	      if ((f = 1 << (j = k - w)) > a + 1)	/* try a k-w bit table */
		{		/* too few codes for k-w bit table */
		  f -= a + 1;	/* deduct codes from patterns left */
		  xp = c + k;
		  while (++j < z)	/* try smaller tables up to z bits */
		    {
		      if ((f <<= 1) <= *++xp)
			break;	/* enough codes to use up j bits */
		      f -= *xp;	/* else deduct codes from patterns */
		    }
		}
	      z = 1 << j;	/* table entries for j-bit table */

	      /* allocate and link in new table */
	      q = (struct huft *) grub_malloc ((z + 1) * sizeof (struct huft));
	      if (! q)
		{
		  if (h)
		    huft_free (u[0]);
		  return 3;
		}

	      *t = q + 1;	/* link to list for huft_free() */
	      *(t = &(q->v.t)) = (struct huft *) NULL;
	      u[h] = ++q;	/* table starts after link */

	      /* connect to last table, if there is one */
	      if (h)
		{
		  x[h] = i;	/* save pattern for backing up */
		  r.b = (uch) l;	/* bits to dump before this table */
		  r.e = (uch) (16 + j);		/* bits in this table */
		  r.v.t = q;	/* pointer to this table */
		  j = i >> (w - l);	/* (get around Turbo C bug) */
		  u[h - 1][j] = r;	/* connect to last table */
		}
	    }

	  /* set up table entry in r */
	  r.b = (uch) (k - w);
	  if (p >= v + n)
	    r.e = 99;		/* out of values--invalid code */
	  else if (*p < s)
	    {
	      r.e = (uch) (*p < 256 ? 16 : 15);		/* 256 is end-of-block code */
	      r.v.n = (ush) (*p);	/* simple code is just the value */
	      p++;		/* one compiler does not like *p++ */
	    }
	  else
	    {
	      r.e = (uch) e[*p - s];	/* non-simple--look up in lists */
	      r.v.n = d[*p++ - s];
	    }

	  /* fill code-like entries with r */
	  f = 1 << (k - w);
	  for (j = i >> w; j < z; j += f)
	    q[j] = r;

	  /* backwards increment the k-bit code i */
	  for (j = 1 << (k - 1); i & j; j >>= 1)
	    i ^= j;
	  i ^= j;

	  /* backup over finished tables */
	  while ((i & ((1 << w) - 1)) != x[h])
	    {
	      h--;		/* don't need to update q */
	      w -= l;
	    }
	}
    }

  /* Return true (1) if we were given an incomplete table */
  return y != 0 && g != 1;
}
Beispiel #6
0
static void
inflate_window (grub_file_t file)
{
  grub_gzio_t gzio = file->data;

  /* initialize window */
  gzio->wp = 0;

  /*
   *  Main decompression loop.
   */

  while (gzio->wp < WSIZE && grub_errno == GRUB_ERR_NONE)
    {
      if (! gzio->block_len)
	{
	  if (gzio->last_block)
	    break;

	  get_new_block (file);
	}

      if (gzio->block_type > INFLATE_DYNAMIC)
	grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
		    "unknown block type %d", gzio->block_type);

      if (grub_errno != GRUB_ERR_NONE)
	return;

      /*
       *  Expand stored block here.
       */
      if (gzio->block_type == INFLATE_STORED)
	{
	  int w = gzio->wp;

	  /*
	   *  This is basically a glorified pass-through
	   */

	  while (gzio->block_len && w < WSIZE && grub_errno == GRUB_ERR_NONE)
	    {
	      gzio->slide[w++] = get_byte (file);
	      gzio->block_len--;
	    }

	  gzio->wp = w;

	  continue;
	}

      /*
       *  Expand other kind of block.
       */

      if (inflate_codes_in_window (file))
	{
	  huft_free (gzio->tl);
	  huft_free (gzio->td);
	  gzio->tl = 0;
	  gzio->td = 0;
	}
    }

  gzio->saved_offset += WSIZE;

  /* XXX do CRC calculation here! */
}
/* called once from inflate_get_next_window */
static int inflate_codes(STATE_PARAM_ONLY)
{
	unsigned e;	/* table entry flag/number of extra bits */
	huft_t *t;	/* pointer to table entry */

	if (resume_copy) goto do_copy;

	while (1) {			/* do until end of block */
		bb = fill_bitbuffer(PASS_STATE bb, &k, bl);
		t = tl + ((unsigned) bb & ml);
		e = t->e;
		if (e > 16)
			do {
				if (e == 99) {
//shouldn't we propagate error?
					bb_error_msg_and_die("inflate_codes error 1");
				}
				bb >>= t->b;
				k -= t->b;
				e -= 16;
				bb = fill_bitbuffer(PASS_STATE bb, &k, e);
				t = t->v.t + ((unsigned) bb & mask_bits[e]);
				e = t->e;
			} while (e > 16);
		bb >>= t->b;
		k -= t->b;
		if (e == 16) {	/* then it's a literal */
			gunzip_window[w++] = (unsigned char) t->v.n;
			if (w == GUNZIP_WSIZE) {
				gunzip_outbuf_count = w;
				//flush_gunzip_window();
				w = 0;
				return 1; // We have a block to read
			}
		} else {		/* it's an EOB or a length */
			/* exit if end of block */
			if (e == 15) {
				break;
			}

			/* get length of block to copy */
			bb = fill_bitbuffer(PASS_STATE bb, &k, e);
			nn = t->v.n + ((unsigned) bb & mask_bits[e]);
			bb >>= e;
			k -= e;

			/* decode distance of block to copy */
			bb = fill_bitbuffer(PASS_STATE bb, &k, bd);
			t = td + ((unsigned) bb & md);
			e = t->e;
			if (e > 16)
				do {
					if (e == 99)
//shouldn't we propagate error?
						bb_error_msg_and_die("inflate_codes error 2");
					bb >>= t->b;
					k -= t->b;
					e -= 16;
					bb = fill_bitbuffer(PASS_STATE bb, &k, e);
					t = t->v.t + ((unsigned) bb & mask_bits[e]);
					e = t->e;
				} while (e > 16);
			bb >>= t->b;
			k -= t->b;
			bb = fill_bitbuffer(PASS_STATE bb, &k, e);
			dd = w - t->v.n - ((unsigned) bb & mask_bits[e]);
			bb >>= e;
			k -= e;

			/* do the copy */
 do_copy:
			do {
				/* Was: nn -= (e = (e = GUNZIP_WSIZE - ((dd &= GUNZIP_WSIZE - 1) > w ? dd : w)) > nn ? nn : e); */
				/* Who wrote THAT?? rewritten as: */
				dd &= GUNZIP_WSIZE - 1;
				e = GUNZIP_WSIZE - (dd > w ? dd : w);
				if (e > nn) e = nn;
				nn -= e;

				/* copy to new buffer to prevent possible overwrite */
				if (w - dd >= e) {	/* (this test assumes unsigned comparison) */
					memcpy(gunzip_window + w, gunzip_window + dd, e);
					w += e;
					dd += e;
				} else {
					/* do it slow to avoid memcpy() overlap */
					/* !NOMEMCPY */
					do {
						gunzip_window[w++] = gunzip_window[dd++];
					} while (--e);
				}
				if (w == GUNZIP_WSIZE) {
					gunzip_outbuf_count = w;
					resume_copy = (nn != 0);
					//flush_gunzip_window();
					w = 0;
					return 1;
				}
			} while (nn);
			resume_copy = 0;
		}
	}

	/* restore the globals from the locals */
	gunzip_outbuf_count = w;	/* restore global gunzip_window pointer */
	gunzip_bb = bb;			/* restore global bit buffer */
	gunzip_bk = k;

	/* normally just after call to inflate_codes, but save code by putting it here */
	/* free the decoding tables, return */
	huft_free(tl);
	huft_free(td);

	/* done */
	return 0;
}
Beispiel #8
0
static int inflate_codes(huft_t * my_tl, huft_t * my_td,
                         const unsigned int my_bl, const unsigned int my_bd,
                         int setup)
{
    static unsigned int e;        /* table entry flag/number of extra bits */
    static unsigned int n, d;    /* length and index for copy */
    static unsigned int w;        /* current gunzip_window position */
    static huft_t *t;            /* pointer to table entry */
    static unsigned int ml, md;    /* masks for bl and bd bits */
    static unsigned int b;        /* bit buffer */
    static unsigned int k;        /* number of bits in bit buffer */
    static huft_t *tl, *td;
    static unsigned int bl, bd;

    if (setup)   /* 1st time we are called, copy in variables */
    {
        tl = my_tl;
        td = my_td;
        bl = my_bl;
        bd = my_bd;
        /* make local copies of globals */
        b = gunzip_bb;                /* initialize bit buffer */
        k = gunzip_bk;
        w = gunzip_outbuf_count;            /* initialize gunzip_window position
                                             */

        /* inflate the coded data */
        ml = mask_bits[bl];    /* precompute masks for speed */
        md = mask_bits[bd];
        return 0; /* Don't actually do anything the first time */
    }

    if (inflate_codes_resumeCopy) goto do_copy;

    while (1)              /* do until end of block */
    {
        b = fill_bitbuffer(b, &k, bl);
        if ((e = (t = tl + ((unsigned) b & ml))->e) > 16)
            do {
                if (e == 99)
                    error_die("inflate_codes error 1");

                b >>= t->b;
                k -= t->b;
                e -= 16;
                b = fill_bitbuffer(b, &k, e);
            } while ((e =
                          (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);

        b >>= t->b;
        k -= t->b;
        if (e == 16)      /* then it's a literal */
        {
            gunzip_window[w++] = (unsigned char) t->v.n;
            if (w == gunzip_wsize)
            {
                gunzip_outbuf_count = (w);
                w = 0;
                return 1; /* We have a block to read */
            }
        }
        else            /* it's an EOB or a length */
        {   /* exit if end of block */
            if (e == 15)
                break;

            /* get length of block to copy */
            b = fill_bitbuffer(b, &k, e);
            n = t->v.n + ((unsigned) b & mask_bits[e]);
            b >>= e;
            k -= e;

            /* decode distance of block to copy */
            b = fill_bitbuffer(b, &k, bd);
            if ((e = (t = td + ((unsigned) b & md))->e) > 16)
                do {
                    if (e == 99)
                        error_die("inflate_codes error 2");

                    b >>= t->b;
                    k -= t->b;
                    e -= 16;
                    b = fill_bitbuffer(b, &k, e);
                } while ((e =
                              (t =
                                   t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);

            b >>= t->b;
            k -= t->b;
            b = fill_bitbuffer(b, &k, e);
            d = w - t->v.n - ((unsigned) b & mask_bits[e]);
            b >>= e;
            k -= e;

            /* do the copy */
do_copy:        do {
                n -= (e =
                          (e =
                               gunzip_wsize - ((d &= gunzip_wsize - 1) > w ? d : w)) > n ? n : e);
                /* copy to new buffer to prevent possible overwrite */
                if (w - d >= e)      /* (this test assumes unsigned comparison)
                                      */
                {
                    memcpy(gunzip_window + w, gunzip_window + d, e);
                    w += e;
                    d += e;
                }
                else
                {
                    /* do it slow to avoid memcpy() overlap */
                    /* !NOMEMCPY */
                    do {
                        gunzip_window[w++] = gunzip_window[d++];
                    } while (--e);
                }

                if (w == gunzip_wsize)
                {
                    gunzip_outbuf_count = (w);
                    if (n) inflate_codes_resumeCopy = 1;
                    else inflate_codes_resumeCopy = 0;

                    w = 0;
                    return 1;
                }
            } while (n);
            inflate_codes_resumeCopy = 0;
        }
    }

    /* restore the globals from the locals */
    gunzip_outbuf_count = w;    /* restore global gunzip_window pointer */
    gunzip_bb = b;                /* restore global bit buffer */
    gunzip_bk = k;

    /* normally just after call to inflate_codes, but save code by putting it
       here */
    /* free the decoding tables, return */
    huft_free(tl,HUFT_MMP1);
    huft_free(td,HUFT_MMP2);

    /* done */
    return 0;
}