Skip to contentSkip to conversation

ppc32: Switch arch/ppc/boot to zlib_inflate

PATCH New Tom Rini 2 participants 6 messages Sep 1, 2004 – Sep 3, 2004

lore
Share & tools
lore

Tom Rini

author
#0 lore raw

PATCH 1/1 ppc32: Switch arch/ppc/boot to zlib_inflate

The following patch switches arch/ppc/boot over from using its own version of zlib to the code found under lib/zlib_inflate. The plus side to this, is one less version of zlib stuff around in the kernel. The downside is that the zlib code is ~8kB larger now, so I'm not sure if this is a good idea. This has been tested on both a Motorola LoPEC (which exercised the misc-common parts) and a pmac (which exercised the openfirmware/common.c parts).

Sam, any kbuild comments? I'm assuming that this is the best way to get these files built here.

arch/ppc/boot/lib/Makefile +14 -1
@@ -4,5 +4,18 @@
 
 CFLAGS_kbd.o	+= -Idrivers/char
 
-lib-y := zlib.o div64.o
+$(obj)/infblock.o: lib/zlib_inflate/infblock.c
+	$(call cmd,cc_o_c)
+$(obj)/infcodes.o: lib/zlib_inflate/infcodes.c
+	$(call cmd,cc_o_c)
+$(obj)/inffast.o: lib/zlib_inflate/inffast.c
+	$(call cmd,cc_o_c)
+$(obj)/inflate.o: lib/zlib_inflate/inflate.c
+	$(call cmd,cc_o_c)
+$(obj)/inftrees.o: lib/zlib_inflate/inftrees.c
+	$(call cmd,cc_o_c)
+$(obj)/infutil.o: lib/zlib_inflate/infutil.c
+	$(call cmd,cc_o_c)
+
+lib-y := infblock.o infcodes.o inffast.o inflate.o inftrees.o infutil.o div64.o
 lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o
arch/ppc/boot/lib/zlib.c deleted +0 -2169

2,169 lines not on this page · raw message

arch/ppc/boot/common/misc-common.c +9 -16
@@ -17,7 +17,7 @@
 #include <stdarg.h>	/* for va_ bits */
 #include <linux/config.h>
 #include <linux/string.h>
-#include "zlib.h"
+#include <linux/zlib.h>
 #include "nonstdio.h"
 
 /* If we're on a PReP, assume we have a keyboard controller
@@ -202,11 +202,10 @@ void error(char *x)
 	while(1);	/* Halt */
 }
 
