summaryrefslogtreecommitdiff
path: root/packages/linux/linux-mtx-1-2.4.27/06-zboot-2.4.26.patch
diff options
context:
space:
mode:
authorKoen Kooi <koen@openembedded.org>2005-06-30 08:19:37 +0000
committerOpenEmbedded Project <openembedded-devel@lists.openembedded.org>2005-06-30 08:19:37 +0000
commitc8e5702127e507e82e6f68a4b8c546803accea9d (patch)
tree00583491f40ecc640f2b28452af995e3a63a09d7 /packages/linux/linux-mtx-1-2.4.27/06-zboot-2.4.26.patch
parent87ec8ca4d2e2eb4d1c1e1e1a6b46a395d56805b9 (diff)
import clean BK tree at cset 1.3670
Diffstat (limited to 'packages/linux/linux-mtx-1-2.4.27/06-zboot-2.4.26.patch')
-rw-r--r--packages/linux/linux-mtx-1-2.4.27/06-zboot-2.4.26.patch5308
1 files changed, 5308 insertions, 0 deletions
diff --git a/packages/linux/linux-mtx-1-2.4.27/06-zboot-2.4.26.patch b/packages/linux/linux-mtx-1-2.4.27/06-zboot-2.4.26.patch
index e69de29bb2..4e8a7576bd 100644
--- a/packages/linux/linux-mtx-1-2.4.27/06-zboot-2.4.26.patch
+++ b/packages/linux/linux-mtx-1-2.4.27/06-zboot-2.4.26.patch
@@ -0,0 +1,5308 @@
+diff -Naru linux/arch/mips/Makefile linux.spi/arch/mips/Makefile
+--- linux/arch/mips/Makefile 2004-05-06 15:23:41.000000000 -0400
++++ linux.spi/arch/mips/Makefile 2004-05-11 23:19:24.000000000 -0400
+@@ -29,6 +29,8 @@
+ endif
+
+ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
++MAKEZBOOT = $(MAKE) -C arch/$(ARCH)/zboot
++BOOT_TARGETS = zImage zImage.initrd zImage.flash
+
+ check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
+
+@@ -757,12 +749,16 @@
+
+ vmlinux.ecoff: vmlinux
+ @$(MAKEBOOT) $@
++
++$(BOOT_TARGETS): vmlinux
++ @$(MAKEZBOOT) $@
+
+ vmlinux.srec: vmlinux
+ @$(MAKEBOOT) $@
+
+ archclean:
+ @$(MAKEBOOT) clean
++ @$(MAKEZBOOT) clean
+ rm -f arch/$(ARCH)/ld.script
+ $(MAKE) -C arch/$(ARCH)/tools clean
+ $(MAKE) -C arch/mips/baget clean
+diff -Naru linux/arch/mips/zboot/common/au1k_uart.c linux.spi/arch/mips/zboot/common/au1k_uart.c
+--- linux/arch/mips/zboot/common/au1k_uart.c 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/common/au1k_uart.c 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,103 @@
++/*
++ * BRIEF MODULE DESCRIPTION
++ * Simple Au1000 uart routines.
++ *
++ * Copyright 2001 MontaVista Software Inc.
++ * Author: MontaVista Software, Inc.
++ * ppopov@mvista.com or source@mvista.com
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#include <linux/config.h>
++#include <asm/io.h>
++#include <asm/au1000.h>
++#include "ns16550.h"
++
++typedef unsigned char uint8;
++typedef unsigned int uint32;
++
++#define UART16550_BAUD_2400 2400
++#define UART16550_BAUD_4800 4800
++#define UART16550_BAUD_9600 9600
++#define UART16550_BAUD_19200 19200
++#define UART16550_BAUD_38400 38400
++#define UART16550_BAUD_57600 57600
++#define UART16550_BAUD_115200 115200
++
++#define UART16550_PARITY_NONE 0
++#define UART16550_PARITY_ODD 0x08
++#define UART16550_PARITY_EVEN 0x18
++#define UART16550_PARITY_MARK 0x28
++#define UART16550_PARITY_SPACE 0x38
++
++#define UART16550_DATA_5BIT 0x0
++#define UART16550_DATA_6BIT 0x1
++#define UART16550_DATA_7BIT 0x2
++#define UART16550_DATA_8BIT 0x3
++
++#define UART16550_STOP_1BIT 0x0
++#define UART16550_STOP_2BIT 0x4
++
++/* It would be nice if we had a better way to do this.
++ * It could be a variable defined in one of the board specific files.
++ */
++#undef UART_BASE
++#ifdef CONFIG_COGENT_CSB250
++#define UART_BASE UART3_ADDR
++#else
++#define UART_BASE UART0_ADDR
++#endif
++
++/* memory-mapped read/write of the port */
++#define UART16550_READ(y) (readl(UART_BASE + y) & 0xff)
++#define UART16550_WRITE(y,z) (writel(z&0xff, UART_BASE + y))
++
++/*
++ * We use uart 0, which is already initialized by
++ * yamon.
++ */
++volatile struct NS16550 *
++serial_init(int chan)
++{
++ volatile struct NS16550 *com_port;
++ com_port = (struct NS16550 *) UART_BASE;
++ return (com_port);
++}
++
++void
++serial_putc(volatile struct NS16550 *com_port, unsigned char c)
++{
++ while ((UART16550_READ(UART_LSR)&0x40) == 0);
++ UART16550_WRITE(UART_TX, c);
++}
++
++unsigned char
++serial_getc(volatile struct NS16550 *com_port)
++{
++ while((UART16550_READ(UART_LSR) & 0x1) == 0);
++ return UART16550_READ(UART_RX);
++}
++
++int
++serial_tstc(volatile struct NS16550 *com_port)
++{
++ return((UART16550_READ(UART_LSR) & LSR_DR) != 0);
++}
+diff -Naru linux/arch/mips/zboot/common/ctype.c linux.spi/arch/mips/zboot/common/ctype.c
+--- linux/arch/mips/zboot/common/ctype.c 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/common/ctype.c 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,35 @@
++/*
++ * linux/lib/ctype.c
++ *
++ * Copyright (C) 1991, 1992 Linus Torvalds
++ */
++
++#include <linux/ctype.h>
++
++unsigned char _ctype[] = {
++_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
++_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
++_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
++_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
++_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
++_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
++_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
++_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
++_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
++_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
++_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
++_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
++_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
++_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
++_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
++_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
++0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
++0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
++_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
++_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
++_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
++_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
++_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
++_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
++
++
+diff -Naru linux/arch/mips/zboot/common/dummy.c linux.spi/arch/mips/zboot/common/dummy.c
+--- linux/arch/mips/zboot/common/dummy.c 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/common/dummy.c 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,4 @@
++int main(void)
++{
++ return 0;
++}
+diff -Naru linux/arch/mips/zboot/common/Makefile linux.spi/arch/mips/zboot/common/Makefile
+--- linux/arch/mips/zboot/common/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/common/Makefile 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,27 @@
++#
++# arch/mips/zboot/common/Makefile
++#
++# This file is subject to the terms and conditions of the GNU General Public
++# License. See the file "COPYING" in the main directory of this archive
++# for more details.
++#
++# Tom Rini January 2001
++#
++
++.c.s:
++ $(CC) $(CFLAGS) -S -o $*.s $<
++.s.o:
++ $(AS) -o $*.o $<
++.c.o:
++ $(CC) $(CFLAGS) -c -o $*.o $<
++.S.s:
++ $(CPP) $(AFLAGS) -o $*.o $<
++.S.o:
++ $(CC) $(AFLAGS) -c -o $*.o $<
++
++clean:
++ rm -rf *.o
++
++OBJCOPY_ARGS = -O elf32-tradlittlemips
++
++include $(TOPDIR)/Rules.make
+diff -Naru linux/arch/mips/zboot/common/misc-common.c linux.spi/arch/mips/zboot/common/misc-common.c
+--- linux/arch/mips/zboot/common/misc-common.c 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/common/misc-common.c 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,437 @@
++/*
++ * arch/mips/zboot/common/misc-common.c
++ *
++ * Misc. bootloader code (almost) all platforms can use
++ *
++ * Author: Johnnie Peters <jpeters@mvista.com>
++ * Editor: Tom Rini <trini@mvista.com>
++ *
++ * Derived from arch/ppc/boot/prep/misc.c
++ *
++ * Ported by Pete Popov <ppopov@mvista.com> to
++ * support mips board(s). I also got rid of the vga console
++ * code.
++ *
++ * Copyright 2000-2001 MontaVista Software Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/config.h>
++#include "zlib.h"
++#include <stdarg.h>
++
++extern char *avail_ram;
++extern char *end_avail;
++extern char _end[];
++
++void puts(const char *);
++void putc(const char c);
++void puthex(unsigned long val);
++void _bcopy(char *src, char *dst, int len);
++void gunzip(void *, int, unsigned char *, int *);
++static int _cvt(unsigned long val, char *buf, long radix, char *digits);
++
++void _vprintk(void(*)(const char), const char *, va_list ap);
++
++struct NS16550 *com_port;
++
++int serial_tstc(volatile struct NS16550 *);
++unsigned char serial_getc(volatile struct NS16550 *);
++void serial_putc(volatile struct NS16550 *, unsigned char);
++
++void pause(void)
++{
++ puts("pause\n");
++}
++
++void exit(void)
++{
++ puts("exit\n");
++ while(1);
++}
++
++int tstc(void)
++{
++ return (serial_tstc(com_port));
++}
++
++int getc(void)
++{
++ while (1) {
++ if (serial_tstc(com_port))
++ return (serial_getc(com_port));
++ }
++}
++
++void
++putc(const char c)
++{
++ int x,y;
++
++ serial_putc(com_port, c);
++ if ( c == '\n' )
++ serial_putc(com_port, '\r');
++}
++
++void puts(const char *s)
++{
++ char c;
++ while ( ( c = *s++ ) != '\0' ) {
++ serial_putc(com_port, c);
++ if ( c == '\n' ) serial_putc(com_port, '\r');
++ }
++}
++
++void error(char *x)
++{
++ puts("\n\n");
++ puts(x);
++ puts("\n\n -- System halted");
++
++ while(1); /* Halt */
++}
++
++void *zalloc(void *x, unsigned items, unsigned size)
++{
++ void *p = avail_ram;
++
++ size *= items;
++ size = (size + 7) & -8;
++ avail_ram += size;
++ if (avail_ram > end_avail) {
++ puts("oops... out of memory\n");
++ pause();
++ }
++ 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;
++ int r, i, flags;
++
++ /* skip header */
++ i = 10;
++ flags = src[3];
++ if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
++ puts("bad gzipped data\n");
++ exit();
++ }
++ if ((flags & EXTRA_FIELD) != 0)
++ i = 12 + src[10] + (src[11] << 8);
++ if ((flags & ORIG_NAME) != 0)
++ while (src[i++] != 0)
++ ;
++ if ((flags & COMMENT) != 0)
++ while (src[i++] != 0)
++ ;
++ if ((flags & HEAD_CRC) != 0)
++ i += 2;
++ if (i >= *lenp) {
++ puts("gunzip: ran out of data in header\n");
++ exit();
++ }
++
++ s.zalloc = zalloc;
++ s.zfree = zfree;
++ r = inflateInit2(&s, -MAX_WBITS);
++ if (r != Z_OK) {
++ puts("inflateInit2 returned %d\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);
++ if (r != Z_OK && r != Z_STREAM_END) {
++ puts("inflate returned %d\n");
++ exit();
++ }
++ *lenp = s.next_out - (unsigned char *) dst;
++ inflateEnd(&s);
++}
++
++void
++puthex(unsigned long val)
++{
++
++ unsigned char buf[10];
++ int i;
++ for (i = 7; i >= 0; i--)
++ {
++ buf[i] = "0123456789ABCDEF"[val & 0x0F];
++ val >>= 4;
++ }
++ buf[8] = '\0';
++ puts(buf);
++}
++
++#define FALSE 0
++#define TRUE 1
++
++void
++_printk(char const *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ _vprintk(putc, fmt, ap);
++ va_end(ap);
++ return;
++}
++
++#define is_digit(c) ((c >= '0') && (c <= '9'))
++
++void
++_vprintk(void(*putc)(const char), const char *fmt0, va_list ap)
++{
++ char c, sign, *cp = 0;
++ int left_prec, right_prec, zero_fill, length = 0, pad, pad_on_right;
++ char buf[32];
++ long val;
++ while ((c = *fmt0++))
++ {
++ if (c == '%')
++ {
++ c = *fmt0++;
++ left_prec = right_prec = pad_on_right = 0;
++ if (c == '-')
++ {
++ c = *fmt0++;
++ pad_on_right++;
++ }
++ if (c == '0')
++ {
++ zero_fill = TRUE;
++ c = *fmt0++;
++ } else
++ {
++ zero_fill = FALSE;
++ }
++ while (is_digit(c))
++ {
++ left_prec = (left_prec * 10) + (c - '0');
++ c = *fmt0++;
++ }
++ if (c == '.')
++ {
++ c = *fmt0++;
++ zero_fill++;
++ while (is_digit(c))
++ {
++ right_prec = (right_prec * 10) + (c - '0');
++ c = *fmt0++;
++ }
++ } else
++ {
++ right_prec = left_prec;
++ }
++ sign = '\0';
++ switch (c)
++ {
++ case 'd':
++ case 'x':
++ case 'X':
++ val = va_arg(ap, long);
++ switch (c)
++ {
++ case 'd':
++ if (val < 0)
++ {
++ sign = '-';
++ val = -val;
++ }
++ length = _cvt(val, buf, 10, "0123456789");
++ break;
++ case 'x':
++ length = _cvt(val, buf, 16, "0123456789abcdef");
++ break;
++ case 'X':
++ length = _cvt(val, buf, 16, "0123456789ABCDEF");
++ break;
++ }
++ cp = buf;
++ break;
++ case 's':
++ cp = va_arg(ap, char *);
++ length = strlen(cp);
++ break;
++ case 'c':
++ c = va_arg(ap, long /*char*/);
++ (*putc)(c);
++ continue;
++ default:
++ (*putc)('?');
++ }
++ pad = left_prec - length;
++ if (sign != '\0')
++ {
++ pad--;
++ }
++ if (zero_fill)
++ {
++ c = '0';
++ if (sign != '\0')
++ {
++ (*putc)(sign);
++ sign = '\0';
++ }
++ } else
++ {
++ c = ' ';
++ }
++ if (!pad_on_right)
++ {
++ while (pad-- > 0)
++ {
++ (*putc)(c);
++ }
++ }
++ if (sign != '\0')
++ {
++ (*putc)(sign);
++ }
++ while (length-- > 0)
++ {
++ (*putc)(c = *cp++);
++ if (c == '\n')
++ {
++ (*putc)('\r');
++ }
++ }
++ if (pad_on_right)
++ {
++ while (pad-- > 0)
++ {
++ (*putc)(c);
++ }
++ }
++ } else
++ {
++ (*putc)(c);
++ if (c == '\n')
++ {
++ (*putc)('\r');
++ }
++ }
++ }
++}
++
++int
++_cvt(unsigned long val, char *buf, long radix, char *digits)
++{
++ char temp[80];
++ char *cp = temp;
++ int length = 0;
++ if (val == 0)
++ { /* Special case */
++ *cp++ = '0';
++ } else
++ while (val)
++ {
++ *cp++ = digits[val % radix];
++ val /= radix;
++ }
++ while (cp != temp)
++ {
++ *buf++ = *--cp;
++ length++;
++ }
++ *buf = '\0';
++ return (length);
++}
++
++void
++_dump_buf_with_offset(unsigned char *p, int s, unsigned char *base)
++{
++ int i, c;
++ if ((unsigned int)s > (unsigned int)p)
++ {
++ s = (unsigned int)s - (unsigned int)p;
++ }
++ while (s > 0)
++ {
++ if (base)
++ {
++ _printk("%06X: ", (int)p - (int)base);
++ } else
++ {
++ _printk("%06X: ", p);
++ }
++ for (i = 0; i < 16; i++)
++ {
++ if (i < s)
++ {
++ _printk("%02X", p[i] & 0xFF);
++ } else
++ {
++ _printk(" ");
++ }
++ if ((i % 2) == 1) _printk(" ");
++ if ((i % 8) == 7) _printk(" ");
++ }
++ _printk(" |");
++ for (i = 0; i < 16; i++)
++ {
++ if (i < s)
++ {
++ c = p[i] & 0xFF;
++ if ((c < 0x20) || (c >= 0x7F)) c = '.';
++ } else
++ {
++ c = ' ';
++ }
++ _printk("%c", c);
++ }
++ _printk("|\n");
++ s -= 16;
++ p += 16;
++ }
++}
++
++void
++_dump_buf(unsigned char *p, int s)
++{
++ _printk("\n");
++ _dump_buf_with_offset(p, s, 0);
++}
++
++/*
++ * Local variables:
++ * c-indent-level: 8
++ * c-basic-offset: 8
++ * tab-width: 8
++ * End:
++ */
+diff -Naru linux/arch/mips/zboot/common/misc-simple.c linux.spi/arch/mips/zboot/common/misc-simple.c
+--- linux/arch/mips/zboot/common/misc-simple.c 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/common/misc-simple.c 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,127 @@
++/*
++ * arch/mips/zboot/common/misc-simple.c
++ *
++ * Misc. bootloader code for many machines. This assumes you have are using
++ * a 6xx/7xx/74xx CPU in your machine. This assumes the chunk of memory
++ * below 8MB is free. Finally, it assumes you have a NS16550-style uart for
++ * your serial console. If a machine meets these requirements, it can quite
++ * likely use this code during boot.
++ *
++ * Author: Matt Porter <mporter@mvista.com>
++ * Derived from arch/ppc/boot/prep/misc.c
++ *
++ * Copyright 2001 MontaVista Software Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/types.h>
++#include <linux/elf.h>
++#include <linux/config.h>
++
++#include <asm/page.h>
++#include <asm/processor.h>
++#include <asm/mmu.h>
++
++#include "zlib.h"
++
++extern struct NS16550 *com_port;
++
++char *avail_ram;
++char *end_avail;
++extern char _end[];
++char *zimage_start;
++
++#ifdef CONFIG_CMDLINE
++#define CMDLINE CONFIG_CMDLINE
++#else
++#define CMDLINE ""
++#endif
++char cmd_preset[] = CMDLINE;
++char cmd_buf[256];
++char *cmd_line = cmd_buf;
++
++/* The linker tells us where the image is.
++*/
++extern unsigned char __image_begin, __image_end;
++extern unsigned char __ramdisk_begin, __ramdisk_end;
++unsigned long initrd_size;
++
++extern void puts(const char *);
++extern void putc(const char c);
++extern void puthex(unsigned long val);
++extern void *memcpy(void * __dest, __const void * __src,
++ __kernel_size_t __n);
++extern void gunzip(void *, int, unsigned char *, int *);
++extern void udelay(long delay);
++extern int tstc(void);
++extern int getc(void);
++extern volatile struct NS16550 *serial_init(int chan);
++
++void
++decompress_kernel(unsigned long load_addr, int num_words,
++ unsigned long cksum, unsigned long *sp)
++{
++ int timer = 0;
++ extern unsigned long start;
++ char *cp, ch;
++ int i;
++ int zimage_size;
++
++ com_port = (struct NS16550 *)serial_init(0);
++
++ initrd_size = (unsigned long)(&__ramdisk_end) -
++ (unsigned long)(&__ramdisk_begin);
++
++ /*
++ * Reveal where we were loaded at and where we
++ * were relocated to.
++ */
++ puts("loaded at: "); puthex(load_addr);
++ puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
++ if ( (unsigned long)load_addr != (unsigned long)&start )
++ {
++ puts("relocated to: "); puthex((unsigned long)&start);
++ puts(" ");
++ puthex((unsigned long)((unsigned long)&start + (4*num_words)));
++ puts("\n");
++ }
++
++ /*
++ * We link ourself to an arbitrary low address. When we run, we
++ * relocate outself to that address. __image_being points to
++ * the part of the image where the zImage is. -- Tom
++ */
++ zimage_start = (char *)(unsigned long)(&__image_begin);
++ zimage_size = (unsigned long)(&__image_end) -
++ (unsigned long)(&__image_begin);
++
++ /*
++ * The zImage and initrd will be between start and _end, so they've
++ * already been moved once. We're good to go now. -- Tom
++ */
++ puts("zimage at: "); puthex((unsigned long)zimage_start);
++ puts(" "); puthex((unsigned long)(zimage_size+zimage_start));
++ puts("\n");
++
++ if ( initrd_size ) {
++ puts("initrd at: ");
++ puthex((unsigned long)(&__ramdisk_begin));
++ puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n");
++ }
++
++ /* assume the chunk below 8M is free */
++ avail_ram = (char *)AVAIL_RAM_START;
++ end_avail = (char *)AVAIL_RAM_END;
++
++ /* Display standard Linux/MIPS boot prompt for kernel args */
++ puts("Uncompressing Linux at load address ");
++ puthex(LOADADDR);
++ puts("\n");
++ /* I don't like this hard coded gunzip size (fixme) */
++ gunzip((void *)LOADADDR, 0x400000, zimage_start, &zimage_size);
++ puts("Now booting the kernel\n");
++}
+diff -Naru linux/arch/mips/zboot/common/no_initrd.c linux.spi/arch/mips/zboot/common/no_initrd.c
+--- linux/arch/mips/zboot/common/no_initrd.c 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/common/no_initrd.c 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,2 @@
++char initrd_data[1];
++int initrd_len = 0;
+diff -Naru linux/arch/mips/zboot/common/ns16550.c linux.spi/arch/mips/zboot/common/ns16550.c
+--- linux/arch/mips/zboot/common/ns16550.c 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/common/ns16550.c 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,57 @@
++/*
++ * NS16550 support
++ */
++
++#include <linux/config.h>
++#include <asm/serial.h>
++#include "ns16550.h"
++
++typedef struct NS16550 *NS16550_t;
++
++const NS16550_t COM_PORTS[] = { (NS16550_t) COM1,
++ (NS16550_t) COM2,
++ (NS16550_t) COM3,
++ (NS16550_t) COM4 };
++
++volatile struct NS16550 *
++serial_init(int chan)
++{
++ volatile struct NS16550 *com_port;
++ com_port = (struct NS16550 *) COM_PORTS[chan];
++ /* See if port is present */
++ com_port->lcr = 0x00;
++ com_port->ier = 0xFF;
++#if 0
++ if (com_port->ier != 0x0F) return ((struct NS16550 *)0);
++#endif
++ com_port->ier = 0x00;
++ com_port->lcr = 0x80; /* Access baud rate */
++#ifdef CONFIG_SERIAL_CONSOLE_NONSTD
++ com_port->dll = (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD);
++ com_port->dlm = (BASE_BAUD / CONFIG_SERIAL_CONSOLE_BAUD) >> 8;
++#endif
++ com_port->lcr = 0x03; /* 8 data, 1 stop, no parity */
++ com_port->mcr = 0x03; /* RTS/DTR */
++ com_port->fcr = 0x07; /* Clear & enable FIFOs */
++ return (com_port);
++}
++
++void
++serial_putc(volatile struct NS16550 *com_port, unsigned char c)
++{
++ while ((com_port->lsr & LSR_THRE) == 0) ;
++ com_port->thr = c;
++}
++
++unsigned char
++serial_getc(volatile struct NS16550 *com_port)
++{
++ while ((com_port->lsr & LSR_DR) == 0) ;
++ return (com_port->rbr);
++}
++
++int
++serial_tstc(volatile struct NS16550 *com_port)
++{
++ return ((com_port->lsr & LSR_DR) != 0);
++}
+diff -Naru linux/arch/mips/zboot/common/string.c linux.spi/arch/mips/zboot/common/string.c
+--- linux/arch/mips/zboot/common/string.c 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/common/string.c 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,497 @@
++/*
++ * linux/lib/string.c
++ *
++ * Copyright (C) 1991, 1992 Linus Torvalds
++ */
++
++/*
++ * stupid library routines.. The optimized versions should generally be found
++ * as inline code in <asm-xx/string.h>
++ *
++ * These are buggy as well..
++ *
++ * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
++ * - Added strsep() which will replace strtok() soon (because strsep() is
++ * reentrant and should be faster). Use only strsep() in new code, please.
++ */
++
++#include <linux/types.h>
++#include <linux/string.h>
++#include <linux/ctype.h>
++
++/**
++ * strnicmp - Case insensitive, length-limited string comparison
++ * @s1: One string
++ * @s2: The other string
++ * @len: the maximum number of characters to compare
++ */
++int strnicmp(const char *s1, const char *s2, size_t len)
++{
++ /* Yes, Virginia, it had better be unsigned */
++ unsigned char c1, c2;
++
++ c1 = 0; c2 = 0;
++ if (len) {
++ do {
++ c1 = *s1; c2 = *s2;
++ s1++; s2++;
++ if (!c1)
++ break;
++ if (!c2)
++ break;
++ if (c1 == c2)
++ continue;
++ c1 = tolower(c1);
++ c2 = tolower(c2);
++ if (c1 != c2)
++ break;
++ } while (--len);
++ }
++ return (int)c1 - (int)c2;
++}
++
++char * ___strtok;
++
++#ifndef __HAVE_ARCH_STRCPY
++/**
++ * strcpy - Copy a %NUL terminated string
++ * @dest: Where to copy the string to
++ * @src: Where to copy the string from
++ */
++char * strcpy(char * dest,const char *src)
++{
++ char *tmp = dest;
++
++ while ((*dest++ = *src++) != '\0')
++ /* nothing */;
++ return tmp;
++}
++#endif
++
++#ifndef __HAVE_ARCH_STRNCPY
++/**
++ * strncpy - Copy a length-limited, %NUL-terminated string
++ * @dest: Where to copy the string to
++ * @src: Where to copy the string from
++ * @count: The maximum number of bytes to copy
++ *
++ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer.
++ * However, the result is not %NUL-terminated if the source exceeds
++ * @count bytes.
++ */
++char * strncpy(char * dest,const char *src,size_t count)
++{
++ char *tmp = dest;
++
++ while (count-- && (*dest++ = *src++) != '\0')
++ /* nothing */;
++
++ return tmp;
++}
++#endif
++
++/**
++ * strcat - Append one %NUL-terminated string to another
++ * @dest: The string to be appended to
++ * @src: The string to append to it
++ */
++char * strcat(char * dest, const char * src)
++{
++ char *tmp = dest;
++
++ while (*dest)
++ dest++;
++ while ((*dest++ = *src++) != '\0')
++ ;
++
++ return tmp;
++}
++
++/**
++ * strncat - Append a length-limited, %NUL-terminated string to another
++ * @dest: The string to be appended to
++ * @src: The string to append to it
++ * @count: The maximum numbers of bytes to copy
++ *
++ * Note that in contrast to strncpy, strncat ensures the result is
++ * terminated.
++ */
++char * strncat(char *dest, const char *src, size_t count)
++{
++ char *tmp = dest;
++
++ if (count) {
++ while (*dest)
++ dest++;
++ while ((*dest++ = *src++)) {
++ if (--count == 0) {
++ *dest = '\0';
++ break;
++ }
++ }
++ }
++
++ return tmp;
++}
++
++#ifndef __HAVE_ARCH_STRCMP
++/**
++ * strcmp - Compare two strings
++ * @cs: One string
++ * @ct: Another string
++ */
++int strcmp(const char * cs,const char * ct)
++{
++ register signed char __res;
++
++ while (1) {
++ if ((__res = *cs - *ct++) != 0 || !*cs++)
++ break;
++ }
++
++ return __res;
++}
++#endif
++
++#ifndef __HAVE_ARCH_STRNCMP
++/**
++ * strncmp - Compare two length-limited strings
++ * @cs: One string
++ * @ct: Another string
++ * @count: The maximum number of bytes to compare
++ */
++int strncmp(const char * cs,const char * ct,size_t count)
++{
++ register signed char __res = 0;
++
++ while (count) {
++ if ((__res = *cs - *ct++) != 0 || !*cs++)
++ break;
++ count--;
++ }
++
++ return __res;
++}
++#endif
++
++/**
++ * strchr - Find the first occurrence of a character in a string
++ * @s: The string to be searched
++ * @c: The character to search for
++ */
++char * strchr(const char * s, int c)
++{
++ for(; *s != (char) c; ++s)
++ if (*s == '\0')
++ return NULL;
++ return (char *) s;
++}
++
++/**
++ * strrchr - Find the last occurrence of a character in a string
++ * @s: The string to be searched
++ * @c: The character to search for
++ */
++char * strrchr(const char * s, int c)
++{
++ const char *p = s + strlen(s);
++ do {
++ if (*p == (char)c)
++ return (char *)p;
++ } while (--p >= s);
++ return NULL;
++}
++
++/**
++ * strlen - Find the length of a string
++ * @s: The string to be sized
++ */
++size_t strlen(const char * s)
++{
++ const char *sc;
++
++ for (sc = s; *sc != '\0'; ++sc)
++ /* nothing */;
++ return sc - s;
++}
++
++/**
++ * strnlen - Find the length of a length-limited string
++ * @s: The string to be sized
++ * @count: The maximum number of bytes to search
++ */
++size_t strnlen(const char * s, size_t count)
++{
++ const char *sc;
++
++ for (sc = s; count-- && *sc != '\0'; ++sc)
++ /* nothing */;
++ return sc - s;
++}
++
++/**
++ * strspn - Calculate the length of the initial substring of @s which only
++ * contain letters in @accept
++ * @s: The string to be searched
++ * @accept: The string to search for
++ */
++size_t strspn(const char *s, const char *accept)
++{
++ const char *p;
++ const char *a;
++ size_t count = 0;
++
++ for (p = s; *p != '\0'; ++p) {
++ for (a = accept; *a != '\0'; ++a) {
++ if (*p == *a)
++ break;
++ }
++ if (*a == '\0')
++ return count;
++ ++count;
++ }
++
++ return count;
++}
++
++/**
++ * strpbrk - Find the first occurrence of a set of characters
++ * @cs: The string to be searched
++ * @ct: The characters to search for
++ */
++char * strpbrk(const char * cs,const char * ct)
++{
++ const char *sc1,*sc2;
++
++ for( sc1 = cs; *sc1 != '\0'; ++sc1) {
++ for( sc2 = ct; *sc2 != '\0'; ++sc2) {
++ if (*sc1 == *sc2)
++ return (char *) sc1;
++ }
++ }
++ return NULL;
++}
++
++/**
++ * strtok - Split a string into tokens
++ * @s: The string to be searched
++ * @ct: The characters to search for
++ *
++ * WARNING: strtok is deprecated, use strsep instead.
++ */
++char * strtok(char * s,const char * ct)
++{
++ char *sbegin, *send;
++
++ sbegin = s ? s : ___strtok;
++ if (!sbegin) {
++ return NULL;
++ }
++ sbegin += strspn(sbegin,ct);
++ if (*sbegin == '\0') {
++ ___strtok = NULL;
++ return( NULL );
++ }
++ send = strpbrk( sbegin, ct);
++ if (send && *send != '\0')
++ *send++ = '\0';
++ ___strtok = send;
++ return (sbegin);
++}
++
++/**
++ * strsep - Split a string into tokens
++ * @s: The string to be searched
++ * @ct: The characters to search for
++ *
++ * strsep() updates @s to point after the token, ready for the next call.
++ *
++ * It returns empty tokens, too, behaving exactly like the libc function
++ * of that name. In fact, it was stolen from glibc2 and de-fancy-fied.
++ * Same semantics, slimmer shape. ;)
++ */
++char * strsep(char **s, const char *ct)
++{
++ char *sbegin = *s, *end;
++
++ if (sbegin == NULL)
++ return NULL;
++
++ end = strpbrk(sbegin, ct);
++ if (end)
++ *end++ = '\0';
++ *s = end;
++
++ return sbegin;
++}
++
++/**
++ * memset - Fill a region of memory with the given value
++ * @s: Pointer to the start of the area.
++ * @c: The byte to fill the area with
++ * @count: The size of the area.
++ *
++ * Do not use memset() to access IO space, use memset_io() instead.
++ */
++void * memset(void * s,int c, size_t count)
++{
++ char *xs = (char *) s;
++
++ while (count--)
++ *xs++ = c;
++
++ return s;
++}
++
++/**
++ * bcopy - Copy one area of memory to another
++ * @src: Where to copy from
++ * @dest: Where to copy to
++ * @count: The size of the area.
++ *
++ * Note that this is the same as memcpy(), with the arguments reversed.
++ * memcpy() is the standard, bcopy() is a legacy BSD function.
++ *
++ * You should not use this function to access IO space, use memcpy_toio()
++ * or memcpy_fromio() instead.
++ */
++char * bcopy(const char * src, char * dest, int count)
++{
++ char *tmp = dest;
++
++ while (count--)
++ *tmp++ = *src++;
++
++ return dest;
++}
++
++/**
++ * memcpy - Copy one area of memory to another
++ * @dest: Where to copy to
++ * @src: Where to copy from
++ * @count: The size of the area.
++ *
++ * You should not use this function to access IO space, use memcpy_toio()
++ * or memcpy_fromio() instead.
++ */
++void * memcpy(void * dest,const void *src,size_t count)
++{
++ char *tmp = (char *) dest, *s = (char *) src;
++
++ while (count--)
++ *tmp++ = *s++;
++
++ return dest;
++}
++
++/**
++ * memmove - Copy one area of memory to another
++ * @dest: Where to copy to
++ * @src: Where to copy from
++ * @count: The size of the area.
++ *
++ * Unlike memcpy(), memmove() copes with overlapping areas.
++ */
++void * memmove(void * dest,const void *src,size_t count)
++{
++ char *tmp, *s;
++
++ if (dest <= src) {
++ tmp = (char *) dest;
++ s = (char *) src;
++ while (count--)
++ *tmp++ = *s++;
++ }
++ else {
++ tmp = (char *) dest + count;
++ s = (char *) src + count;
++ while (count--)
++ *--tmp = *--s;
++ }
++
++ return dest;
++}
++
++/**
++ * memcmp - Compare two areas of memory
++ * @cs: One area of memory
++ * @ct: Another area of memory
++ * @count: The size of the area.
++ */
++int memcmp(const void * cs,const void * ct,size_t count)
++{
++ const unsigned char *su1, *su2;
++ signed char res = 0;
++
++ for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
++ if ((res = *su1 - *su2) != 0)
++ break;
++ return res;
++}
++
++#ifndef __HAVE_ARCH_MEMSCAN
++/**
++ * memscan - Find a character in an area of memory.
++ * @addr: The memory area
++ * @c: The byte to search for
++ * @size: The size of the area.
++ *
++ * returns the address of the first occurrence of @c, or 1 byte past
++ * the area if @c is not found
++ */
++void * memscan(void * addr, int c, size_t size)
++{
++ unsigned char * p = (unsigned char *) addr;
++ unsigned char * e = p + size;
++
++ while (p != e) {
++ if (*p == c)
++ return (void *) p;
++ p++;
++ }
++
++ return (void *) p;
++}
++#endif
++
++/**
++ * strstr - Find the first substring in a %NUL terminated string
++ * @s1: The string to be searched
++ * @s2: The string to search for
++ */
++char * strstr(const char * s1,const char * s2)
++{
++ int l1, l2;
++
++ l2 = strlen(s2);
++ if (!l2)
++ return (char *) s1;
++ l1 = strlen(s1);
++ while (l1 >= l2) {
++ l1--;
++ if (!memcmp(s1,s2,l2))
++ return (char *) s1;
++ s1++;
++ }
++ return NULL;
++}
++
++/**
++ * memchr - Find a character in an area of memory.
++ * @s: The memory area
++ * @c: The byte to search for
++ * @n: The size of the area.
++ *
++ * returns the address of the first occurrence of @c, or %NULL
++ * if @c is not found
++ */
++void *memchr(const void *s, int c, size_t n)
++{
++ const unsigned char *p = s;
++ while (n-- != 0) {
++ if ((unsigned char)c == *p++) {
++ return (void *)(p-1);
++ }
++ }
++ return NULL;
++}
+diff -Naru linux/arch/mips/zboot/csb250/head.S linux.spi/arch/mips/zboot/csb250/head.S
+--- linux/arch/mips/zboot/csb250/head.S 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/csb250/head.S 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,157 @@
++/*
++ * arch/mips/kernel/head.S
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 1994, 1995 Waldorf Electronics
++ * Written by Ralf Baechle and Andreas Busse
++ * Copyright (C) 1995 - 1999 Ralf Baechle
++ * Copyright (C) 1996 Paul M. Antoine
++ * Modified for DECStation and hence R3000 support by Paul M. Antoine
++ * Further modifications by David S. Miller and Harald Koerfgen
++ * Copyright (C) 1999 Silicon Graphics, Inc.
++ *
++ * Head.S contains the MIPS exception handler and startup code.
++ *
++ **************************************************************************
++ * 9 Nov, 2000.
++ * Added Cache Error exception handler and SBDDP EJTAG debug exception.
++ *
++ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
++ **************************************************************************
++ */
++#include <linux/config.h>
++#include <linux/threads.h>
++
++#include <asm/asm.h>
++#include <asm/cacheops.h>
++#include <asm/mipsregs.h>
++#include <asm/offset.h>
++#include <asm/cachectl.h>
++#include <asm/regdef.h>
++
++#define IndexInvalidate_I 0x00
++#define IndexWriteBack_D 0x01
++
++ .set noreorder
++ .cprestore
++ LEAF(start)
++start:
++ bal locate
++ nop
++
++ .globl asize /* Someday we'll put the initrd info here. */
++asize: .word 0
++ .word 0
++ .word 0
++ .word 0
++
++locate:
++ subu s8, ra, 8 /* Where we were loaded */
++ la sp, (.stack + 8192)
++
++ move s0, a0 /* Save boot rom start args */
++ move s1, a1
++ move s2, a2
++ move s3, a3
++
++ la a0, start /* Where we were linked to run */
++
++ move a1, s8
++ la a2, _edata
++ subu t1, a2, a0
++ srl t1, t1, 2
++
++ /* copy text section */
++ li t0, 0
++1: lw v0, 0(a1)
++ nop
++ sw v0, 0(a0)
++ xor t0, t0, v0
++ addu a0, 4
++ bne a2, a0, 1b
++ addu a1, 4
++
++ /* Clear BSS */
++ la a0, _edata
++ la a2, _end
++2: sw zero, 0(a0)
++ bne a2, a0, 2b
++ addu a0, 4
++
++ /* push the D-Cache and invalidate I-Cache */
++ li k0, 0x80000000 # start address
++ li k1, 0x80004000 # end address (16KB I-Cache)
++ subu k1, 128
++
++1:
++ .set mips3
++ cache IndexWriteBack_D, 0(k0)
++ cache IndexWriteBack_D, 32(k0)
++ cache IndexWriteBack_D, 64(k0)
++ cache IndexWriteBack_D, 96(k0)
++ cache IndexInvalidate_I, 0(k0)
++ cache IndexInvalidate_I, 32(k0)
++ cache IndexInvalidate_I, 64(k0)
++ cache IndexInvalidate_I, 96(k0)
++ .set mips0
++
++ bne k0, k1, 1b
++ addu k0, k0, 128
++ /* done */
++
++/* move a0, s8 /* load address */
++ subu a0, s8, 0x1000 /* load address */
++ move a1, t1 /* length in words */
++ move a2, t0 /* checksum */
++ move a3, sp
++
++ la ra, 1f
++ la k0, decompress_kernel
++ jr k0
++ nop
++1:
++
++ la a2, __ramdisk_begin
++ la a3, initrd_size
++ lw a0, 0(a2)
++ lw a1, 0(a3)
++ li k0, KERNEL_ENTRY
++ jr k0
++ nop
++3:
++ b 3b
++ END(start)
++
++ LEAF(udelay)
++udelay:
++ END(udelay)
++
++
++ LEAF(FlushCache)
++ li k0, 0x80000000 # start address
++ li k1, 0x80004000 # end address (16KB I-Cache)
++ subu k1, 128
++
++1:
++ .set mips3
++ cache IndexWriteBack_D, 0(k0)
++ cache IndexWriteBack_D, 32(k0)
++ cache IndexWriteBack_D, 64(k0)
++ cache IndexWriteBack_D, 96(k0)
++ cache IndexInvalidate_I, 0(k0)
++ cache IndexInvalidate_I, 32(k0)
++ cache IndexInvalidate_I, 64(k0)
++ cache IndexInvalidate_I, 96(k0)
++ .set mips0
++
++ bne k0, k1, 1b
++ addu k0, k0, 128
++ jr ra
++ nop
++ END(FlushCache)
++
++ .comm .stack,4096*2,4
+diff -Naru linux/arch/mips/zboot/csb250/Makefile linux.spi/arch/mips/zboot/csb250/Makefile
+--- linux/arch/mips/zboot/csb250/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/csb250/Makefile 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,90 @@
++# arch/mips/zboot/pb1xxx/Makefile
++#
++# Makefile for Cogent CSB250 Au1500 board.
++# All of the boot loader code was derived from the ppc
++# boot code.
++#
++# This program is free software; you can redistribute it and/or modify it
++# under the terms of the GNU General Public License as published by the
++# Free Software Foundation; either version 2 of the License, or (at your
++# option) any later version.
++
++.c.s:
++ $(CC) $(CFLAGS) -S -o $*.s $<
++.s.o:
++ $(AS) -o $*.o $<
++.c.o:
++ $(CC) $(CFLAGS) -D__BOOTER__ -c -o $*.o $<
++.S.s:
++ $(CPP) $(AFLAGS) -o $*.o $<
++.S.o:
++ $(CC) $(AFLAGS) -c -o $*.o $<
++
++#########################################################################
++# START BOARD SPECIFIC VARIABLES
++BNAME=csb250
++
++# These two variables control where the zImage is stored
++# in flash and loaded in memory. It only controls how the srec
++# file is generated, the code is the same.
++RAM_RUN_ADDR = 0x80a00000
++FLASH_LOAD_ADDR = 0xBFD00000
++
++# These two variables specify the free ram region
++# that can be used for temporary malloc area
++AVAIL_RAM_START=0x80400000
++AVAIL_RAM_END=0x80800000
++
++# This one must match the LOADADDR in arch/mips/Makefile!
++LOADADDR=0x80100000
++# END BOARD SPECIFIC VARIABLES
++#########################################################################
++
++OBJECTS := head.o ../common/misc-common.o ../common/misc-simple.o \
++ ../common/au1k_uart.o ../common/string.o ../common/ctype.o
++LIBS := ../lib/zlib.a
++
++ENTRY := ../utils/entry
++OFFSET := ../utils/offset
++SIZE := ../utils/size
++
++LD_ARGS := -T ../ld.script -Ttext $(RAM_RUN_ADDR) -Bstatic
++OBJCOPY_ARGS = -O elf32-tradbigmips
++
++all: zImage
++
++clean:
++ rm -rf *.o vmlinux* zvmlinux.* ../images/*.srec
++
++head.o: head.S $(TOPDIR)/vmlinux
++ $(CC) $(AFLAGS) \
++ -DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) $(TOPDIR)/vmlinux ) \
++ -c -o $*.o $<
++
++../common/misc-simple.o:
++ $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \
++ -DAVAIL_RAM_START=$(AVAIL_RAM_START) \
++ -DAVAIL_RAM_END=$(AVAIL_RAM_END) \
++ -DLOADADDR=$(LOADADDR) \
++ -DZIMAGE_SIZE=0 -c -o $@ $*.c
++
++zvmlinux: $(OBJECTS) $(LIBS) ../ld.script ../images/vmlinux.gz ../common/dummy.o
++ $(OBJCOPY) \
++ --add-section=.image=../images/vmlinux.gz \
++ --set-section-flags=.image=contents,alloc,load,readonly,data \
++ ../common/dummy.o image.o
++ $(LD) $(LD_ARGS) -o $@ $(OBJECTS) image.o $(LIBS)
++ $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr \
++ -R .initrd -R .sysmap
++
++# Here we manipulate the image in order to get it the necessary
++# srecord file we need.
++zImage: zvmlinux
++ mv zvmlinux ../images/zImage.$(BNAME)
++ $(OBJCOPY) -O binary ../images/zImage.$(BNAME) ../images/$(BNAME).bin
++
++zImage.flash: zImage
++ $(OBJCOPY) -O srec --adjust-vma 0x3ed00000 \
++ ../images/zImage.$(BNAME) ../images/$(BNAME).flash.srec
++
++include $(TOPDIR)/Rules.make
+diff -Naru linux/arch/mips/zboot/images/Makefile linux.spi/arch/mips/zboot/images/Makefile
+--- linux/arch/mips/zboot/images/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/images/Makefile 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,10 @@
++
++include $(TOPDIR)/Rules.make
++
++vmlinux.gz: $(TOPDIR)/vmlinux
++ $(OBJCOPY) -S -O binary $(TOPDIR)/vmlinux vmlinux
++ gzip -vf vmlinux
++
++clean:
++ rm -f vmlinux.* zImage.*
++
+diff -Naru linux/arch/mips/zboot/include/nonstdio.h linux.spi/arch/mips/zboot/include/nonstdio.h
+--- linux/arch/mips/zboot/include/nonstdio.h 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/include/nonstdio.h 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,18 @@
++/*
++ * Copyright (C) Paul Mackerras 1997.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version
++ * 2 of the License, or (at your option) any later version.
++ */
++typedef int FILE;
++extern FILE *stdin, *stdout;
++#define NULL ((void *)0)
++#define EOF (-1)
++#define fopen(n, m) NULL
++#define fflush(f) 0
++#define fclose(f) 0
++extern char *fgets();
++
++#define perror(s) printf("%s: no files!\n", (s))
+diff -Naru linux/arch/mips/zboot/include/ns16550.h linux.spi/arch/mips/zboot/include/ns16550.h
+--- linux/arch/mips/zboot/include/ns16550.h 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/include/ns16550.h 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,49 @@
++/*
++ * NS16550 Serial Port
++ */
++
++/*
++ * Figure out which file will have the definitons of COMx
++ */
++#if !defined(CONFIG_AU1X00_UART)
++#error no serial.h
++#endif
++
++/* Some machines have their uart registers 16 bytes apart. Most don't.
++ * TODO: Make this work like drivers/char/serial does - Tom */
++#if !defined(UART_REG_PAD)
++#define UART_REG_PAD(x)
++#endif
++
++struct NS16550
++ {
++ unsigned char rbr; /* 0 */
++ UART_REG_PAD(rbr)
++ unsigned char ier; /* 1 */
++ UART_REG_PAD(ier)
++ unsigned char fcr; /* 2 */
++ UART_REG_PAD(fcr)
++ unsigned char lcr; /* 3 */
++ UART_REG_PAD(lcr)
++ unsigned char mcr; /* 4 */
++ UART_REG_PAD(mcr)
++ unsigned char lsr; /* 5 */
++ UART_REG_PAD(lsr)
++ unsigned char msr; /* 6 */
++ UART_REG_PAD(msr)
++ unsigned char scr; /* 7 */
++ };
++
++#define thr rbr
++#define iir fcr
++#define dll rbr
++#define dlm ier
++
++#define LSR_DR 0x01 /* Data ready */
++#define LSR_OE 0x02 /* Overrun */
++#define LSR_PE 0x04 /* Parity error */
++#define LSR_FE 0x08 /* Framing error */
++#define LSR_BI 0x10 /* Break */
++#define LSR_THRE 0x20 /* Xmit holding register empty */
++#define LSR_TEMT 0x40 /* Xmitter empty */
++#define LSR_ERR 0x80 /* Error */
+diff -Naru linux/arch/mips/zboot/include/pb1000_serial.h linux.spi/arch/mips/zboot/include/pb1000_serial.h
+--- linux/arch/mips/zboot/include/pb1000_serial.h 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/include/pb1000_serial.h 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,20 @@
++/*
++ * arch/ppc/boot/include/sandpoint_serial.h
++ *
++ * Location of the COM ports on Motorola SPS Sandpoint machines
++ *
++ * Author: Mark A. Greer
++ * mgreer@mvista.com
++ *
++ * Copyright 2001 MontaVista Software Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#define COM1 0xfe0003f8
++#define COM2 0xfe0002f8
++#define COM3 0x00000000 /* No COM3 */
++#define COM4 0x00000000 /* No COM4 */
+diff -Naru linux/arch/mips/zboot/include/zlib.h linux.spi/arch/mips/zboot/include/zlib.h
+--- linux/arch/mips/zboot/include/zlib.h 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/include/zlib.h 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,432 @@
++/* $Id: zlib.h,v 1.2 2002/02/16 16:55:45 ppopov Exp $ */
++
++/*
++ * This file is derived from zlib.h and zconf.h from the zlib-0.95
++ * distribution by Jean-loup Gailly and Mark Adler, with some additions
++ * by Paul Mackerras to aid in implementing Deflate compression and
++ * decompression for PPP packets.
++ */
++
++/*
++ * ==FILEVERSION 960122==
++ *
++ * This marker is used by the Linux installation script to determine
++ * whether an up-to-date version of this file is already installed.
++ */
++
++/* zlib.h -- interface of the 'zlib' general purpose compression library
++ version 0.95, Aug 16th, 1995.
++
++ Copyright (C) 1995 Jean-loup Gailly and Mark Adler
++
++ This software is provided 'as-is', without any express or implied
++ warranty. In no event will the authors be held liable for any damages
++ arising from the use of this software.
++
++ Permission is granted to anyone to use this software for any purpose,
++ including commercial applications, and to alter it and redistribute it
++ freely, subject to the following restrictions:
++
++ 1. The origin of this software must not be misrepresented; you must not
++ claim that you wrote the original software. If you use this software
++ in a product, an acknowledgment in the product documentation would be
++ appreciated but is not required.
++ 2. Altered source versions must be plainly marked as such, and must not be
++ misrepresented as being the original software.
++ 3. This notice may not be removed or altered from any source distribution.
++
++ Jean-loup Gailly Mark Adler
++ gzip@prep.ai.mit.edu madler@alumni.caltech.edu
++ */
++
++#ifndef _ZLIB_H
++#define _ZLIB_H
++
++/* #include "zconf.h" */ /* included directly here */
++
++/* zconf.h -- configuration of the zlib compression library
++ * Copyright (C) 1995 Jean-loup Gailly.
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
++
++/*
++ The library does not install any signal handler. It is recommended to
++ add at least a handler for SIGSEGV when decompressing; the library checks
++ the consistency of the input data whenever possible but may go nuts
++ for some forms of corrupted input.
++ */
++
++/*
++ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
++ * than 64k bytes at a time (needed on systems with 16-bit int).
++ * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
++ * at addresses which are not a multiple of their size.
++ * Under DOS, -DFAR=far or -DFAR=__far may be needed.
++ */
++
++#ifndef STDC
++# if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
++# define STDC
++# endif
++#endif
++
++#ifdef __MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
++# include <unix.h>
++#endif
++
++/* Maximum value for memLevel in deflateInit2 */
++#ifndef MAX_MEM_LEVEL
++# ifdef MAXSEG_64K
++# define MAX_MEM_LEVEL 8
++# else
++# define MAX_MEM_LEVEL 9
++# endif
++#endif
++
++#ifndef FAR
++# define FAR
++#endif
++
++/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
++#ifndef MAX_WBITS
++# define MAX_WBITS 15 /* 32K LZ77 window */
++#endif
++
++/* The memory requirements for deflate are (in bytes):
++ 1 << (windowBits+2) + 1 << (memLevel+9)
++ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
++ plus a few kilobytes for small objects. For example, if you want to reduce
++ the default memory requirements from 256K to 128K, compile with
++ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
++ Of course this will generally degrade compression (there's no free lunch).
++
++ The memory requirements for inflate are (in bytes) 1 << windowBits
++ that is, 32K for windowBits=15 (default value) plus a few kilobytes
++ for small objects.
++*/
++
++ /* Type declarations */
++
++#ifndef OF /* function prototypes */
++# ifdef STDC
++# define OF(args) args
++# else
++# define OF(args) ()
++# endif
++#endif
++
++typedef unsigned char Byte; /* 8 bits */
++typedef unsigned int uInt; /* 16 bits or more */
++typedef unsigned long uLong; /* 32 bits or more */
++
++typedef Byte FAR Bytef;
++typedef char FAR charf;
++typedef int FAR intf;
++typedef uInt FAR uIntf;
++typedef uLong FAR uLongf;
++
++#ifdef STDC
++ typedef void FAR *voidpf;
++ typedef void *voidp;
++#else
++ typedef Byte FAR *voidpf;
++ typedef Byte *voidp;
++#endif
++
++/* end of original zconf.h */
++
++#define ZLIB_VERSION "0.95P"
++
++/*
++ The 'zlib' compression library provides in-memory compression and
++ decompression functions, including integrity checks of the uncompressed
++ data. This version of the library supports only one compression method
++ (deflation) but other algorithms may be added later and will have the same
++ stream interface.
++
++ For compression the application must provide the output buffer and
++ may optionally provide the input buffer for optimization. For decompression,
++ the application must provide the input buffer and may optionally provide
++ the output buffer for optimization.
++
++ Compression can be done in a single step if the buffers are large
++ enough (for example if an input file is mmap'ed), or can be done by
++ repeated calls of the compression function. In the latter case, the
++ application must provide more input and/or consume the output
++ (providing more output space) before each call.
++*/
++
++typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
++typedef void (*free_func) OF((voidpf opaque, voidpf address, uInt nbytes));
++
++struct internal_state;
++
++typedef struct z_stream_s {
++ Bytef *next_in; /* next input byte */
++ uInt avail_in; /* number of bytes available at next_in */
++ uLong total_in; /* total nb of input bytes read so far */
++
++ Bytef *next_out; /* next output byte should be put there */
++ uInt avail_out; /* remaining free space at next_out */
++ uLong total_out; /* total nb of bytes output so far */
++
++ char *msg; /* last error message, NULL if no error */
++ struct internal_state FAR *state; /* not visible by applications */
++
++ alloc_func zalloc; /* used to allocate the internal state */
++ free_func zfree; /* used to free the internal state */
++ voidp opaque; /* private data object passed to zalloc and zfree */
++
++ Byte data_type; /* best guess about the data type: ascii or binary */
++
++} z_stream;
++
++/*
++ The application must update next_in and avail_in when avail_in has
++ dropped to zero. It must update next_out and avail_out when avail_out
++ has dropped to zero. The application must initialize zalloc, zfree and
++ opaque before calling the init function. All other fields are set by the
++ compression library and must not be updated by the application.
++
++ The opaque value provided by the application will be passed as the first
++ parameter for calls of zalloc and zfree. This can be useful for custom
++ memory management. The compression library attaches no meaning to the
++ opaque value.
++
++ zalloc must return Z_NULL if there is not enough memory for the object.
++ On 16-bit systems, the functions zalloc and zfree must be able to allocate
++ exactly 65536 bytes, but will not be required to allocate more than this
++ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
++ pointers returned by zalloc for objects of exactly 65536 bytes *must*
++ have their offset normalized to zero. The default allocation function
++ provided by this library ensures this (see zutil.c). To reduce memory
++ requirements and avoid any allocation of 64K objects, at the expense of
++ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
++
++ The fields total_in and total_out can be used for statistics or
++ progress reports. After compression, total_in holds the total size of
++ the uncompressed data and may be saved for use in the decompressor
++ (particularly if the decompressor wants to decompress everything in
++ a single step).
++*/
++
++ /* constants */
++
++#define Z_NO_FLUSH 0
++#define Z_PARTIAL_FLUSH 1
++#define Z_FULL_FLUSH 2
++#define Z_SYNC_FLUSH 3 /* experimental: partial_flush + byte align */
++#define Z_FINISH 4
++#define Z_PACKET_FLUSH 5
++/* See deflate() below for the usage of these constants */
++
++#define Z_OK 0
++#define Z_STREAM_END 1
++#define Z_ERRNO (-1)
++#define Z_STREAM_ERROR (-2)
++#define Z_DATA_ERROR (-3)
++#define Z_MEM_ERROR (-4)
++#define Z_BUF_ERROR (-5)
++/* error codes for the compression/decompression functions */
++
++#define Z_BEST_SPEED 1
++#define Z_BEST_COMPRESSION 9
++#define Z_DEFAULT_COMPRESSION (-1)
++/* compression levels */
++
++#define Z_FILTERED 1
++#define Z_HUFFMAN_ONLY 2
++#define Z_DEFAULT_STRATEGY 0
++
++#define Z_BINARY 0
++#define Z_ASCII 1
++#define Z_UNKNOWN 2
++/* Used to set the data_type field */
++
++#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
++
++extern char *zlib_version;
++/* The application can compare zlib_version and ZLIB_VERSION for consistency.
++ If the first character differs, the library code actually used is
++ not compatible with the zlib.h header file used by the application.
++ */
++
++ /* basic functions */
++
++extern int inflateInit OF((z_stream *strm));
++/*
++ Initializes the internal stream state for decompression. The fields
++ zalloc and zfree must be initialized before by the caller. If zalloc and
++ zfree are set to Z_NULL, inflateInit updates them to use default allocation
++ functions.
++
++ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
++ enough memory. msg is set to null if there is no error message.
++ inflateInit does not perform any decompression: this will be done by
++ inflate().
++*/
++
++
++extern int inflate OF((z_stream *strm, int flush));
++/*
++ Performs one or both of the following actions:
++
++ - Decompress more input starting at next_in and update next_in and avail_in
++ accordingly. If not all input can be processed (because there is not
++ enough room in the output buffer), next_in is updated and processing
++ will resume at this point for the next call of inflate().
++
++ - Provide more output starting at next_out and update next_out and avail_out
++ accordingly. inflate() always provides as much output as possible
++ (until there is no more input data or no more space in the output buffer).
++
++ Before the call of inflate(), the application should ensure that at least
++ one of the actions is possible, by providing more input and/or consuming
++ more output, and updating the next_* and avail_* values accordingly.
++ The application can consume the uncompressed output when it wants, for
++ example when the output buffer is full (avail_out == 0), or after each
++ call of inflate().
++
++ If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
++ inflate flushes as much output as possible to the output buffer. The
++ flushing behavior of inflate is not specified for values of the flush
++ parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
++ current implementation actually flushes as much output as possible
++ anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data
++ has been consumed, it is expecting to see the length field of a stored
++ block; if not, it returns Z_DATA_ERROR.
++
++ inflate() should normally be called until it returns Z_STREAM_END or an
++ error. However if all decompression is to be performed in a single step
++ (a single call of inflate), the parameter flush should be set to
++ Z_FINISH. In this case all pending input is processed and all pending
++ output is flushed; avail_out must be large enough to hold all the
++ uncompressed data. (The size of the uncompressed data may have been saved
++ by the compressor for this purpose.) The next operation on this stream must
++ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
++ is never required, but can be used to inform inflate that a faster routine
++ may be used for the single inflate() call.
++
++ inflate() returns Z_OK if some progress has been made (more input
++ processed or more output produced), Z_STREAM_END if the end of the
++ compressed data has been reached and all uncompressed output has been
++ produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
++ the stream structure was inconsistent (for example if next_in or next_out
++ was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
++ progress is possible or if there was not enough room in the output buffer
++ when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
++ call inflateSync to look for a good compression block. */
++
++
++extern int inflateEnd OF((z_stream *strm));
++/*
++ All dynamically allocated data structures for this stream are freed.
++ This function discards any unprocessed input and does not flush any
++ pending output.
++
++ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
++ was inconsistent. In the error case, msg may be set but then points to a
++ static string (which must not be deallocated).
++*/
++
++ /* advanced functions */
++
++extern int inflateInit2 OF((z_stream *strm,
++ int windowBits));
++/*
++ This is another version of inflateInit with more compression options. The
++ fields next_out, zalloc and zfree must be initialized before by the caller.
++
++ The windowBits parameter is the base two logarithm of the maximum window
++ size (the size of the history buffer). It should be in the range 8..15 for
++ this version of the library (the value 16 will be allowed soon). The
++ default value is 15 if inflateInit is used instead. If a compressed stream
++ with a larger window size is given as input, inflate() will return with
++ the error code Z_DATA_ERROR instead of trying to allocate a larger window.
++
++ If next_out is not null, the library will use this buffer for the history
++ buffer; the buffer must either be large enough to hold the entire output
++ data, or have at least 1<<windowBits bytes. If next_out is null, the
++ library will allocate its own buffer (and leave next_out null). next_in
++ need not be provided here but must be provided by the application for the
++ next call of inflate().
++
++ If the history buffer is provided by the application, next_out must
++ never be changed by the application since the decompressor maintains
++ history information inside this buffer from call to call; the application
++ can only reset next_out to the beginning of the history buffer when
++ avail_out is zero and all output has been consumed.
++
++ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
++ not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
++ windowBits < 8). msg is set to null if there is no error message.
++ inflateInit2 does not perform any decompression: this will be done by
++ inflate().
++*/
++
++extern int inflateSync OF((z_stream *strm));
++/*
++ Skips invalid compressed data until the special marker (see deflate()
++ above) can be found, or until all available input is skipped. No output
++ is provided.
++
++ inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
++ if no more input was provided, Z_DATA_ERROR if no marker has been found,
++ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
++ case, the application may save the current current value of total_in which
++ indicates where valid compressed data was found. In the error case, the
++ application may repeatedly call inflateSync, providing more input each time,
++ until success or end of the input data.
++*/
++
++extern int inflateReset OF((z_stream *strm));
++/*
++ This function is equivalent to inflateEnd followed by inflateInit,
++ but does not free and reallocate all the internal decompression state.
++ The stream will keep attributes that may have been set by inflateInit2.
++
++ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
++ stream state was inconsistent (such as zalloc or state being NULL).
++*/
++
++extern int inflateIncomp OF((z_stream *strm));
++/*
++ This function adds the data at next_in (avail_in bytes) to the output
++ history without performing any output. There must be no pending output,
++ and the decompressor must be expecting to see the start of a block.
++ Calling this function is equivalent to decompressing a stored block
++ containing the data at next_in (except that the data is not output).
++*/
++
++ /* checksum functions */
++
++/*
++ This function is not related to compression but is exported
++ anyway because it might be useful in applications using the
++ compression library.
++*/
++
++extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len));
++
++/*
++ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
++ return the updated checksum. If buf is NULL, this function returns
++ the required initial value for the checksum.
++ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
++ much faster. Usage example:
++
++ uLong adler = adler32(0L, Z_NULL, 0);
++
++ while (read_buffer(buffer, length) != EOF) {
++ adler = adler32(adler, buffer, length);
++ }
++ if (adler != original_adler) error();
++*/
++
++#ifndef _Z_UTIL_H
++ struct internal_state {int dummy;}; /* hack for buggy compilers */
++#endif
++
++#endif /* _ZLIB_H */
+diff -Naru linux/arch/mips/zboot/ld.script linux.spi/arch/mips/zboot/ld.script
+--- linux/arch/mips/zboot/ld.script 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/ld.script 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,151 @@
++OUTPUT_ARCH(mips)
++ENTRY(start)
++SECTIONS
++{
++ /* Read-only sections, merged into text segment: */
++ /* . = 0x81000000; */
++ .init : { *(.init) } =0
++ .text :
++ {
++ _ftext = . ;
++ *(.text)
++ *(.rodata)
++ *(.rodata1)
++ /* .gnu.warning sections are handled specially by elf32.em. */
++ *(.gnu.warning)
++ } =0
++ .kstrtab : { *(.kstrtab) }
++
++ . = ALIGN(16); /* Exception table */
++ __start___ex_table = .;
++ __ex_table : { *(__ex_table) }
++ __stop___ex_table = .;
++
++ __start___dbe_table = .; /* Exception table for data bus errors */
++ __dbe_table : { *(__dbe_table) }
++ __stop___dbe_table = .;
++
++ __start___ksymtab = .; /* Kernel symbol table */
++ __ksymtab : { *(__ksymtab) }
++ __stop___ksymtab = .;
++
++ _etext = .;
++
++ . = ALIGN(8192);
++ .data.init_task : { *(.data.init_task) }
++
++ /* Startup code */
++ . = ALIGN(4096);
++ __init_begin = .;
++ .text.init : { *(.text.init) }
++ .data.init : { *(.data.init) }
++ . = ALIGN(16);
++ __setup_start = .;
++ .setup.init : { *(.setup.init) }
++ __setup_end = .;
++ __initcall_start = .;
++ .initcall.init : { *(.initcall.init) }
++ __initcall_end = .;
++ . = ALIGN(4096); /* Align double page for init_task_union */
++ __init_end = .;
++
++ . = ALIGN(4096);
++ .data.page_aligned : { *(.data.idt) }
++
++ . = ALIGN(32);
++ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
++
++ .fini : { *(.fini) } =0
++ .reginfo : { *(.reginfo) }
++ /* Adjust the address for the data segment. We want to adjust up to
++ the same address within the page on the next page up. It would
++ be more correct to do this:
++ . = .;
++ The current expression does not correctly handle the case of a
++ text segment ending precisely at the end of a page; it causes the
++ data segment to skip a page. The above expression does not have
++ this problem, but it will currently (2/95) cause BFD to allocate
++ a single segment, combining both text and data, for this case.
++ This will prevent the text segment from being shared among
++ multiple executions of the program; I think that is more
++ important than losing a page of the virtual address space (note
++ that no actual memory is lost; the page which is skipped can not
++ be referenced). */
++ . = .;
++ .data :
++ {
++ _fdata = . ;
++ *(.data)
++
++ /* Put the compressed image here, so bss is on the end. */
++ __image_begin = .;
++ *(.image)
++ __image_end = .;
++ /* Align the initial ramdisk image (INITRD) on page boundaries. */
++ . = ALIGN(4096);
++ __ramdisk_begin = .;
++ *(.initrd)
++ __ramdisk_end = .;
++ . = ALIGN(4096);
++
++ CONSTRUCTORS
++ }
++ .data1 : { *(.data1) }
++ _gp = . + 0x8000;
++ .lit8 : { *(.lit8) }
++ .lit4 : { *(.lit4) }
++ .ctors : { *(.ctors) }
++ .dtors : { *(.dtors) }
++ .got : { *(.got.plt) *(.got) }
++ .dynamic : { *(.dynamic) }
++ /* We want the small data sections together, so single-instruction offsets
++ can access them all, and initialized data all before uninitialized, so
++ we can shorten the on-disk segment size. */
++ .sdata : { *(.sdata) }
++ . = ALIGN(4);
++ _edata = .;
++ PROVIDE (edata = .);
++
++ __bss_start = .;
++ _fbss = .;
++ .sbss : { *(.sbss) *(.scommon) }
++ .bss :
++ {
++ *(.dynbss)
++ *(.bss)
++ *(COMMON)
++ . = ALIGN(4);
++ _end = . ;
++ PROVIDE (end = .);
++ }
++
++ /* Sections to be discarded */
++ /DISCARD/ :
++ {
++ *(.text.exit)
++ *(.data.exit)
++ *(.exitcall.exit)
++ }
++
++ /* This is the MIPS specific mdebug section. */
++ .mdebug : { *(.mdebug) }
++ /* These are needed for ELF backends which have not yet been
++ converted to the new style linker. */
++ .stab 0 : { *(.stab) }
++ .stabstr 0 : { *(.stabstr) }
++ /* DWARF debug sections.
++ Symbols in the .debug DWARF section are relative to the beginning of the
++ section so we begin .debug at 0. It's not clear yet what needs to happen
++ for the others. */
++ .debug 0 : { *(.debug) }
++ .debug_srcinfo 0 : { *(.debug_srcinfo) }
++ .debug_aranges 0 : { *(.debug_aranges) }
++ .debug_pubnames 0 : { *(.debug_pubnames) }
++ .debug_sfnames 0 : { *(.debug_sfnames) }
++ .line 0 : { *(.line) }
++ /* These must appear regardless of . */
++ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
++ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
++ .comment : { *(.comment) }
++ .note : { *(.note) }
++}
+diff -Naru linux/arch/mips/zboot/lib/Makefile linux.spi/arch/mips/zboot/lib/Makefile
+--- linux/arch/mips/zboot/lib/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/lib/Makefile 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,9 @@
++#
++# Makefile for some libs needed by zImage.
++#
++
++L_TARGET := zlib.a
++
++obj-y := zlib.o
++
++include $(TOPDIR)/Rules.make
+diff -Naru linux/arch/mips/zboot/lib/zlib.c linux.spi/arch/mips/zboot/lib/zlib.c
+--- linux/arch/mips/zboot/lib/zlib.c 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/lib/zlib.c 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,2148 @@
++/*
++ * This file is derived from various .h and .c files from the zlib-0.95
++ * distribution by Jean-loup Gailly and Mark Adler, with some additions
++ * by Paul Mackerras to aid in implementing Deflate compression and
++ * decompression for PPP packets. See zlib.h for conditions of
++ * distribution and use.
++ *
++ * Changes that have been made include:
++ * - changed functions not used outside this file to "local"
++ * - added minCompression parameter to deflateInit2
++ * - added Z_PACKET_FLUSH (see zlib.h for details)
++ * - added inflateIncomp
++ *
++ * $Id: zlib.c,v 1.2 2002/02/16 16:55:45 ppopov Exp $
++ */
++
++/*+++++*/
++/* zutil.h -- internal interface and configuration of the compression library
++ * Copyright (C) 1995 Jean-loup Gailly.
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++ part of the implementation of the compression library and is
++ subject to change. Applications should only use zlib.h.
++ */
++
++/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */
++
++#define _Z_UTIL_H
++
++#include "zlib.h"
++
++#ifndef local
++# define local static
++#endif
++/* compile with -Dlocal if your debugger can't find static symbols */
++
++#define FAR
++
++typedef unsigned char uch;
++typedef uch FAR uchf;
++typedef unsigned short ush;
++typedef ush FAR ushf;
++typedef unsigned long ulg;
++
++extern char *z_errmsg[]; /* indexed by 1-zlib_error */
++
++#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err)
++/* To be used only when the state is known to be valid */
++
++#ifndef NULL
++#define NULL ((void *) 0)
++#endif
++
++ /* common constants */
++
++#define DEFLATED 8
++
++#ifndef DEF_WBITS
++# define DEF_WBITS MAX_WBITS
++#endif
++/* default windowBits for decompression. MAX_WBITS is for compression only */
++
++#if MAX_MEM_LEVEL >= 8
++# define DEF_MEM_LEVEL 8
++#else
++# define DEF_MEM_LEVEL MAX_MEM_LEVEL
++#endif
++/* default memLevel */
++
++#define STORED_BLOCK 0
++#define STATIC_TREES 1
++#define DYN_TREES 2
++/* The three kinds of block type */
++
++#define MIN_MATCH 3
++#define MAX_MATCH 258
++/* The minimum and maximum match lengths */
++
++ /* functions */
++
++#include <linux/string.h>
++#define zmemcpy memcpy
++#define zmemzero(dest, len) memset(dest, 0, len)
++
++/* Diagnostic functions */
++#ifdef DEBUG_ZLIB
++# include <stdio.h>
++# ifndef verbose
++# define verbose 0
++# endif
++# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
++# define Trace(x) fprintf x
++# define Tracev(x) {if (verbose) fprintf x ;}
++# define Tracevv(x) {if (verbose>1) fprintf x ;}
++# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
++# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
++#else
++# define Assert(cond,msg)
++# define Trace(x)
++# define Tracev(x)
++# define Tracevv(x)
++# define Tracec(c,x)
++# define Tracecv(c,x)
++#endif
++
++
++typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len));
++
++/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */
++/* void zcfree OF((voidpf opaque, voidpf ptr)); */
++
++#define ZALLOC(strm, items, size) \
++ (*((strm)->zalloc))((strm)->opaque, (items), (size))
++#define ZFREE(strm, addr, size) \
++ (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size))
++#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);}
++
++/* deflate.h -- internal compression state
++ * Copyright (C) 1995 Jean-loup Gailly
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++ part of the implementation of the compression library and is
++ subject to change. Applications should only use zlib.h.
++ */
++
++/*+++++*/
++/* infblock.h -- header to use infblock.c
++ * Copyright (C) 1995 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++ part of the implementation of the compression library and is
++ subject to change. Applications should only use zlib.h.
++ */
++
++struct inflate_blocks_state;
++typedef struct inflate_blocks_state FAR inflate_blocks_statef;
++
++local inflate_blocks_statef * inflate_blocks_new OF((
++ z_stream *z,
++ check_func c, /* check function */
++ uInt w)); /* window size */
++
++local int inflate_blocks OF((
++ inflate_blocks_statef *,
++ z_stream *,
++ int)); /* initial return code */
++
++local void inflate_blocks_reset OF((
++ inflate_blocks_statef *,
++ z_stream *,
++ uLongf *)); /* check value on output */
++
++local int inflate_blocks_free OF((
++ inflate_blocks_statef *,
++ z_stream *,
++ uLongf *)); /* check value on output */
++
++local int inflate_addhistory OF((
++ inflate_blocks_statef *,
++ z_stream *));
++
++local int inflate_packet_flush OF((
++ inflate_blocks_statef *));
++
++/*+++++*/
++/* inftrees.h -- header to use inftrees.c
++ * Copyright (C) 1995 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++ part of the implementation of the compression library and is
++ subject to change. Applications should only use zlib.h.
++ */
++
++/* Huffman code lookup table entry--this entry is four bytes for machines
++ that have 16-bit pointers (e.g. PC's in the small or medium model). */
++
++typedef struct inflate_huft_s FAR inflate_huft;
++
++struct inflate_huft_s {
++ union {
++ struct {
++ Byte Exop; /* number of extra bits or operation */
++ Byte Bits; /* number of bits in this code or subcode */
++ } what;
++ uInt Nalloc; /* number of these allocated here */
++ Bytef *pad; /* pad structure to a power of 2 (4 bytes for */
++ } word; /* 16-bit, 8 bytes for 32-bit machines) */
++ union {
++ uInt Base; /* literal, length base, or distance base */
++ inflate_huft *Next; /* pointer to next level of table */
++ } more;
++};
++
++#ifdef DEBUG_ZLIB
++ local uInt inflate_hufts;
++#endif
++
++local int inflate_trees_bits OF((
++ uIntf *, /* 19 code lengths */
++ uIntf *, /* bits tree desired/actual depth */
++ inflate_huft * FAR *, /* bits tree result */
++ z_stream *)); /* for zalloc, zfree functions */
++
++local int inflate_trees_dynamic OF((
++ uInt, /* number of literal/length codes */
++ uInt, /* number of distance codes */
++ uIntf *, /* that many (total) code lengths */
++ uIntf *, /* literal desired/actual bit depth */
++ uIntf *, /* distance desired/actual bit depth */
++ inflate_huft * FAR *, /* literal/length tree result */
++ inflate_huft * FAR *, /* distance tree result */
++ z_stream *)); /* for zalloc, zfree functions */
++
++local int inflate_trees_fixed OF((
++ uIntf *, /* literal desired/actual bit depth */
++ uIntf *, /* distance desired/actual bit depth */
++ inflate_huft * FAR *, /* literal/length tree result */
++ inflate_huft * FAR *)); /* distance tree result */
++
++local int inflate_trees_free OF((
++ inflate_huft *, /* tables to free */
++ z_stream *)); /* for zfree function */
++
++
++/*+++++*/
++/* infcodes.h -- header to use infcodes.c
++ * Copyright (C) 1995 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++ part of the implementation of the compression library and is
++ subject to change. Applications should only use zlib.h.
++ */
++
++struct inflate_codes_state;
++typedef struct inflate_codes_state FAR inflate_codes_statef;
++
++local inflate_codes_statef *inflate_codes_new OF((
++ uInt, uInt,
++ inflate_huft *, inflate_huft *,
++ z_stream *));
++
++local int inflate_codes OF((
++ inflate_blocks_statef *,
++ z_stream *,
++ int));
++
++local void inflate_codes_free OF((
++ inflate_codes_statef *,
++ z_stream *));
++
++
++/*+++++*/
++/* inflate.c -- zlib interface to inflate modules
++ * Copyright (C) 1995 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* inflate private state */
++struct internal_state {
++
++ /* mode */
++ enum {
++ METHOD, /* waiting for method byte */
++ FLAG, /* waiting for flag byte */
++ BLOCKS, /* decompressing blocks */
++ CHECK4, /* four check bytes to go */
++ CHECK3, /* three check bytes to go */
++ CHECK2, /* two check bytes to go */
++ CHECK1, /* one check byte to go */
++ DONE, /* finished check, done */
++ BAD} /* got an error--stay here */
++ mode; /* current inflate mode */
++
++ /* mode dependent information */
++ union {
++ uInt method; /* if FLAGS, method byte */
++ struct {
++ uLong was; /* computed check value */
++ uLong need; /* stream check value */
++ } check; /* if CHECK, check values to compare */
++ uInt marker; /* if BAD, inflateSync's marker bytes count */
++ } sub; /* submode */
++
++ /* mode independent information */
++ int nowrap; /* flag for no wrapper */
++ uInt wbits; /* log2(window size) (8..15, defaults to 15) */
++ inflate_blocks_statef
++ *blocks; /* current inflate_blocks state */
++
++};
++
++
++int inflateReset(z)
++z_stream *z;
++{
++ uLong c;
++
++ if (z == Z_NULL || z->state == Z_NULL)
++ return Z_STREAM_ERROR;
++ z->total_in = z->total_out = 0;
++ z->msg = Z_NULL;
++ z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
++ inflate_blocks_reset(z->state->blocks, z, &c);
++ Trace((stderr, "inflate: reset\n"));
++ return Z_OK;
++}
++
++
++int inflateEnd(z)
++z_stream *z;
++{
++ uLong c;
++
++ if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
++ return Z_STREAM_ERROR;
++ if (z->state->blocks != Z_NULL)
++ inflate_blocks_free(z->state->blocks, z, &c);
++ ZFREE(z, z->state, sizeof(struct internal_state));
++ z->state = Z_NULL;
++ Trace((stderr, "inflate: end\n"));
++ return Z_OK;
++}
++
++
++int inflateInit2(z, w)
++z_stream *z;
++int w;
++{
++ /* initialize state */
++ if (z == Z_NULL)
++ return Z_STREAM_ERROR;
++/* if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */
++/* if (z->zfree == Z_NULL) z->zfree = zcfree; */
++ if ((z->state = (struct internal_state FAR *)
++ ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
++ return Z_MEM_ERROR;
++ z->state->blocks = Z_NULL;
++
++ /* handle undocumented nowrap option (no zlib header or check) */
++ z->state->nowrap = 0;
++ if (w < 0)
++ {
++ w = - w;
++ z->state->nowrap = 1;
++ }
++
++ /* set window size */
++ if (w < 8 || w > 15)
++ {
++ inflateEnd(z);
++ return Z_STREAM_ERROR;
++ }
++ z->state->wbits = (uInt)w;
++
++ /* create inflate_blocks state */
++ if ((z->state->blocks =
++ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w))
++ == Z_NULL)
++ {
++ inflateEnd(z);
++ return Z_MEM_ERROR;
++ }
++ Trace((stderr, "inflate: allocated\n"));
++
++ /* reset state */
++ inflateReset(z);
++ return Z_OK;
++}
++
++
++int inflateInit(z)
++z_stream *z;
++{
++ return inflateInit2(z, DEF_WBITS);
++}
++
++
++#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;}
++#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
++
++int inflate(z, f)
++z_stream *z;
++int f;
++{
++ int r;
++ uInt b;
++
++ if (z == Z_NULL || z->next_in == Z_NULL)
++ return Z_STREAM_ERROR;
++ r = Z_BUF_ERROR;
++ while (1) switch (z->state->mode)
++ {
++ case METHOD:
++ NEEDBYTE
++ if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED)
++ {
++ z->state->mode = BAD;
++ z->msg = "unknown compression method";
++ z->state->sub.marker = 5; /* can't try inflateSync */
++ break;
++ }
++ if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
++ {
++ z->state->mode = BAD;
++ z->msg = "invalid window size";
++ z->state->sub.marker = 5; /* can't try inflateSync */
++ break;
++ }
++ z->state->mode = FLAG;
++ case FLAG:
++ NEEDBYTE
++ if ((b = NEXTBYTE) & 0x20)
++ {
++ z->state->mode = BAD;
++ z->msg = "invalid reserved bit";
++ z->state->sub.marker = 5; /* can't try inflateSync */
++ break;
++ }
++ if (((z->state->sub.method << 8) + b) % 31)
++ {
++ z->state->mode = BAD;
++ z->msg = "incorrect header check";
++ z->state->sub.marker = 5; /* can't try inflateSync */
++ break;
++ }
++ Trace((stderr, "inflate: zlib header ok\n"));
++ z->state->mode = BLOCKS;
++ case BLOCKS:
++ r = inflate_blocks(z->state->blocks, z, r);
++ if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
++ r = inflate_packet_flush(z->state->blocks);
++ if (r == Z_DATA_ERROR)
++ {
++ z->state->mode = BAD;
++ z->state->sub.marker = 0; /* can try inflateSync */
++ break;
++ }
++ if (r != Z_STREAM_END)
++ return r;
++ r = Z_OK;
++ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
++ if (z->state->nowrap)
++ {
++ z->state->mode = DONE;
++ break;
++ }
++ z->state->mode = CHECK4;
++ case CHECK4:
++ NEEDBYTE
++ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
++ z->state->mode = CHECK3;
++ case CHECK3:
++ NEEDBYTE
++ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
++ z->state->mode = CHECK2;
++ case CHECK2:
++ NEEDBYTE
++ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
++ z->state->mode = CHECK1;
++ case CHECK1:
++ NEEDBYTE
++ z->state->sub.check.need += (uLong)NEXTBYTE;
++
++ if (z->state->sub.check.was != z->state->sub.check.need)
++ {
++ z->state->mode = BAD;
++ z->msg = "incorrect data check";
++ z->state->sub.marker = 5; /* can't try inflateSync */
++ break;
++ }
++ Trace((stderr, "inflate: zlib check ok\n"));
++ z->state->mode = DONE;
++ case DONE:
++ return Z_STREAM_END;
++ case BAD:
++ return Z_DATA_ERROR;
++ default:
++ return Z_STREAM_ERROR;
++ }
++
++ empty:
++ if (f != Z_PACKET_FLUSH)
++ return r;
++ z->state->mode = BAD;
++ z->state->sub.marker = 0; /* can try inflateSync */
++ return Z_DATA_ERROR;
++}
++
++/*
++ * 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 inflateIncomp(z)
++z_stream *z;
++{
++ if (z->state->mode != BLOCKS)
++ return Z_DATA_ERROR;
++ return inflate_addhistory(z->state->blocks, z);
++}
++
++
++int inflateSync(z)
++z_stream *z;
++{
++ uInt n; /* number of bytes to look at */
++ Bytef *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 == Z_NULL || z->state == Z_NULL)
++ return Z_STREAM_ERROR;
++ if (z->state->mode != BAD)
++ {
++ z->state->mode = 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)
++ {
++ if (*p == (Byte)(m < 2 ? 0 : 0xff))
++ 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;
++ inflateReset(z);
++ z->total_in = r; z->total_out = w;
++ z->state->mode = BLOCKS;
++ return Z_OK;
++}
++
++#undef NEEDBYTE
++#undef NEXTBYTE
++
++/*+++++*/
++/* infutil.h -- types and macros common to blocks and codes
++ * Copyright (C) 1995 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++ part of the implementation of the compression library and is
++ subject to change. Applications should only use zlib.h.
++ */
++
++/* inflate blocks semi-private state */
++struct inflate_blocks_state {
++
++ /* mode */
++ enum {
++ TYPE, /* get type bits (3, including end bit) */
++ LENS, /* get lengths for stored */
++ STORED, /* processing stored block */
++ TABLE, /* get table lengths */
++ BTREE, /* get bit lengths tree for a dynamic block */
++ DTREE, /* get length, distance trees for a dynamic block */
++ CODES, /* processing fixed or dynamic block */
++ DRY, /* output remaining window bytes */
++ DONEB, /* finished last block, done */
++ BADB} /* got a data error--stuck here */
++ mode; /* current inflate_block mode */
++
++ /* mode dependent information */
++ union {
++ uInt left; /* if STORED, bytes left to copy */
++ struct {
++ uInt table; /* table lengths (14 bits) */
++ uInt index; /* index into blens (or border) */
++ uIntf *blens; /* bit lengths of codes */
++ uInt bb; /* bit length tree depth */
++ inflate_huft *tb; /* bit length decoding tree */
++ int nblens; /* # elements allocated at blens */
++ } trees; /* if DTREE, decoding info for trees */
++ struct {
++ inflate_huft *tl, *td; /* trees to free */
++ inflate_codes_statef
++ *codes;
++ } decode; /* if CODES, current state */
++ } sub; /* submode */
++ uInt last; /* true if this block is the last block */
++
++ /* mode independent information */
++ uInt bitk; /* bits in bit buffer */
++ uLong bitb; /* bit buffer */
++ Bytef *window; /* sliding window */
++ Bytef *end; /* one byte after sliding window */
++ Bytef *read; /* window read pointer */
++ Bytef *write; /* window write pointer */
++ check_func checkfn; /* check function */
++ uLong check; /* check on output */
++
++};
++
++
++/* defines for inflate input/output */
++/* update pointers and return */
++#define UPDBITS {s->bitb=b;s->bitk=k;}
++#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
++#define UPDOUT {s->write=q;}
++#define UPDATE {UPDBITS UPDIN UPDOUT}
++#define LEAVE {UPDATE return inflate_flush(s,z,r);}
++/* get bytes and bits */
++#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
++#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
++#define NEXTBYTE (n--,*p++)
++#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
++#define DUMPBITS(j) {b>>=(j);k-=(j);}
++/* output bytes */
++#define WAVAIL (q<s->read?s->read-q-1:s->end-q)
++#define LOADOUT {q=s->write;m=WAVAIL;}
++#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}}
++#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
++#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
++#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
++/* load local pointers */
++#define LOAD {LOADIN LOADOUT}
++
++/*
++ * The IBM 150 firmware munges the data right after _etext[]. This
++ * protects it. -- Cort
++ */
++local uInt protect_mask[] = {0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0};
++/* And'ing with mask[n] masks the lower n bits */
++local uInt inflate_mask[] = {
++ 0x0000,
++ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
++ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
++};
++
++/* copy as much as possible from the sliding window to the output area */
++local int inflate_flush OF((
++ inflate_blocks_statef *,
++ z_stream *,
++ int));
++
++/*+++++*/
++/* inffast.h -- header to use inffast.c
++ * Copyright (C) 1995 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* WARNING: this file should *not* be used by applications. It is
++ part of the implementation of the compression library and is
++ subject to change. Applications should only use zlib.h.
++ */
++
++local int inflate_fast OF((
++ uInt,
++ uInt,
++ inflate_huft *,
++ inflate_huft *,
++ inflate_blocks_statef *,
++ z_stream *));
++
++
++/*+++++*/
++/* infblock.c -- interpret and process block types to last block
++ * Copyright (C) 1995 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* Table for deflate from PKZIP's appnote.txt. */
++local uInt border[] = { /* Order of the bit length code lengths */
++ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
++
++/*
++ Notes beyond the 1.93a appnote.txt:
++
++ 1. Distance pointers never point before the beginning of the output
++ stream.
++ 2. Distance pointers can point back across blocks, up to 32k away.
++ 3. There is an implied maximum of 7 bits for the bit length table and
++ 15 bits for the actual data.
++ 4. If only one code exists, then it is encoded using one bit. (Zero
++ would be more efficient, but perhaps a little confusing.) If two
++ codes exist, they are coded using one bit each (0 and 1).
++ 5. There is no way of sending zero distance codes--a dummy must be
++ sent if there are none. (History: a pre 2.0 version of PKZIP would
++ store blocks with no distance codes, but this was discovered to be
++ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
++ zero distance codes, which is sent as one code of zero bits in
++ length.
++ 6. There are up to 286 literal/length codes. Code 256 represents the
++ end-of-block. Note however that the static length tree defines
++ 288 codes just to fill out the Huffman codes. Codes 286 and 287
++ cannot be used though, since there is no length base or extra bits
++ defined for them. Similarily, there are up to 30 distance codes.
++ However, static trees define 32 codes (all 5 bits) to fill out the
++ Huffman codes, but the last two had better not show up in the data.
++ 7. Unzip can check dynamic Huffman blocks for complete code sets.
++ The exception is that a single code would not be complete (see #4).
++ 8. The five bits following the block type is really the number of
++ literal codes sent minus 257.
++ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
++ (1+6+6). Therefore, to output three times the length, you output
++ three codes (1+1+1), whereas to output four times the same length,
++ you only need two codes (1+3). Hmm.
++ 10. In the tree reconstruction algorithm, Code = Code + Increment
++ only if BitLength(i) is not zero. (Pretty obvious.)
++ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
++ 12. Note: length code 284 can represent 227-258, but length code 285
++ really is 258. The last length deserves its own, short code
++ since it gets used a lot in very redundant files. The length
++ 258 is special since 258 - 3 (the min match length) is 255.
++ 13. The literal/length and distance code bit lengths are read as a
++ single stream of lengths. It is possible (and advantageous) for
++ a repeat code (16, 17, or 18) to go across the boundary between
++ the two sets of lengths.
++ */
++
++
++local void inflate_blocks_reset(s, z, c)
++inflate_blocks_statef *s;
++z_stream *z;
++uLongf *c;
++{
++ if (s->checkfn != Z_NULL)
++ *c = s->check;
++ if (s->mode == BTREE || s->mode == DTREE)
++ ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
++ if (s->mode == CODES)
++ {
++ inflate_codes_free(s->sub.decode.codes, z);
++ inflate_trees_free(s->sub.decode.td, z);
++ inflate_trees_free(s->sub.decode.tl, z);
++ }
++ s->mode = TYPE;
++ s->bitk = 0;
++ s->bitb = 0;
++ s->read = s->write = s->window;
++ if (s->checkfn != Z_NULL)
++ s->check = (*s->checkfn)(0L, Z_NULL, 0);
++ Trace((stderr, "inflate: blocks reset\n"));
++}
++
++
++local inflate_blocks_statef *inflate_blocks_new(z, c, w)
++z_stream *z;
++check_func c;
++uInt w;
++{
++ inflate_blocks_statef *s;
++
++ if ((s = (inflate_blocks_statef *)ZALLOC
++ (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
++ return s;
++ if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
++ {
++ ZFREE(z, s, sizeof(struct inflate_blocks_state));
++ return Z_NULL;
++ }
++ s->end = s->window + w;
++ s->checkfn = c;
++ s->mode = TYPE;
++ Trace((stderr, "inflate: blocks allocated\n"));
++ inflate_blocks_reset(s, z, &s->check);
++ return s;
++}
++
++
++local int inflate_blocks(s, z, r)
++inflate_blocks_statef *s;
++z_stream *z;
++int r;
++{
++ uInt t; /* temporary storage */
++ uLong b; /* bit buffer */
++ uInt k; /* bits in bit buffer */
++ Bytef *p; /* input data pointer */
++ uInt n; /* bytes available there */
++ Bytef *q; /* output window write pointer */
++ uInt m; /* bytes to end of window or read pointer */
++
++ /* copy input/output information to locals (UPDATE macro restores) */
++ LOAD
++
++ /* process input based on current state */
++ while (1) switch (s->mode)
++ {
++ case TYPE:
++ NEEDBITS(3)
++ t = (uInt)b & 7;
++ s->last = t & 1;
++ switch (t >> 1)
++ {
++ case 0: /* stored */
++ Trace((stderr, "inflate: stored block%s\n",
++ s->last ? " (last)" : ""));
++ DUMPBITS(3)
++ t = k & 7; /* go to byte boundary */
++ DUMPBITS(t)
++ s->mode = LENS; /* get length of stored block */
++ break;
++ case 1: /* fixed */
++ Trace((stderr, "inflate: fixed codes block%s\n",
++ s->last ? " (last)" : ""));
++ {
++ uInt bl, bd;
++ inflate_huft *tl, *td;
++
++ inflate_trees_fixed(&bl, &bd, &tl, &td);
++ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
++ if (s->sub.decode.codes == Z_NULL)
++ {
++ r = Z_MEM_ERROR;
++ LEAVE
++ }
++ s->sub.decode.tl = Z_NULL; /* don't try to free these */
++ s->sub.decode.td = Z_NULL;
++ }
++ DUMPBITS(3)
++ s->mode = CODES;
++ break;
++ case 2: /* dynamic */
++ Trace((stderr, "inflate: dynamic codes block%s\n",
++ s->last ? " (last)" : ""));
++ DUMPBITS(3)
++ s->mode = TABLE;
++ break;
++ case 3: /* illegal */
++ DUMPBITS(3)
++ s->mode = BADB;
++ z->msg = "invalid block type";
++ r = Z_DATA_ERROR;
++ LEAVE
++ }
++ break;
++ case LENS:
++ NEEDBITS(32)
++ if (((~b) >> 16) != (b & 0xffff))
++ {
++ s->mode = BADB;
++ z->msg = "invalid stored block lengths";
++ r = Z_DATA_ERROR;
++ LEAVE
++ }
++ s->sub.left = (uInt)b & 0xffff;
++ b = k = 0; /* dump bits */
++ Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
++ s->mode = s->sub.left ? STORED : TYPE;
++ break;
++ case STORED:
++ if (n == 0)
++ LEAVE
++ NEEDOUT
++ t = s->sub.left;
++ if (t > n) t = n;
++ if (t > m) t = m;
++ zmemcpy(q, p, t);
++ p += t; n -= t;
++ q += t; m -= t;
++ if ((s->sub.left -= t) != 0)
++ break;
++ Tracev((stderr, "inflate: stored end, %lu total out\n",
++ z->total_out + (q >= s->read ? q - s->read :
++ (s->end - s->read) + (q - s->window))));
++ s->mode = s->last ? DRY : TYPE;
++ break;
++ case TABLE:
++ NEEDBITS(14)
++ s->sub.trees.table = t = (uInt)b & 0x3fff;
++#ifndef PKZIP_BUG_WORKAROUND
++ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
++ {
++ s->mode = BADB;
++ z->msg = "too many length or distance symbols";
++ r = Z_DATA_ERROR;
++ LEAVE
++ }
++#endif
++ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
++ if (t < 19)
++ t = 19;
++ if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
++ {
++ r = Z_MEM_ERROR;
++ LEAVE
++ }
++ s->sub.trees.nblens = t;
++ DUMPBITS(14)
++ s->sub.trees.index = 0;
++ Tracev((stderr, "inflate: table sizes ok\n"));
++ s->mode = BTREE;
++ case BTREE:
++ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
++ {
++ NEEDBITS(3)
++ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
++ DUMPBITS(3)
++ }
++ while (s->sub.trees.index < 19)
++ s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
++ s->sub.trees.bb = 7;
++ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
++ &s->sub.trees.tb, z);
++ if (t != Z_OK)
++ {
++ r = t;
++ if (r == Z_DATA_ERROR)
++ s->mode = BADB;
++ LEAVE
++ }
++ s->sub.trees.index = 0;
++ Tracev((stderr, "inflate: bits tree ok\n"));
++ s->mode = DTREE;
++ case DTREE:
++ while (t = s->sub.trees.table,
++ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
++ {
++ inflate_huft *h;
++ uInt i, j, c;
++
++ t = s->sub.trees.bb;
++ NEEDBITS(t)
++ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
++ t = h->word.what.Bits;
++ c = h->more.Base;
++ if (c < 16)
++ {
++ DUMPBITS(t)
++ s->sub.trees.blens[s->sub.trees.index++] = c;
++ }
++ else /* c == 16..18 */
++ {
++ i = c == 18 ? 7 : c - 14;
++ j = c == 18 ? 11 : 3;
++ NEEDBITS(t + i)
++ DUMPBITS(t)
++ j += (uInt)b & inflate_mask[i];
++ DUMPBITS(i)
++ i = s->sub.trees.index;
++ t = s->sub.trees.table;
++ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
++ (c == 16 && i < 1))
++ {
++ s->mode = BADB;
++ z->msg = "invalid bit length repeat";
++ r = Z_DATA_ERROR;
++ LEAVE
++ }
++ c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
++ do {
++ s->sub.trees.blens[i++] = c;
++ } while (--j);
++ s->sub.trees.index = i;
++ }
++ }
++ inflate_trees_free(s->sub.trees.tb, z);
++ s->sub.trees.tb = Z_NULL;
++ {
++ uInt bl, bd;
++ inflate_huft *tl, *td;
++ inflate_codes_statef *c;
++
++ bl = 9; /* must be <= 9 for lookahead assumptions */
++ bd = 6; /* must be <= 9 for lookahead assumptions */
++ t = s->sub.trees.table;
++ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
++ s->sub.trees.blens, &bl, &bd, &tl, &td, z);
++ if (t != Z_OK)
++ {
++ if (t == (uInt)Z_DATA_ERROR)
++ s->mode = BADB;
++ r = t;
++ LEAVE
++ }
++ Tracev((stderr, "inflate: trees ok\n"));
++ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
++ {
++ inflate_trees_free(td, z);
++ inflate_trees_free(tl, z);
++ r = Z_MEM_ERROR;
++ LEAVE
++ }
++ ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
++ s->sub.decode.codes = c;
++ s->sub.decode.tl = tl;
++ s->sub.decode.td = td;
++ }
++ s->mode = CODES;
++ case CODES:
++ UPDATE
++ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
++ return inflate_flush(s, z, r);
++ r = Z_OK;
++ inflate_codes_free(s->sub.decode.codes, z);
++ inflate_trees_free(s->sub.decode.td, z);
++ inflate_trees_free(s->sub.decode.tl, z);
++ LOAD
++ Tracev((stderr, "inflate: codes end, %lu total out\n",
++ z->total_out + (q >= s->read ? q - s->read :
++ (s->end - s->read) + (q - s->window))));
++ if (!s->last)
++ {
++ s->mode = TYPE;
++ break;
++ }
++ if (k > 7) /* return unused byte, if any */
++ {
++ Assert(k < 16, "inflate_codes grabbed too many bytes")
++ k -= 8;
++ n++;
++ p--; /* can always return one */
++ }
++ s->mode = DRY;
++ case DRY:
++ FLUSH
++ if (s->read != s->write)
++ LEAVE
++ s->mode = DONEB;
++ case DONEB:
++ r = Z_STREAM_END;
++ LEAVE
++ case BADB:
++ r = Z_DATA_ERROR;
++ LEAVE
++ default:
++ r = Z_STREAM_ERROR;
++ LEAVE
++ }
++}
++
++
++local int inflate_blocks_free(s, z, c)
++inflate_blocks_statef *s;
++z_stream *z;
++uLongf *c;
++{
++ inflate_blocks_reset(s, z, c);
++ ZFREE(z, s->window, s->end - s->window);
++ ZFREE(z, s, sizeof(struct inflate_blocks_state));
++ Trace((stderr, "inflate: blocks freed\n"));
++ 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.
++ */
++local int inflate_addhistory(s, z)
++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 */
++ Bytef *p; /* input data pointer */
++ uInt n; /* bytes available there */
++ Bytef *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 != Z_NULL)
++ s->check = (*s->checkfn)(s->check, q, t);
++ zmemcpy(q, p, t);
++ q += t;
++ p += t;
++ n -= t;
++ z->total_out += t;
++ s->read = q; /* drag read pointer forward */
++/* WRAP */ /* expand WRAP macro by hand to handle s->read */
++ if (q == s->end) {
++ s->read = q = s->window;
++ m = WAVAIL;
++ }
++ }
++ UPDATE
++ return Z_OK;
++}
++
++
++/*
++ * At the end of a Deflate-compressed PPP packet, we expect to have seen
++ * a `stored' block type value but not the (zero) length bytes.
++ */
++local int inflate_packet_flush(s)
++ inflate_blocks_statef *s;
++{
++ if (s->mode != LENS)
++ return Z_DATA_ERROR;
++ s->mode = TYPE;
++ return Z_OK;
++}
++
++
++/*+++++*/
++/* inftrees.c -- generate Huffman trees for efficient decoding
++ * Copyright (C) 1995 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* simplify the use of the inflate_huft type with some defines */
++#define base more.Base
++#define next more.Next
++#define exop word.what.Exop
++#define bits word.what.Bits
++
++
++local int huft_build OF((
++ uIntf *, /* code lengths in bits */
++ uInt, /* number of codes */
++ uInt, /* number of "simple" codes */
++ uIntf *, /* list of base values for non-simple codes */
++ uIntf *, /* list of extra bits for non-simple codes */
++ inflate_huft * FAR*,/* result: starting table */
++ uIntf *, /* maximum lookup bits (returns actual) */
++ z_stream *)); /* for zalloc function */
++
++local voidpf falloc OF((
++ voidpf, /* opaque pointer (not used) */
++ uInt, /* number of items */
++ uInt)); /* size of item */
++
++local void ffree OF((
++ voidpf q, /* opaque pointer (not used) */
++ voidpf p, /* what to free (not used) */
++ uInt n)); /* number of bytes (not used) */
++
++/* Tables for deflate from PKZIP's appnote.txt. */
++local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */
++ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
++ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
++ /* actually lengths - 2; also see note #13 above about 258 */
++local uInt cplext[] = { /* Extra bits for literal codes 257..285 */
++ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
++ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */
++local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */
++ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
++ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
++ 8193, 12289, 16385, 24577};
++local uInt cpdext[] = { /* Extra bits for distance codes */
++ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
++ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
++ 12, 12, 13, 13};
++
++/*
++ Huffman code decoding is performed using a multi-level table lookup.
++ The fastest way to decode is to simply build a lookup table whose
++ size is determined by the longest code. However, the time it takes
++ to build this table can also be a factor if the data being decoded
++ is not very long. The most common codes are necessarily the
++ shortest codes, so those codes dominate the decoding time, and hence
++ the speed. The idea is you can have a shorter table that decodes the
++ shorter, more probable codes, and then point to subsidiary tables for
++ the longer codes. The time it costs to decode the longer codes is
++ then traded against the time it takes to make longer tables.
++
++ This results of this trade are in the variables lbits and dbits
++ below. lbits is the number of bits the first level table for literal/
++ length codes can decode in one step, and dbits is the same thing for
++ the distance codes. Subsequent tables are also less than or equal to
++ those sizes. These values may be adjusted either when all of the
++ codes are shorter than that, in which case the longest code length in
++ bits is used, or when the shortest code is *longer* than the requested
++ table size, in which case the length of the shortest code in bits is
++ used.
++
++ There are two different values for the two tables, since they code a
++ different number of possibilities each. The literal/length table
++ codes 286 possible values, or in a flat code, a little over eight
++ bits. The distance table codes 30 possible values, or a little less
++ than five bits, flat. The optimum values for speed end up being
++ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
++ The optimum values may differ though from machine to machine, and
++ possibly even between compilers. Your mileage may vary.
++ */
++
++
++/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
++#define BMAX 15 /* maximum bit length of any code */
++#define N_MAX 288 /* maximum number of codes in any set */
++
++#ifdef DEBUG_ZLIB
++ uInt inflate_hufts;
++#endif
++
++local int huft_build(b, n, s, d, e, t, m, zs)
++uIntf *b; /* code lengths in bits (all assumed <= BMAX) */
++uInt n; /* number of codes (assumed <= N_MAX) */
++uInt s; /* number of simple-valued codes (0..s-1) */
++uIntf *d; /* list of base values for non-simple codes */
++uIntf *e; /* list of extra bits for non-simple codes */
++inflate_huft * FAR *t; /* result: starting table */
++uIntf *m; /* maximum lookup bits, returns actual */
++z_stream *zs; /* for zalloc function */
++/* Given a list of code lengths and a maximum table size, make a set of
++ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
++ if the given code set is incomplete (the tables are still built in this
++ case), Z_DATA_ERROR if the input is invalid (all zero length codes or an
++ over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */
++{
++
++ uInt a; /* counter for codes of length k */
++ uInt c[BMAX+1]; /* bit length count table */
++ uInt f; /* i repeats in table every f entries */
++ int g; /* maximum code length */
++ int h; /* table level */
++ register uInt i; /* counter, current code */
++ register uInt j; /* counter */
++ register int k; /* number of bits in current code */
++ int l; /* bits per table (returned in m) */
++ register uIntf *p; /* pointer into c[], b[], or v[] */
++ inflate_huft *q; /* points to current table */
++ struct inflate_huft_s r; /* table entry for structure assignment */
++ inflate_huft *u[BMAX]; /* table stack */
++ uInt v[N_MAX]; /* values in order of bit length */
++ register int w; /* bits before this table == (l * h) */
++ uInt x[BMAX+1]; /* bit offsets, then code stack */
++ uIntf *xp; /* pointer into x */
++ int y; /* number of dummy codes added */
++ uInt z; /* number of entries in current table */
++
++
++ /* Generate counts for each bit length */
++ p = c;
++#define C0 *p++ = 0;
++#define C2 C0 C0 C0 C0
++#define C4 C2 C2 C2 C2
++ C4 /* clear c[]--assume BMAX+1 is 16 */
++ p = b; i = n;
++ do {
++ c[*p++]++; /* assume all entries <= BMAX */
++ } while (--i);
++ if (c[0] == n) /* null input--all zero length codes */
++ {
++ *t = (inflate_huft *)Z_NULL;
++ *m = 0;
++ return Z_OK;
++ }
++
++
++ /* 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 ((uInt)l < j)
++ l = j;
++ for (i = BMAX; i; i--)
++ if (c[i])
++ break;
++ g = i; /* maximum code length */
++ if ((uInt)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 Z_DATA_ERROR;
++ if ((y -= c[i]) < 0)
++ return Z_DATA_ERROR;
++ 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] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
++ q = (inflate_huft *)Z_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 = g - w) > (uInt)l ? l : z; /* table size upper limit */
++ 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;
++ if (j < z)
++ 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 */
++ if ((q = (inflate_huft *)ZALLOC
++ (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
++ {
++ if (h)
++ inflate_trees_free(u[0], zs);
++ return Z_MEM_ERROR; /* not enough memory */
++ }
++ q->word.Nalloc = z + 1;
++#ifdef DEBUG_ZLIB
++ inflate_hufts += z + 1;
++#endif
++ *t = q + 1; /* link to list for huft_free() */
++ *(t = &(q->next)) = Z_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.bits = (Byte)l; /* bits to dump before this table */
++ r.exop = (Byte)j; /* bits in this table */
++ r.next = 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.bits = (Byte)(k - w);
++ if (p >= v + n)
++ r.exop = 128 + 64; /* out of values--invalid code */
++ else if (*p < s)
++ {
++ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
++ r.base = *p++; /* simple code is just the value */
++ }
++ else
++ {
++ r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */
++ r.base = 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 Z_BUF_ERROR if we were given an incomplete table */
++ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
++}
++
++
++local int inflate_trees_bits(c, bb, tb, z)
++uIntf *c; /* 19 code lengths */
++uIntf *bb; /* bits tree desired/actual depth */
++inflate_huft * FAR *tb; /* bits tree result */
++z_stream *z; /* for zfree function */
++{
++ int r;
++
++ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
++ if (r == Z_DATA_ERROR)
++ z->msg = "oversubscribed dynamic bit lengths tree";
++ else if (r == Z_BUF_ERROR)
++ {
++ inflate_trees_free(*tb, z);
++ z->msg = "incomplete dynamic bit lengths tree";
++ r = Z_DATA_ERROR;
++ }
++ return r;
++}
++
++
++local int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z)
++uInt nl; /* number of literal/length codes */
++uInt nd; /* number of distance codes */
++uIntf *c; /* that many (total) code lengths */
++uIntf *bl; /* literal desired/actual bit depth */
++uIntf *bd; /* distance desired/actual bit depth */
++inflate_huft * FAR *tl; /* literal/length tree result */
++inflate_huft * FAR *td; /* distance tree result */
++z_stream *z; /* for zfree function */
++{
++ int r;
++
++ /* build literal/length tree */
++ if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK)
++ {
++ if (r == Z_DATA_ERROR)
++ z->msg = "oversubscribed literal/length tree";
++ else if (r == Z_BUF_ERROR)
++ {
++ inflate_trees_free(*tl, z);
++ z->msg = "incomplete literal/length tree";
++ r = Z_DATA_ERROR;
++ }
++ return r;
++ }
++
++ /* build distance tree */
++ if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK)
++ {
++ if (r == Z_DATA_ERROR)
++ z->msg = "oversubscribed literal/length tree";
++ else if (r == Z_BUF_ERROR) {
++#ifdef PKZIP_BUG_WORKAROUND
++ r = Z_OK;
++ }
++#else
++ inflate_trees_free(*td, z);
++ z->msg = "incomplete literal/length tree";
++ r = Z_DATA_ERROR;
++ }
++ inflate_trees_free(*tl, z);
++ return r;
++#endif
++ }
++
++ /* done */
++ return Z_OK;
++}
++
++
++/* build fixed tables only once--keep them here */
++local int fixed_lock = 0;
++local int fixed_built = 0;
++#define FIXEDH 530 /* number of hufts used by fixed tables */
++local uInt fixed_left = FIXEDH;
++local inflate_huft fixed_mem[FIXEDH];
++local uInt fixed_bl;
++local uInt fixed_bd;
++local inflate_huft *fixed_tl;
++local inflate_huft *fixed_td;
++
++
++local voidpf falloc(q, n, s)
++voidpf q; /* opaque pointer (not used) */
++uInt n; /* number of items */
++uInt s; /* size of item */
++{
++ Assert(s == sizeof(inflate_huft) && n <= fixed_left,
++ "inflate_trees falloc overflow");
++ if (q) s++; /* to make some compilers happy */
++ fixed_left -= n;
++ return (voidpf)(fixed_mem + fixed_left);
++}
++
++
++local void ffree(q, p, n)
++voidpf q;
++voidpf p;
++uInt n;
++{
++ Assert(0, "inflate_trees ffree called!");
++ if (q) q = p; /* to make some compilers happy */
++}
++
++
++local int inflate_trees_fixed(bl, bd, tl, td)
++uIntf *bl; /* literal desired/actual bit depth */
++uIntf *bd; /* distance desired/actual bit depth */
++inflate_huft * FAR *tl; /* literal/length tree result */
++inflate_huft * FAR *td; /* distance tree result */
++{
++ /* build fixed tables if not built already--lock out other instances */
++ while (++fixed_lock > 1)
++ fixed_lock--;
++ if (!fixed_built)
++ {
++ int k; /* temporary variable */
++ unsigned c[288]; /* length list for huft_build */
++ z_stream z; /* for falloc function */
++
++ /* set up fake z_stream for memory routines */
++ z.zalloc = falloc;
++ z.zfree = ffree;
++ z.opaque = Z_NULL;
++
++ /* literal table */
++ for (k = 0; k < 144; k++)
++ c[k] = 8;
++ for (; k < 256; k++)
++ c[k] = 9;
++ for (; k < 280; k++)
++ c[k] = 7;
++ for (; k < 288; k++)
++ c[k] = 8;
++ fixed_bl = 7;
++ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
++
++ /* distance table */
++ for (k = 0; k < 30; k++)
++ c[k] = 5;
++ fixed_bd = 5;
++ huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
++
++ /* done */
++ fixed_built = 1;
++ }
++ fixed_lock--;
++ *bl = fixed_bl;
++ *bd = fixed_bd;
++ *tl = fixed_tl;
++ *td = fixed_td;
++ return Z_OK;
++}
++
++
++local int inflate_trees_free(t, z)
++inflate_huft *t; /* table to free */
++z_stream *z; /* for zfree function */
++/* Free the malloc'ed tables built by huft_build(), which makes a linked
++ list of the tables it made, with the links in a dummy first entry of
++ each table. */
++{
++ register inflate_huft *p, *q;
++
++ /* Go through linked list, freeing from the malloced (t[-1]) address. */
++ p = t;
++ while (p != Z_NULL)
++ {
++ q = (--p)->next;
++ ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft));
++ p = q;
++ }
++ return Z_OK;
++}
++
++/*+++++*/
++/* infcodes.c -- process literals and length/distance pairs
++ * Copyright (C) 1995 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* simplify the use of the inflate_huft type with some defines */
++#define base more.Base
++#define next more.Next
++#define exop word.what.Exop
++#define bits word.what.Bits
++
++/* inflate codes private state */
++struct inflate_codes_state {
++
++ /* mode */
++ enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
++ START, /* x: set up for LEN */
++ LEN, /* i: get length/literal/eob next */
++ LENEXT, /* i: getting length extra (have base) */
++ DIST, /* i: get distance next */
++ DISTEXT, /* i: getting distance extra */
++ COPY, /* o: copying bytes in window, waiting for space */
++ LIT, /* o: got literal, waiting for output space */
++ WASH, /* o: got eob, possibly still output waiting */
++ END, /* x: got eob and all data flushed */
++ BADCODE} /* x: got error */
++ mode; /* current inflate_codes mode */
++
++ /* mode dependent information */
++ uInt len;
++ union {
++ struct {
++ inflate_huft *tree; /* pointer into tree */
++ uInt need; /* bits needed */
++ } code; /* if LEN or DIST, where in tree */
++ uInt lit; /* if LIT, literal */
++ struct {
++ uInt get; /* bits to get for extra */
++ uInt dist; /* distance back to copy from */
++ } copy; /* if EXT or COPY, where and how much */
++ } sub; /* submode */
++
++ /* mode independent information */
++ Byte lbits; /* ltree bits decoded per branch */
++ Byte dbits; /* dtree bits decoder per branch */
++ inflate_huft *ltree; /* literal/length/eob tree */
++ inflate_huft *dtree; /* distance tree */
++
++};
++
++
++local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
++uInt bl, bd;
++inflate_huft *tl, *td;
++z_stream *z;
++{
++ inflate_codes_statef *c;
++
++ if ((c = (inflate_codes_statef *)
++ ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
++ {
++ c->mode = START;
++ c->lbits = (Byte)bl;
++ c->dbits = (Byte)bd;
++ c->ltree = tl;
++ c->dtree = td;
++ Tracev((stderr, "inflate: codes new\n"));
++ }
++ return c;
++}
++
++
++local int inflate_codes(s, z, r)
++inflate_blocks_statef *s;
++z_stream *z;
++int r;
++{
++ uInt j; /* temporary storage */
++ inflate_huft *t; /* temporary pointer */
++ uInt e; /* extra bits or operation */
++ uLong b; /* bit buffer */
++ uInt k; /* bits in bit buffer */
++ Bytef *p; /* input data pointer */
++ uInt n; /* bytes available there */
++ Bytef *q; /* output window write pointer */
++ uInt m; /* bytes to end of window or read pointer */
++ Bytef *f; /* pointer to copy strings from */
++ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
++
++ /* copy input/output information to locals (UPDATE macro restores) */
++ LOAD
++
++ /* process input and output based on current state */
++ while (1) switch (c->mode)
++ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
++ case START: /* x: set up for LEN */
++#ifndef SLOW
++ if (m >= 258 && n >= 10)
++ {
++ UPDATE
++ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
++ LOAD
++ if (r != Z_OK)
++ {
++ c->mode = r == Z_STREAM_END ? WASH : BADCODE;
++ break;
++ }
++ }
++#endif /* !SLOW */
++ c->sub.code.need = c->lbits;
++ c->sub.code.tree = c->ltree;
++ c->mode = LEN;
++ case LEN: /* i: get length/literal/eob next */
++ j = c->sub.code.need;
++ NEEDBITS(j)
++ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
++ DUMPBITS(t->bits)
++ e = (uInt)(t->exop);
++ if (e == 0) /* literal */
++ {
++ c->sub.lit = t->base;
++ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
++ "inflate: literal '%c'\n" :
++ "inflate: literal 0x%02x\n", t->base));
++ c->mode = LIT;
++ break;
++ }
++ if (e & 16) /* length */
++ {
++ c->sub.copy.get = e & 15;
++ c->len = t->base;
++ c->mode = LENEXT;
++ break;
++ }
++ if ((e & 64) == 0) /* next table */
++ {
++ c->sub.code.need = e;
++ c->sub.code.tree = t->next;
++ break;
++ }
++ if (e & 32) /* end of block */
++ {
++ Tracevv((stderr, "inflate: end of block\n"));
++ c->mode = WASH;
++ break;
++ }
++ c->mode = BADCODE; /* invalid code */
++ z->msg = "invalid literal/length code";
++ r = Z_DATA_ERROR;
++ LEAVE
++ case LENEXT: /* i: getting length extra (have base) */
++ j = c->sub.copy.get;
++ NEEDBITS(j)
++ c->len += (uInt)b & inflate_mask[j];
++ DUMPBITS(j)
++ c->sub.code.need = c->dbits;
++ c->sub.code.tree = c->dtree;
++ Tracevv((stderr, "inflate: length %u\n", c->len));
++ c->mode = DIST;
++ case DIST: /* i: get distance next */
++ j = c->sub.code.need;
++ NEEDBITS(j)
++ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
++ DUMPBITS(t->bits)
++ e = (uInt)(t->exop);
++ if (e & 16) /* distance */
++ {
++ c->sub.copy.get = e & 15;
++ c->sub.copy.dist = t->base;
++ c->mode = DISTEXT;
++ break;
++ }
++ if ((e & 64) == 0) /* next table */
++ {
++ c->sub.code.need = e;
++ c->sub.code.tree = t->next;
++ break;
++ }
++ c->mode = BADCODE; /* invalid code */
++ z->msg = "invalid distance code";
++ r = Z_DATA_ERROR;
++ LEAVE
++ case DISTEXT: /* i: getting distance extra */
++ j = c->sub.copy.get;
++ NEEDBITS(j)
++ c->sub.copy.dist += (uInt)b & inflate_mask[j];
++ DUMPBITS(j)
++ Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
++ c->mode = COPY;
++ case COPY: /* o: copying bytes in window, waiting for space */
++#ifndef __TURBOC__ /* Turbo C bug for following expression */
++ f = (uInt)(q - s->window) < c->sub.copy.dist ?
++ s->end - (c->sub.copy.dist - (q - s->window)) :
++ q - c->sub.copy.dist;
++#else
++ f = q - c->sub.copy.dist;
++ if ((uInt)(q - s->window) < c->sub.copy.dist)
++ f = s->end - (c->sub.copy.dist - (q - s->window));
++#endif
++ while (c->len)
++ {
++ NEEDOUT
++ OUTBYTE(*f++)
++ if (f == s->end)
++ f = s->window;
++ c->len--;
++ }
++ c->mode = START;
++ break;
++ case LIT: /* o: got literal, waiting for output space */
++ NEEDOUT
++ OUTBYTE(c->sub.lit)
++ c->mode = START;
++ break;
++ case WASH: /* o: got eob, possibly more output */
++ FLUSH
++ if (s->read != s->write)
++ LEAVE
++ c->mode = END;
++ case END:
++ r = Z_STREAM_END;
++ LEAVE
++ case BADCODE: /* x: got error */
++ r = Z_DATA_ERROR;
++ LEAVE
++ default:
++ r = Z_STREAM_ERROR;
++ LEAVE
++ }
++}
++
++
++local void inflate_codes_free(c, z)
++inflate_codes_statef *c;
++z_stream *z;
++{
++ ZFREE(z, c, sizeof(struct inflate_codes_state));
++ Tracev((stderr, "inflate: codes free\n"));
++}
++
++/*+++++*/
++/* inflate_util.c -- data and routines common to blocks and codes
++ * Copyright (C) 1995 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* copy as much as possible from the sliding window to the output area */
++local int inflate_flush(s, z, r)
++inflate_blocks_statef *s;
++z_stream *z;
++int r;
++{
++ uInt n;
++ Bytef *p, *q;
++
++ /* local copies of source and destination pointers */
++ p = z->next_out;
++ q = s->read;
++
++ /* compute number of bytes to copy as far as end of window */
++ n = (uInt)((q <= s->write ? s->write : s->end) - q);
++ if (n > z->avail_out) n = z->avail_out;
++ if (n && r == Z_BUF_ERROR) r = Z_OK;
++
++ /* update counters */
++ z->avail_out -= n;
++ z->total_out += n;
++
++ /* update check information */
++ if (s->checkfn != Z_NULL)
++ s->check = (*s->checkfn)(s->check, q, n);
++
++ /* copy as far as end of window */
++ zmemcpy(p, q, n);
++ p += n;
++ q += n;
++
++ /* see if more to copy at beginning of window */
++ if (q == s->end)
++ {
++ /* wrap pointers */
++ q = s->window;
++ if (s->write == s->end)
++ s->write = s->window;
++
++ /* compute bytes to copy */
++ n = (uInt)(s->write - q);
++ if (n > z->avail_out) n = z->avail_out;
++ if (n && r == Z_BUF_ERROR) r = Z_OK;
++
++ /* update counters */
++ z->avail_out -= n;
++ z->total_out += n;
++
++ /* update check information */
++ if (s->checkfn != Z_NULL)
++ s->check = (*s->checkfn)(s->check, q, n);
++
++ /* copy */
++ zmemcpy(p, q, n);
++ p += n;
++ q += n;
++ }
++
++ /* update pointers */
++ z->next_out = p;
++ s->read = q;
++
++ /* done */
++ return r;
++}
++
++
++/*+++++*/
++/* inffast.c -- process literals and length/distance pairs fast
++ * Copyright (C) 1995 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* simplify the use of the inflate_huft type with some defines */
++#define base more.Base
++#define next more.Next
++#define exop word.what.Exop
++#define bits word.what.Bits
++
++/* macros for bit input with no checking and for returning unused bytes */
++#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
++#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
++
++/* Called with number of bytes left to write in window at least 258
++ (the maximum string length) and number of input bytes available
++ at least ten. The ten bytes are six bytes for the longest length/
++ distance pair plus four bytes for overloading the bit buffer. */
++
++local int inflate_fast(bl, bd, tl, td, s, z)
++uInt bl, bd;
++inflate_huft *tl, *td;
++inflate_blocks_statef *s;
++z_stream *z;
++{
++ inflate_huft *t; /* temporary pointer */
++ uInt e; /* extra bits or operation */
++ uLong b; /* bit buffer */
++ uInt k; /* bits in bit buffer */
++ Bytef *p; /* input data pointer */
++ uInt n; /* bytes available there */
++ Bytef *q; /* output window write pointer */
++ uInt m; /* bytes to end of window or read pointer */
++ uInt ml; /* mask for literal/length tree */
++ uInt md; /* mask for distance tree */
++ uInt c; /* bytes to copy */
++ uInt d; /* distance back to copy from */
++ Bytef *r; /* copy source pointer */
++
++ /* load input, output, bit values */
++ LOAD
++
++ /* initialize masks */
++ ml = inflate_mask[bl];
++ md = inflate_mask[bd];
++
++ /* do until not enough input or output space for fast loop */
++ do { /* assume called with m >= 258 && n >= 10 */
++ /* get literal/length code */
++ GRABBITS(20) /* max bits for literal/length code */
++ if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
++ {
++ DUMPBITS(t->bits)
++ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
++ "inflate: * literal '%c'\n" :
++ "inflate: * literal 0x%02x\n", t->base));
++ *q++ = (Byte)t->base;
++ m--;
++ continue;
++ }
++ do {
++ DUMPBITS(t->bits)
++ if (e & 16)
++ {
++ /* get extra bits for length */
++ e &= 15;
++ c = t->base + ((uInt)b & inflate_mask[e]);
++ DUMPBITS(e)
++ Tracevv((stderr, "inflate: * length %u\n", c));
++
++ /* decode distance base of block to copy */
++ GRABBITS(15); /* max bits for distance code */
++ e = (t = td + ((uInt)b & md))->exop;
++ do {
++ DUMPBITS(t->bits)
++ if (e & 16)
++ {
++ /* get extra bits to add to distance base */
++ e &= 15;
++ GRABBITS(e) /* get extra bits (up to 13) */
++ d = t->base + ((uInt)b & inflate_mask[e]);
++ DUMPBITS(e)
++ Tracevv((stderr, "inflate: * distance %u\n", d));
++
++ /* do the copy */
++ m -= c;
++ if ((uInt)(q - s->window) >= d) /* offset before dest */
++ { /* just copy */
++ r = q - d;
++ *q++ = *r++; c--; /* minimum count is three, */
++ *q++ = *r++; c--; /* so unroll loop a little */
++ }
++ else /* else offset after destination */
++ {
++ e = d - (q - s->window); /* bytes from offset to end */
++ r = s->end - e; /* pointer to offset */
++ if (c > e) /* if source crosses, */
++ {
++ c -= e; /* copy to end of window */
++ do {
++ *q++ = *r++;
++ } while (--e);
++ r = s->window; /* copy rest from start of window */
++ }
++ }
++ do { /* copy all or what's left */
++ *q++ = *r++;
++ } while (--c);
++ break;
++ }
++ else if ((e & 64) == 0)
++ e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
++ else
++ {
++ z->msg = "invalid distance code";
++ UNGRAB
++ UPDATE
++ return Z_DATA_ERROR;
++ }
++ } while (1);
++ break;
++ }
++ if ((e & 64) == 0)
++ {
++ if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
++ {
++ DUMPBITS(t->bits)
++ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
++ "inflate: * literal '%c'\n" :
++ "inflate: * literal 0x%02x\n", t->base));
++ *q++ = (Byte)t->base;
++ m--;
++ break;
++ }
++ }
++ else if (e & 32)
++ {
++ Tracevv((stderr, "inflate: * end of block\n"));
++ UNGRAB
++ UPDATE
++ return Z_STREAM_END;
++ }
++ else
++ {
++ z->msg = "invalid literal/length code";
++ UNGRAB
++ UPDATE
++ return Z_DATA_ERROR;
++ }
++ } while (1);
++ } while (m >= 258 && n >= 10);
++
++ /* not enough input or output--restore pointers and return */
++ UNGRAB
++ UPDATE
++ return Z_OK;
++}
++
++
++/*+++++*/
++/* zutil.c -- target dependent utility functions for the compression library
++ * Copyright (C) 1995 Jean-loup Gailly.
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */
++
++char *zlib_version = ZLIB_VERSION;
++
++char *z_errmsg[] = {
++"stream end", /* Z_STREAM_END 1 */
++"", /* Z_OK 0 */
++"file error", /* Z_ERRNO (-1) */
++"stream error", /* Z_STREAM_ERROR (-2) */
++"data error", /* Z_DATA_ERROR (-3) */
++"insufficient memory", /* Z_MEM_ERROR (-4) */
++"buffer error", /* Z_BUF_ERROR (-5) */
++""};
++
++
++/*+++++*/
++/* adler32.c -- compute the Adler-32 checksum of a data stream
++ * Copyright (C) 1995 Mark Adler
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */
++
++#define BASE 65521L /* largest prime smaller than 65536 */
++#define NMAX 5552
++/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
++
++#define DO1(buf) {s1 += *buf++; s2 += s1;}
++#define DO2(buf) DO1(buf); DO1(buf);
++#define DO4(buf) DO2(buf); DO2(buf);
++#define DO8(buf) DO4(buf); DO4(buf);
++#define DO16(buf) DO8(buf); DO8(buf);
++
++/* ========================================================================= */
++uLong adler32(adler, buf, len)
++ uLong adler;
++ Bytef *buf;
++ uInt len;
++{
++ unsigned long s1 = adler & 0xffff;
++ unsigned long s2 = (adler >> 16) & 0xffff;
++ int k;
++
++ if (buf == Z_NULL) return 1L;
++
++ while (len > 0) {
++ k = len < NMAX ? len : NMAX;
++ len -= k;
++ while (k >= 16) {
++ DO16(buf);
++ k -= 16;
++ }
++ if (k != 0) do {
++ DO1(buf);
++ } while (--k);
++ s1 %= BASE;
++ s2 %= BASE;
++ }
++ return (s2 << 16) | s1;
++}
+diff -Naru linux/arch/mips/zboot/Makefile linux.spi/arch/mips/zboot/Makefile
+--- linux/arch/mips/zboot/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/Makefile 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,84 @@
++#
++# arch/mips/zboot/Makefile
++#
++# This file is subject to the terms and conditions of the GNU General Public
++# License. See the file "COPYING" in the main directory of this archive
++# for more details.
++
++# Adapted for MIPS Pete Popov, Dan Malek
++#
++# Copyright (C) 1994 by Linus Torvalds
++# Adapted for PowerPC by Gary Thomas
++# modified by Cort (cort@cs.nmt.edu)
++#
++
++.c.s:
++ $(CC) $(CFLAGS) -S -o $*.s $<
++.s.o:
++ $(AS) -o $*.o $<
++.c.o:
++ $(CC) $(CFLAGS) -c -o $*.o $<
++.S.s:
++ $(CPP) $(AFLAGS) -o $*.o $<
++.S.o:
++ $(CC) $(AFLAGS) -c -o $*.o $<
++
++GZIP_FLAGS = -v9f
++
++CFLAGS += -D__BOOTER__ -I$(TOPDIR)/arch/$(ARCH)/zboot/include
++AFLAGS += -D__BOOTER__
++
++BOOT_TARGETS = zImage zImage.initrd zImage.flash zImage.initrd.flash
++
++lib/zlib.a:
++ $(MAKE) -C lib
++
++images/vmlinux.gz: $(TOPDIR)/vmlinux
++ $(MAKE) -C images vmlinux.gz
++
++$(BOOT_TARGETS): lib/zlib.a images/vmlinux.gz
++ifdef CONFIG_MIPS_PB1000
++ $(MAKE) -C pb1xxx $@
++endif
++ifdef CONFIG_MIPS_PB1500
++ $(MAKE) -C pb1xxx $@
++endif
++ifdef CONFIG_MIPS_PB1100
++ $(MAKE) -C pb1xxx $@
++endif
++ifdef CONFIG_MIPS_PB1550
++ $(MAKE) -C pb1xxx $@
++endif
++ifdef CONFIG_MIPS_DB1000
++ $(MAKE) -C pb1xxx $@
++endif
++ifdef CONFIG_MIPS_DB1100
++ $(MAKE) -C pb1xxx $@
++endif
++ifdef CONFIG_MIPS_DB1500
++ $(MAKE) -C pb1xxx $@
++endif
++ifdef CONFIG_MIPS_BOSPORUS
++ $(MAKE) -C pb1xxx $@
++endif
++ifdef CONFIG_MIPS_MIRAGE
++ $(MAKE) -C pb1xxx $@
++endif
++ifdef CONFIG_MIPS_MTX1
++ $(MAKE) -C pb1xxx $@
++endif
++ifdef CONFIG_COGENT_CSB250
++ $(MAKE) -C csb250 $@
++endif
++ifdef CONFIG_MIPS_XXS1500
++BOOT_DIR = xxs1500
++endif
++
++# Do the dirs
++clean:
++ $(MAKE) -C common clean
++ $(MAKE) -C images clean
++ $(MAKE) -C pb1xxx clean
++ $(MAKE) -C xxs1500 clean
++
++include $(TOPDIR)/Rules.make
+diff -Naru linux/arch/mips/zboot/pb1xxx/head.S linux.spi/arch/mips/zboot/pb1xxx/head.S
+--- linux/arch/mips/zboot/pb1xxx/head.S 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/pb1xxx/head.S 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,149 @@
++/*
++ * arch/mips/kernel/head.S
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 1994, 1995 Waldorf Electronics
++ * Written by Ralf Baechle and Andreas Busse
++ * Copyright (C) 1995 - 1999 Ralf Baechle
++ * Copyright (C) 1996 Paul M. Antoine
++ * Modified for DECStation and hence R3000 support by Paul M. Antoine
++ * Further modifications by David S. Miller and Harald Koerfgen
++ * Copyright (C) 1999 Silicon Graphics, Inc.
++ *
++ * Head.S contains the MIPS exception handler and startup code.
++ *
++ **************************************************************************
++ * 9 Nov, 2000.
++ * Added Cache Error exception handler and SBDDP EJTAG debug exception.
++ *
++ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
++ **************************************************************************
++ */
++#include <linux/config.h>
++#include <linux/threads.h>
++
++#include <asm/asm.h>
++#include <asm/cacheops.h>
++#include <asm/mipsregs.h>
++#include <asm/offset.h>
++#include <asm/cachectl.h>
++#include <asm/regdef.h>
++
++#define IndexInvalidate_I 0x00
++#define IndexWriteBack_D 0x01
++
++ .set noreorder
++ .cprestore
++ LEAF(start)
++start:
++ bal locate
++ nop
++locate:
++ subu s8, ra, 8 /* Where we were loaded */
++ la sp, (.stack + 8192)
++
++ move s0, a0 /* Save boot rom start args */
++ move s1, a1
++ move s2, a2
++ move s3, a3
++
++ la a0, start /* Where we were linked to run */
++
++ move a1, s8
++ la a2, _edata
++ subu t1, a2, a0
++ srl t1, t1, 2
++
++ /* copy text section */
++ li t0, 0
++1: lw v0, 0(a1)
++ nop
++ sw v0, 0(a0)
++ xor t0, t0, v0
++ addu a0, 4
++ bne a2, a0, 1b
++ addu a1, 4
++
++ /* Clear BSS */
++ la a0, _edata
++ la a2, _end
++2: sw zero, 0(a0)
++ bne a2, a0, 2b
++ addu a0, 4
++
++ /* push the D-Cache and invalidate I-Cache */
++ li k0, 0x80000000 # start address
++ li k1, 0x80004000 # end address (16KB I-Cache)
++ subu k1, 128
++
++1:
++ .set mips3
++ cache IndexWriteBack_D, 0(k0)
++ cache IndexWriteBack_D, 32(k0)
++ cache IndexWriteBack_D, 64(k0)
++ cache IndexWriteBack_D, 96(k0)
++ cache IndexInvalidate_I, 0(k0)
++ cache IndexInvalidate_I, 32(k0)
++ cache IndexInvalidate_I, 64(k0)
++ cache IndexInvalidate_I, 96(k0)
++ .set mips0
++
++ bne k0, k1, 1b
++ addu k0, k0, 128
++ /* done */
++
++ move a0, s8 /* load address */
++ move a1, t1 /* length in words */
++ move a2, t0 /* checksum */
++ move a3, sp
++
++ la ra, 1f
++ la k0, decompress_kernel
++ jr k0
++ nop
++1:
++
++ move a0, s0
++ move a1, s1
++ move a2, s2
++ move a3, s3
++ li k0, KERNEL_ENTRY
++ jr k0
++ nop
++3:
++ b 3b
++ END(start)
++
++ LEAF(udelay)
++udelay:
++ END(udelay)
++
++
++ LEAF(FlushCache)
++ li k0, 0x80000000 # start address
++ li k1, 0x80004000 # end address (16KB I-Cache)
++ subu k1, 128
++
++1:
++ .set mips3
++ cache IndexWriteBack_D, 0(k0)
++ cache IndexWriteBack_D, 32(k0)
++ cache IndexWriteBack_D, 64(k0)
++ cache IndexWriteBack_D, 96(k0)
++ cache IndexInvalidate_I, 0(k0)
++ cache IndexInvalidate_I, 32(k0)
++ cache IndexInvalidate_I, 64(k0)
++ cache IndexInvalidate_I, 96(k0)
++ .set mips0
++
++ bne k0, k1, 1b
++ addu k0, k0, 128
++ jr ra
++ nop
++ END(FlushCache)
++
++ .comm .stack,4096*2,4
+diff -Naru linux/arch/mips/zboot/pb1xxx/Makefile linux.spi/arch/mips/zboot/pb1xxx/Makefile
+--- linux/arch/mips/zboot/pb1xxx/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/pb1xxx/Makefile 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,135 @@
++# arch/mips/zboot/pb1xxx/Makefile
++#
++# Makefile for Alchemy Semiconductor Pb1[015]00 boards.
++# All of the boot loader code was derived from the ppc
++# boot code.
++#
++# Copyright 2001,2002 MontaVista Software Inc.
++#
++# Author: Mark A. Greer
++# mgreer@mvista.com
++# Ported and modified for mips support by
++# Pete Popov <ppopov@mvista.com>
++#
++# This program is free software; you can redistribute it and/or modify it
++# under the terms of the GNU General Public License as published by the
++# Free Software Foundation; either version 2 of the License, or (at your
++# option) any later version.
++
++.c.s:
++ $(CC) $(CFLAGS) -S -o $*.s $<
++.s.o:
++ $(AS) -o $*.o $<
++.c.o:
++ $(CC) $(CFLAGS) -D__BOOTER__ -c -o $*.o $<
++.S.s:
++ $(CPP) $(AFLAGS) -o $*.o $<
++.S.o:
++ $(CC) $(AFLAGS) -c -o $*.o $<
++
++#########################################################################
++# START BOARD SPECIFIC VARIABLES
++ifdef CONFIG_MIPS_PB1000
++BNAME=pb1000
++endif
++
++ifdef CONFIG_MIPS_PB1100
++BNAME=pb1100
++endif
++
++ifdef CONFIG_MIPS_PB1500
++BNAME=pb1500
++endif
++
++ifdef CONFIG_MIPS_PB1550
++BNAME=pb1550
++endif
++
++ifdef CONFIG_MIPS_DB1000
++BNAME=db1000
++endif
++
++ifdef CONFIG_MIPS_DB1100
++BNAME=db1100
++endif
++
++ifdef CONFIG_MIPS_DB1500
++BNAME=db1500
++endif
++
++ifdef CONFIG_MIPS_BOSPORUS
++BNAME=bosporus
++endif
++
++ifdef CONFIG_MIPS_MIRAGE
++BNAME=mirage
++endif
++
++ifdef CONFIG_MIPS_MTX1
++BNAME=mtx-1
++endif
++
++# These two variables control where the zImage is stored
++# in flash and loaded in memory. It only controls how the srec
++# file is generated, the code is the same.
++RAM_RUN_ADDR = 0x81000000
++FLASH_LOAD_ADDR = 0xBFD00000
++
++# These two variables specify the free ram region
++# that can be used for temporary malloc area
++AVAIL_RAM_START=0x80400000
++AVAIL_RAM_END=0x80800000
++
++# This one must match the LOADADDR in arch/mips/Makefile!
++LOADADDR=0x80100000
++# END BOARD SPECIFIC VARIABLES
++#########################################################################
++
++OBJECTS := head.o ../common/misc-common.o ../common/misc-simple.o \
++ ../common/au1k_uart.o ../common/string.o ../common/ctype.o
++LIBS := ../lib/zlib.a
++
++ENTRY := ../utils/entry
++OFFSET := ../utils/offset
++SIZE := ../utils/size
++
++LD_ARGS := -T ../ld.script -Ttext $(RAM_RUN_ADDR) -Bstatic
++OBJCOPY_ARGS = -O elf32-tradlittlemips
++
++all: zImage
++
++clean:
++ rm -rf *.o vmlinux* zvmlinux.* ../images/*.srec
++
++head.o: head.S $(TOPDIR)/vmlinux
++ $(CC) $(AFLAGS) \
++ -DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) $(TOPDIR)/vmlinux ) \
++ -c -o $*.o $<
++
++../common/misc-simple.o:
++ $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \
++ -DAVAIL_RAM_START=$(AVAIL_RAM_START) \
++ -DAVAIL_RAM_END=$(AVAIL_RAM_END) \
++ -DLOADADDR=$(LOADADDR) \
++ -DZIMAGE_SIZE=0 -c -o $@ $*.c
++
++zvmlinux: $(OBJECTS) $(LIBS) ../ld.script ../images/vmlinux.gz ../common/dummy.o
++ $(OBJCOPY) \
++ --add-section=.image=../images/vmlinux.gz \
++ --set-section-flags=.image=contents,alloc,load,readonly,data \
++ ../common/dummy.o image.o
++ $(LD) $(LD_ARGS) -o $@ $(OBJECTS) image.o $(LIBS)
++ $(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab -R .stabstr \
++ -R .initrd -R .sysmap
++
++# Here we manipulate the image in order to get it the necessary
++# srecord file we need.
++zImage: zvmlinux
++ mv zvmlinux ../images/zImage.$(BNAME)
++ $(OBJCOPY) -O srec ../images/zImage.$(BNAME) ../images/$(BNAME).srec
++
++zImage.flash: zImage
++ $(OBJCOPY) -O srec --adjust-vma 0x3ed00000 \
++ ../images/zImage.$(BNAME) ../images/$(BNAME).flash.srec
++
++include $(TOPDIR)/Rules.make
+diff -Naru linux/arch/mips/zboot/utils/entry linux.spi/arch/mips/zboot/utils/entry
+--- linux/arch/mips/zboot/utils/entry 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/utils/entry 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,12 @@
++#!/bin/sh
++
++# grab the kernel_entry address from the vmlinux elf image
++entry=`$1 $2 | grep kernel_entry`
++
++fs=`echo $entry | grep ffffffff` # check toolchain output
++
++if [ -n "$fs" ]; then
++ echo "0x"`$1 $2 | grep kernel_entry | cut -c9- | awk '{print $1}'`
++else
++ echo "0x"`$1 $2 | grep kernel_entry | cut -c1- | awk '{print $1}'`
++fi
+diff -Naru linux/arch/mips/zboot/utils/offset linux.spi/arch/mips/zboot/utils/offset
+--- linux/arch/mips/zboot/utils/offset 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/utils/offset 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,3 @@
++#!/bin/sh
++
++echo "0x"`$1 -h $2 | grep $3 | grep -v zvmlinux| awk '{print $6}'`
+diff -Naru linux/arch/mips/zboot/utils/size linux.spi/arch/mips/zboot/utils/size
+--- linux/arch/mips/zboot/utils/size 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/utils/size 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,4 @@
++#!/bin/sh
++
++OFFSET=`$1 -h $2 | grep $3 | grep -v zvmlinux | awk '{print $3}'`
++echo "0x"$OFFSET
+diff -Naru linux/arch/mips/zboot/xxs1500/head.S linux.spi/arch/mips/zboot/xxs1500/head.S
+--- linux/arch/mips/zboot/xxs1500/head.S 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/xxs1500/head.S 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,137 @@
++/*
++ * arch/mips/kernel/head.S
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 1994, 1995 Waldorf Electronics
++ * Written by Ralf Baechle and Andreas Busse
++ * Copyright (C) 1995 - 1999 Ralf Baechle
++ * Copyright (C) 1996 Paul M. Antoine
++ * Modified for DECStation and hence R3000 support by Paul M. Antoine
++ * Further modifications by David S. Miller and Harald Koerfgen
++ * Copyright (C) 1999 Silicon Graphics, Inc.
++ *
++ * Head.S contains the MIPS exception handler and startup code.
++ *
++ **************************************************************************
++ * 9 Nov, 2000.
++ * Added Cache Error exception handler and SBDDP EJTAG debug exception.
++ *
++ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
++ **************************************************************************
++ */
++#include <linux/config.h>
++#include <linux/threads.h>
++
++#include <asm/asm.h>
++#include <asm/cacheops.h>
++#include <asm/mipsregs.h>
++#include <asm/offset.h>
++#include <asm/cachectl.h>
++#include <asm/regdef.h>
++
++#define IndexInvalidate_I 0x00
++
++ .set noreorder
++ .cprestore
++ LEAF(start)
++start:
++
++locate:
++ la sp, .stack
++ move s0, a0
++ move s1, a1
++ move s2, a2
++ move s3, a3
++
++ la a0, start
++
++ li a1, FLASH_LOAD_ADDR
++ la a2, _edata
++ subu t1, a2, a0
++ srl t1, t1, 2
++
++ /* copy text section */
++ li t0, 0
++1: lw v0, 0(a1)
++ nop
++ sw v0, 0(a0)
++ xor t0, t0, v0
++ addu a0, 4
++ bne a2, a0, 1b
++ addu a1, 4
++
++ /* Clear BSS */
++ la a0, _edata
++ la a2, _end
++2: sw zero, 0(a0)
++ bne a2, a0, 2b
++ addu a0, 4
++
++ /* flush the I-Cache */
++ li k0, 0x80000000 # start address
++ li k1, 0x80004000 # end address (16KB I-Cache)
++ subu k1, 128
++
++1:
++ .set mips3
++ cache IndexInvalidate_I, 0(k0)
++ cache IndexInvalidate_I, 32(k0)
++ cache IndexInvalidate_I, 64(k0)
++ cache IndexInvalidate_I, 96(k0)
++ .set mips0
++
++ bne k0, k1, 1b
++ addu k0, k0, 128
++ /* done */
++
++ li a0, FLASH_LOAD_ADDR /* load address */
++ move a1, t1 /* length in words */
++ move a2, t0 /* checksum */
++ move a3, sp
++
++ la ra, 1f
++ la k0, decompress_kernel
++ jr k0
++ nop
++1:
++
++ move a0, s0
++ move a1, s1
++ move a2, s2
++ move a3, s3
++ li k0, KERNEL_ENTRY
++ jr k0
++ nop
++3:
++ b 3b
++ END(start)
++
++ LEAF(udelay)
++udelay:
++ END(udelay)
++
++
++ LEAF(FlushCache)
++ li k0, 0x80000000 # start address
++ li k1, 0x80004000 # end address (16KB I-Cache)
++ subu k1, 128
++
++1:
++ .set mips3
++ cache IndexInvalidate_I, 0(k0)
++ cache IndexInvalidate_I, 32(k0)
++ cache IndexInvalidate_I, 64(k0)
++ cache IndexInvalidate_I, 96(k0)
++ .set mips0
++
++ bne k0, k1, 1b
++ addu k0, k0, 128
++ jr ra
++ nop
++ END(FlushCache)
++
++ .comm .stack,4096*2,4
+diff -Naru linux/arch/mips/zboot/xxs1500/ld.script linux.spi/arch/mips/zboot/xxs1500/ld.script
+--- linux/arch/mips/zboot/xxs1500/ld.script 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/xxs1500/ld.script 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,147 @@
++OUTPUT_ARCH(mips)
++ENTRY(start)
++SECTIONS
++{
++ /* Read-only sections, merged into text segment: */
++ /* . = 0x81000000; */
++ .init : { *(.init) } =0
++ .text :
++ {
++ _ftext = . ;
++ *(.text)
++ *(.rodata)
++ *(.rodata1)
++ /* .gnu.warning sections are handled specially by elf32.em. */
++ *(.gnu.warning)
++ } =0
++ .kstrtab : { *(.kstrtab) }
++
++ . = ALIGN(16); /* Exception table */
++ __start___ex_table = .;
++ __ex_table : { *(__ex_table) }
++ __stop___ex_table = .;
++
++ __start___dbe_table = .; /* Exception table for data bus errors */
++ __dbe_table : { *(__dbe_table) }
++ __stop___dbe_table = .;
++
++ __start___ksymtab = .; /* Kernel symbol table */
++ __ksymtab : { *(__ksymtab) }
++ __stop___ksymtab = .;
++
++ _etext = .;
++
++ . = ALIGN(8192);
++ .data.init_task : { *(.data.init_task) }
++
++ /* Startup code */
++ . = ALIGN(4096);
++ __init_begin = .;
++ .text.init : { *(.text.init) }
++ .data.init : { *(.data.init) }
++ . = ALIGN(16);
++ __setup_start = .;
++ .setup.init : { *(.setup.init) }
++ __setup_end = .;
++ __initcall_start = .;
++ .initcall.init : { *(.initcall.init) }
++ __initcall_end = .;
++ . = ALIGN(4096); /* Align double page for init_task_union */
++ __init_end = .;
++
++ . = ALIGN(4096);
++ .data.page_aligned : { *(.data.idt) }
++
++ . = ALIGN(32);
++ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
++
++ .fini : { *(.fini) } =0
++ .reginfo : { *(.reginfo) }
++ /* Adjust the address for the data segment. We want to adjust up to
++ the same address within the page on the next page up. It would
++ be more correct to do this:
++ . = .;
++ The current expression does not correctly handle the case of a
++ text segment ending precisely at the end of a page; it causes the
++ data segment to skip a page. The above expression does not have
++ this problem, but it will currently (2/95) cause BFD to allocate
++ a single segment, combining both text and data, for this case.
++ This will prevent the text segment from being shared among
++ multiple executions of the program; I think that is more
++ important than losing a page of the virtual address space (note
++ that no actual memory is lost; the page which is skipped can not
++ be referenced). */
++ . = .;
++ .data :
++ {
++ _fdata = . ;
++ *(.data)
++
++ /* Align the initial ramdisk image (INITRD) on page boundaries. */
++ . = ALIGN(4096);
++ __rd_start = .;
++ *(.initrd)
++ __rd_end = .;
++ . = ALIGN(4096);
++
++ CONSTRUCTORS
++ }
++ .data1 : { *(.data1) }
++ _gp = . + 0x8000;
++ .lit8 : { *(.lit8) }
++ .lit4 : { *(.lit4) }
++ .ctors : { *(.ctors) }
++ .dtors : { *(.dtors) }
++ .got : { *(.got.plt) *(.got) }
++ .dynamic : { *(.dynamic) }
++ /* We want the small data sections together, so single-instruction offsets
++ can access them all, and initialized data all before uninitialized, so
++ we can shorten the on-disk segment size. */
++ .sdata : { *(.sdata) }
++ . = ALIGN(4);
++ _edata = .;
++ PROVIDE (edata = .);
++
++ __bss_start = .;
++ _fbss = .;
++ .sbss : { *(.sbss) *(.scommon) }
++ .bss :
++ {
++ *(.dynbss)
++ *(.bss)
++ *(COMMON)
++ . = ALIGN(4);
++ _end = . ;
++ PROVIDE (end = .);
++ }
++
++ /* Sections to be discarded */
++ /DISCARD/ :
++ {
++ *(.text.exit)
++ *(.data.exit)
++ *(.exitcall.exit)
++ }
++
++ /* This is the MIPS specific mdebug section. */
++ .mdebug : { *(.mdebug) }
++ /* These are needed for ELF backends which have not yet been
++ converted to the new style linker. */
++ .stab 0 : { *(.stab) }
++ .stabstr 0 : { *(.stabstr) }
++ /* DWARF debug sections.
++ Symbols in the .debug DWARF section are relative to the beginning of the
++ section so we begin .debug at 0. It's not clear yet what needs to happen
++ for the others. */
++ .debug 0 : { *(.debug) }
++ .debug_srcinfo 0 : { *(.debug_srcinfo) }
++ .debug_aranges 0 : { *(.debug_aranges) }
++ .debug_pubnames 0 : { *(.debug_pubnames) }
++ .debug_sfnames 0 : { *(.debug_sfnames) }
++ .line 0 : { *(.line) }
++ /* These must appear regardless of . */
++ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
++ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
++ .comment : { *(.comment) }
++ .note : { *(.note) }
++}
+diff -Naru linux/arch/mips/zboot/xxs1500/Makefile linux.spi/arch/mips/zboot/xxs1500/Makefile
+--- linux/arch/mips/zboot/xxs1500/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux.spi/arch/mips/zboot/xxs1500/Makefile 2004-05-11 23:19:24.000000000 -0400
+@@ -0,0 +1,123 @@
++# arch/mips/compressed/alchemy/Makefile
++#
++# Makefile for Alchemy Semiconductor Pb1[015]00 boards.
++# All of the boot loader code was derived from the ppc
++# boot code.
++#
++# Copyright 2001,2002 MontaVista Software Inc.
++#
++# Author: Mark A. Greer
++# mgreer@mvista.com
++# Ported and modified for mips support by
++# Pete Popov <ppopov@mvista.com>
++#
++# This program is free software; you can redistribute it and/or modify it
++# under the terms of the GNU General Public License as published by the
++# Free Software Foundation; either version 2 of the License, or (at your
++# option) any later version.
++
++.c.s:
++ $(CC) $(CFLAGS) -S -o $*.s $<
++.s.o:
++ $(AS) -o $*.o $<
++.c.o:
++ $(CC) $(CFLAGS) -D__BOOTER__ -c -o $*.o $<
++.S.s:
++ $(CPP) $(AFLAGS) -o $*.o $<
++.S.o:
++ $(CC) $(AFLAGS) -c -o $*.o $<
++
++#########################################################################
++# START BOARD SPECIFIC VARIABLES
++BNAME=xxs1500
++
++
++# These two variables control where the zImage is stored
++# in flash and loaded in memory. If you change either one,
++# be sure to make the appropriate change to the zImage
++# rule.
++RAM_LOAD_ADDR = 0x81000000
++FLASH_LOAD_ADDR = 0xBF000000
++
++# These two variables specify the free ram region
++# that can be used for temporary malloc area
++AVAIL_RAM_START=0x80400000
++AVAIL_RAM_END=0x80800000
++
++# This one must match the LOADADDR in arch/mips/Makefile!
++LOADADDR=0x80100000
++# END BOARD SPECIFIC VARIABLES
++#########################################################################
++
++ZLINKFLAGS = -T ld.script -Ttext $(RAM_LOAD_ADDR)
++
++OBJECTS := head.o ../common/misc-common.o ../common/misc-simple.o \
++ ../common/au1k_uart.o ../common/string.o ../common/ctype.o
++LIBS := ../lib/zlib.a
++
++ENTRY := ../utils/entry
++OFFSET := ../utils/offset
++SIZE := ../utils/size
++
++all: zImage
++
++clean:
++ rm -rf *.o vmlinux* zvmlinux.*
++
++head.o: head.S $(TOPDIR)/vmlinux
++ $(CC) -DFLASH_LOAD_ADDR=$(FLASH_LOAD_ADDR) $(AFLAGS) \
++ -DKERNEL_ENTRY=$(shell sh $(ENTRY) $(NM) $(TOPDIR)/vmlinux ) \
++ -c -o $*.o $<
++
++../common/misc-simple.o:
++ $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 -DZIMAGE_OFFSET=0 \
++ -DAVAIL_RAM_START=$(AVAIL_RAM_START) \
++ -DAVAIL_RAM_END=$(AVAIL_RAM_END) \
++ -DLOADADDR=$(LOADADDR) \
++ -DZIMAGE_SIZE=0 -c -o $@ $*.c
++
++# This is the first pass at building the boot loader image,
++# without knowing the file offset where the vmlinuz.gz
++# kernel will end up. We build this image, check the offset,
++# and then rebuild it with the correct offset and size
++# passed to mips-simple.c
++zvmlinux.no: $(OBJECTS) $(LIBS) ../images/vmlinux.gz
++ $(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS)
++ $(OBJCOPY) -R .comment \
++ --add-section=image=../images/vmlinux.gz \
++ $@.tmp $@
++ # rm -f $@.tmp
++
++
++# This is the final image we build, now that we know what
++# the vmlinuz.gz offset is.
++zvmlinux: $(OBJECTS) $(LIBS) ../images/vmlinux.gz zvmlinux.no
++ $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \
++ -DZIMAGE_OFFSET=$(shell sh $(OFFSET) $(OBJDUMP) $@.no image) \
++ -DZIMAGE_SIZE=$(shell sh $(SIZE) $(OBJDUMP) $@.no image) \
++ -D__BOOTER__ \
++ -DAVAIL_RAM_START=$(AVAIL_RAM_START) \
++ -DAVAIL_RAM_END=$(AVAIL_RAM_END) \
++ -DLOADADDR=$(LOADADDR) \
++ -c -o ../common/misc-simple.o ../common/misc-simple.c
++ $(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS)
++ $(OBJCOPY) -R .comment \
++ --add-section=image=../images/vmlinux.gz \
++ $@.tmp $@
++ $(OBJCOPY) --adjust-section-vma=image+$(RAM_LOAD_ADDR) $@
++ $(OBJCOPY) --adjust-section-vma=image+$(shell sh $(OFFSET) \
++ $(OBJDUMP) $@.no image ) $@
++ # rm -f $@.tmp
++ # rm -f $@.no
++
++
++# Here we manipulate the image in order to get it the necessary
++# srecord file we need.
++zImage: zvmlinux
++ mv zvmlinux ../images/$@.$(BNAME)
++ $(OBJCOPY) --set-section-flags=image=alloc,load,code ../images/$@.$(BNAME)
++ $(OBJCOPY) -O srec --adjust-vma 0x3e000000 \
++ ../images/$@.$(BNAME) ../images/$@.$(BNAME).srec
++ # rm ../images/vmlinux.gz
++
++include $(TOPDIR)/Rules.make