-void *zalloc(void *x, unsigned items, unsigned size)
+static void *zalloc(unsigned size)
 {
 	void *p = avail_ram;
 
-	size *= items;
 	size = (size + 7) & -8;
 	avail_ram += size;
 	if (avail_ram > end_avail) {
@@ -216,18 +215,12 @@ void *zalloc(void *x, unsigned items, un
 	return p;
 }
 
-void zfree(void *x, void *addr, unsigned nb)
-{
-}
-
 #define HEAD_CRC	2
 #define EXTRA_FIELD	4
 #define ORIG_NAME	8
 #define COMMENT		0x10
 #define RESERVED	0xe0
 
-#define DEFLATED	8
-
 void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
 {
 	z_stream s;
@@ -236,7 +229,7 @@ void gunzip(void *dst, int dstlen, unsig
 	/* skip header */
 	i = 10;
 	flags = src[3];
-	if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+	if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
 		puts("bad gzipped data\n");
 		exit();
 	}
@@ -255,24 +248,24 @@ void gunzip(void *dst, int dstlen, unsig
 		exit();
 	}
 
-	s.zalloc = zalloc;
-	s.zfree = zfree;
-	r = inflateInit2(&s, -MAX_WBITS);
+	/* Initialize ourself. */
+	s.workspace = zalloc(zlib_inflate_workspacesize());
+	r = zlib_inflateInit2(&s, -MAX_WBITS);
 	if (r != Z_OK) {
-		puts("inflateInit2 returned "); puthex(r); puts("\n");
+		puts("zlib_inflateInit2 returned "); puthex(r); puts("\n");
 		exit();
 	}
 	s.next_in = src + i;
 	s.avail_in = *lenp - i;
 	s.next_out = dst;
 	s.avail_out = dstlen;
-	r = inflate(&s, Z_FINISH);
+	r = zlib_inflate(&s, Z_FINISH);
 	if (r != Z_OK && r != Z_STREAM_END) {
 		puts("inflate returned "); puthex(r); puts("\n");
 		exit();
 	}
 	*lenp = s.next_out - (unsigned char *) dst;
-	inflateEnd(&s);
+	zlib_inflateEnd(&s);
 }
 
 void
arch/ppc/boot/openfirmware/coffmain.c +0 -1
@@ -12,7 +12,6 @@
 
 #include "nonstdio.h"
 #include "of1275.h"
-#include "zlib.h"
 
 /* Passed from the linker */
 extern char __image_begin, __image_end;
arch/ppc/boot/simple/misc-embedded.c +0 -1
@@ -22,7 +22,6 @@
 #endif
 
 #include "nonstdio.h"
-#include "zlib.h"
 
 /* The linker tells us where the image is. */
 extern char __image_begin, __image_end;
arch/ppc/boot/openfirmware/common.c +43 -61

139 lines not on this page · raw message

arch/ppc/boot/simple/misc.c +1 -2
@@ -29,7 +29,6 @@
 #include <asm/reg.h>
 
 #include "nonstdio.h"
-#include "zlib.h"
 
 /* Default cmdline */
 #ifdef CONFIG_CMDLINE
@@ -220,7 +219,7 @@ decompress_kernel(unsigned long load_add
 	puts("\n");
 
 	puts("Uncompressing Linux...");
-	gunzip(NULL, 0x400000, zimage_start, &zimage_size);
+	gunzip(0x0, 0x400000, zimage_start, &zimage_size);
 	puts("done.\n");
 
 	/* get the bi_rec address */
arch/ppc/boot/include/zlib.h deleted +0 -430

430 lines not on this page · raw message

Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/
author
#1 lore raw

RFC PATCH 1/2 zlib_inflate: Move zlib_inflateSync & friends

Quoted 5 lines · Tom Rini

The following patch switches arch/ppc/boot over from using its own version of zlib to the code found under lib/zlib_inflate. The plus side to this, is one less version of zlib stuff around in the kernel. The downside is that the zlib code is ~8kB larger now, so I'm not sure if this is a good idea.

So, to try and get around this growth in size, I decided to see how bad things would look, and how much it would take, to get the size back down to what it was. After messing around, I've come up with two patches, which in the end shrink the overall size slightly. The first, and I hope least objectionable is to move zlib_inflateSync, and related bits used by PPP into inflate_sync.c. This saves us 169 bytes.

lib/zlib_inflate/inflate_sync.c new file +148 -0
Index: linux-2.6/lib/zlib_inflate/inflate_sync.c
===================================================================
@@ -0,0 +1,148 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include <linux/zutil.h>
+#include "infblock.h"
+#include "infutil.h"
+
+int zlib_inflateSync(
+	z_streamp z
+)
+{
+  uInt n;       /* number of bytes to look at */
+  Byte *p;      /* pointer to bytes */
+  uInt m;       /* number of marker bytes found in a row */
+  uLong r, w;   /* temporaries to save total_in and total_out */
+
+  /* set up */
+  if (z == NULL || z->state == NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->mode != I_BAD)
+  {
+    z->state->mode = I_BAD;
+    z->state->sub.marker = 0;
+  }
+  if ((n = z->avail_in) == 0)
+    return Z_BUF_ERROR;
+  p = z->next_in;
+  m = z->state->sub.marker;
+
+  /* search */
+  while (n && m < 4)
+  {
+    static const Byte mark[4] = {0, 0, 0xff, 0xff};
+    if (*p == mark[m])
+      m++;
+    else if (*p)
+      m = 0;
+    else
+      m = 4 - m;
+    p++, n--;
+  }
+
+  /* restore */
+  z->total_in += p - z->next_in;
+  z->next_in = p;
+  z->avail_in = n;
+  z->state->sub.marker = m;
+
+  /* return no joy or set up to restart on a new block */
+  if (m != 4)
+    return Z_DATA_ERROR;
+  r = z->total_in;  w = z->total_out;
+  zlib_inflateReset(z);
+  z->total_in = r;  z->total_out = w;
+  z->state->mode = BLOCKS;
+  return Z_OK;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
+ * but removes the length bytes of the resulting empty stored block. When
+ * decompressing, PPP checks that at the end of input packet, inflate is
+ * waiting for these length bytes.
+ */
+int zlib_inflateSyncPoint(
+	z_streamp z
+)
+{
+  if (z == NULL || z->state == NULL || z->state->blocks == NULL)
+    return Z_STREAM_ERROR;
+  return zlib_inflate_blocks_sync_point(z->state->blocks);
+}
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output.  The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS).  On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+static int zlib_inflate_addhistory(inflate_blocks_statef *s,
+				      z_stream              *z)
+{
+    uLong b;              /* bit buffer */  /* NOT USED HERE */
+    uInt k;               /* bits in bit buffer */ /* NOT USED HERE */
+    uInt t;               /* temporary storage */
+    Byte *p;              /* input data pointer */
+    uInt n;               /* bytes available there */
+    Byte *q;              /* output window write pointer */
+    uInt m;               /* bytes to end of window or read pointer */
+
+    if (s->read != s->write)
+	return Z_STREAM_ERROR;
+    if (s->mode != TYPE)
+	return Z_DATA_ERROR;
+
+    /* we're ready to rock */
+    LOAD
+    /* while there is input ready, copy to output buffer, moving
+     * pointers as needed.
+     */
+    while (n) {
+	t = n;  /* how many to do */
+	/* is there room until end of buffer? */
+	if (t > m) t = m;
+	/* update check information */
+	if (s->checkfn != NULL)
+	    s->check = (*s->checkfn)(s->check, q, t);
+	memcpy(q, p, t);
+	q += t;
+	p += t;
+	n -= t;
+	z->total_out += t;
+	s->read = q;    /* drag read pointer forward */
+/*      WWRAP  */ 	/* expand WWRAP macro by hand to handle s->read */
+	if (q == s->end) {
+	    s->read = q = s->window;
+	    m = WAVAIL;
+	}
+    }
+    UPDATE
+    return Z_OK;
+}
+
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output.  The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS).  On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+
+int zlib_inflateIncomp(
+	z_stream *z
+	
+)
+{
+    if (z->state->mode != BLOCKS)
+	return Z_DATA_ERROR;
+    return zlib_inflate_addhistory(z->state->blocks, z);
+}
lib/zlib_inflate/Makefile +1 -1
Index: linux-2.6/lib/zlib_inflate/Makefile
===================================================================
@@ -16,4 +16,4 @@
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o
 
 zlib_inflate-objs := infblock.o infcodes.o inffast.o inflate.o \
-		     inftrees.o infutil.o inflate_syms.o
+		     inflate_sync.o inftrees.o infutil.o inflate_syms.o
lib/zlib_inflate/inflate.c +0 -141

144 lines not on this page · raw message

Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/
author
#2 lore raw

RFC PATCH 2/2 zlib_inflate: Add __BOOTER__ around zlib_inflate_trees_fixed(...)

Quoted 8 lines · Tom Rini
Quoted 5 lines · Tom Rini

The following patch switches arch/ppc/boot over from using its own version of zlib to the code found under lib/zlib_inflate. The plus side to this, is one less version of zlib stuff around in the kernel. The downside is that the zlib code is ~8kB larger now, so I'm not sure if this is a good idea.

Quoted 6 lines

So, to try and get around this growth in size, I decided to see how bad things would look, and how much it would take, to get the size back down to what it was. After messing around, I've come up with two patches, which in the end shrink the overall size slightly. The first, and I hope least objectionable is to move zlib_inflateSync, and related bits used by PPP into inflate_sync.c. This saves us 169 bytes.

This is the second part of what I found. zlib_inflate_trees_fixed(...) isn't called in decompressing a kernel. Dropping this, and the call to it saves ~8kB. __BOOTER__ is a flag already passed along during the build of arch/ppc/boot/. But, I'm going to guess doing it this way is just too ugly. zlib_inflate_trees_fixed(...) itself could be moved into another file, but that leaves the problem of having to provide some sort of stub function, and perhaps making zlib_inflate_trees_fixed return Z_OK (real version) or Z_STREAM_ERROR (stub).

Or if anyone else has a better idea, I'd be glad to give that a shot. Thanks.

lib/zlib_inflate/infblock.c +2 -0
Index: linux-2.6/lib/zlib_inflate/infblock.c
===================================================================
@@ -134,6 +134,7 @@ int zlib_inflate_blocks(
           DUMPBITS(t)
           s->mode = LENS;               /* get length of stored block */
           break;
+#ifndef __BOOTER__
         case 1:                         /* fixed */
           {
             uInt bl, bd;
@@ -150,6 +151,7 @@ int zlib_inflate_blocks(
           DUMPBITS(3)
           s->mode = CODES;
           break;
+#endif
         case 2:                         /* dynamic */
           DUMPBITS(3)
           s->mode = TABLE;
lib/zlib_inflate/inftrees.c +2 -0
Index: linux-2.6/lib/zlib_inflate/inftrees.c
===================================================================
@@ -374,6 +374,7 @@ int zlib_inflate_trees_dynamic(
 }
 
 
+#ifndef __BOOTER__
 /* build fixed tables only once--keep them here */
 #include "inffixed.h"
 
@@ -392,3 +393,4 @@ int zlib_inflate_trees_fixed(
   *td = fixed_td;
   return Z_OK;
 }
+#endif
Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/
#3 lore raw

Re: [PATCH,RFC 2.6.9-rc1 2/2] zlib_inflate: Add __BOOTER__ around zlib_inflate_trees_fixed(...)

Quoted 2 lines · Tom Rini

This is the second part of what I found. zlib_inflate_trees_fixed(...) isn't called in decompressing a kernel. Dropping this, and the call to

I think it is just luck that gzip hasn't used the fixed table in compressing the kernel. I don't think we have any guarantee that gzip won't use the fixed table.

Just out of interest, how big is a bzip2 decompressor?

Regards,
Paul.

author
#4 lore raw

Re: [PATCH,RFC 2.6.9-rc1 2/2] zlib_inflate: Add __BOOTER__ around zlib_inflate_trees_fixed(...)

Quoted 8 lines · Paul Mackerras
Quoted 2 lines · Tom Rini

This is the second part of what I found. zlib_inflate_trees_fixed(...) isn't called in decompressing a kernel. Dropping this, and the call to

I think it is just luck that gzip hasn't used the fixed table in compressing the kernel. I don't think we have any guarantee that gzip won't use the fixed table.

That is a good point. Looking at arch/ppc/boot/lib/zlib.c it generates the table, instead of having a static one. So perhaps we should move to that instead for lib/zlib_inflate ?

Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/
author
#5 lore raw

Re: [PATCH,RFC 2.6.9-rc1 2/2] zlib_inflate: Add __BOOTER__ around zlib_inflate_trees_fixed(...)

Quoted 7 lines · Tom Rini
Quoted 5 lines · Paul Mackerras
Quoted 2 lines · Tom Rini

This is the second part of what I found. zlib_inflate_trees_fixed(...) isn't called in decompressing a kernel. Dropping this, and the call to

Quoted 7 lines
Quoted 3 lines

I think it is just luck that gzip hasn't used the fixed table in compressing the kernel. I don't think we have any guarantee that gzip won't use the fixed table.

That is a good point. Looking at arch/ppc/boot/lib/zlib.c it generates the table, instead of having a static one. So perhaps we should move to that instead for lib/zlib_inflate ?

I've moved lib/zlib_inflate over to generating the table. But, in trying to test it, I haven't been able to find anything that will actually use this (it appears that using this static table was something that pkzip introduced long ago as an alternative method of good compression / speed) so I can't actually test it. But the image size is back in line.

Signature · 2 lines
Tom Rini
http://gate.crashing.org/~trini/