Home | History | Annotate | Line # | Download | only in gzboot
gzboot.c revision 1.11.90.1
      1  1.11.90.1       jym /*	$NetBSD: gzboot.c,v 1.11.90.1 2009/05/13 17:16:39 jym Exp $	*/
      2        1.1   thorpej 
      3        1.1   thorpej /*
      4        1.1   thorpej  * Copyright (c) 2002 Wasabi Systems, Inc.
      5        1.1   thorpej  * All rights reserved.
      6        1.1   thorpej  *
      7        1.1   thorpej  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
      8        1.1   thorpej  *
      9        1.1   thorpej  * Redistribution and use in source and binary forms, with or without
     10        1.1   thorpej  * modification, are permitted provided that the following conditions
     11        1.1   thorpej  * are met:
     12        1.1   thorpej  * 1. Redistributions of source code must retain the above copyright
     13        1.1   thorpej  *    notice, this list of conditions and the following disclaimer.
     14        1.1   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     15        1.1   thorpej  *    notice, this list of conditions and the following disclaimer in the
     16        1.1   thorpej  *    documentation and/or other materials provided with the distribution.
     17        1.1   thorpej  * 3. All advertising materials mentioning features or use of this software
     18        1.1   thorpej  *    must display the following acknowledgement:
     19        1.1   thorpej  *	This product includes software developed for the NetBSD Project by
     20        1.1   thorpej  *	Wasabi Systems, Inc.
     21        1.1   thorpej  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22        1.1   thorpej  *    or promote products derived from this software without specific prior
     23        1.1   thorpej  *    written permission.
     24        1.1   thorpej  *
     25        1.1   thorpej  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26        1.1   thorpej  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27        1.1   thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28        1.1   thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29        1.1   thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30        1.1   thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31        1.1   thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32        1.1   thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33        1.1   thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34        1.1   thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35        1.1   thorpej  * POSSIBILITY OF SUCH DAMAGE.
     36        1.1   thorpej  */
     37        1.1   thorpej 
     38        1.1   thorpej /*
     39        1.1   thorpej  * The Gzip header parser and libz interface glue are derived from
     40        1.1   thorpej  * sys/lib/libsa/cread.c, which carries the following notice:
     41        1.1   thorpej  *
     42        1.1   thorpej  * Copyright (c) 1996
     43        1.1   thorpej  *	Matthias Drochner.  All rights reserved.
     44        1.1   thorpej  *
     45        1.1   thorpej  * Redistribution and use in source and binary forms, with or without
     46        1.1   thorpej  * modification, are permitted provided that the following conditions
     47        1.1   thorpej  * are met:
     48        1.1   thorpej  * 1. Redistributions of source code must retain the above copyright
     49        1.1   thorpej  *    notice, this list of conditions and the following disclaimer.
     50        1.1   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     51        1.1   thorpej  *    notice, this list of conditions and the following disclaimer in the
     52        1.1   thorpej  *    documentation and/or other materials provided with the distribution.
     53        1.1   thorpej  *
     54        1.1   thorpej  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     55        1.1   thorpej  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     56        1.1   thorpej  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     57        1.1   thorpej  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     58        1.1   thorpej  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     59        1.1   thorpej  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     60        1.1   thorpej  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     61        1.1   thorpej  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     62        1.1   thorpej  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     63        1.1   thorpej  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     64        1.1   thorpej  */
     65        1.1   thorpej 
     66        1.1   thorpej #include <sys/param.h>
     67        1.1   thorpej #include <lib/libsa/stand.h>
     68        1.1   thorpej #include <lib/libkern/libkern.h>
     69       1.10        he #include <lib/libz/libz.h>
     70        1.1   thorpej 
     71        1.1   thorpej #include "board.h"
     72        1.1   thorpej #include "gzboot.h"
     73        1.1   thorpej 
     74        1.1   thorpej /* zlib glue defns */
     75        1.1   thorpej 
     76        1.1   thorpej #define	EOF	(-1)	/* needed by compression code */
     77        1.1   thorpej 
     78        1.1   thorpej #define	Z_BUFSIZE	1024
     79        1.1   thorpej 
     80        1.1   thorpej static const int gz_magic[2] = { 0x1f, 0x8b }; /* gzip magic header */
     81        1.1   thorpej 
     82        1.1   thorpej /* gzip flag byte */
     83        1.1   thorpej #define	ASCII_FLAG	0x01	/* bit 0 set: file probably ascii text */
     84        1.1   thorpej #define	HEAD_CRC	0x02	/* bit 1 set: header CRC present */
     85        1.1   thorpej #define	EXTRA_FIELD	0x04	/* bit 2 set: extra field present */
     86        1.1   thorpej #define	ORIG_NAME	0x08	/* bit 3 set: original file name present */
     87        1.1   thorpej #define	COMMENT		0x10	/* bit 4 set: file comment present */
     88        1.1   thorpej #define	RESERVED	0xe0	/* bits 5..7: reserved */
     89        1.1   thorpej 
     90        1.1   thorpej struct state {
     91        1.1   thorpej 	z_stream	stream;
     92        1.1   thorpej 	int		z_err;	/* error code for last stream operation */
     93        1.1   thorpej 	int		z_eof;	/* set of end of input file */
     94        1.1   thorpej 	const unsigned char *srcbuf;/* source buffer */
     95        1.1   thorpej 	size_t		srcoff;	/* source buffer offset */
     96        1.1   thorpej 	size_t		srcsize;/* size of source buffer */
     97        1.1   thorpej 	unsigned char	*inbuf;	/* input buffer */
     98        1.1   thorpej 	uint32_t	crc;	/* crc32 of uncompressed data */
     99        1.1   thorpej 	int		spinny;	/* twiddle every N reads */
    100        1.1   thorpej };
    101        1.1   thorpej 
    102        1.1   thorpej static uint32_t	get_u8(struct state *);
    103        1.1   thorpej static uint32_t	get_u32(struct state *);
    104        1.1   thorpej static int	check_header(struct state *);
    105        1.1   thorpej 
    106        1.1   thorpej /* XXX - find a suitable header for these: */
    107        1.1   thorpej void	zmemcpy(unsigned char *, unsigned char *, unsigned int);
    108        1.1   thorpej 
    109        1.1   thorpej /* end zlib glue defns */
    110        1.1   thorpej 
    111        1.1   thorpej void	main(void);
    112        1.1   thorpej void	gzcopy(void *, const void *, size_t);
    113        1.1   thorpej 
    114        1.1   thorpej void
    115        1.1   thorpej main(void)
    116        1.1   thorpej {
    117        1.1   thorpej 	extern char bootprog_name[], bootprog_rev[],
    118        1.1   thorpej 	    bootprog_maker[], bootprog_date[];
    119        1.1   thorpej 	void (*loadaddr)(void) = (void *) md_root_loadaddr;
    120        1.1   thorpej 
    121        1.1   thorpej 	cons_init();
    122        1.1   thorpej 
    123        1.1   thorpej 	printf("\n");
    124        1.1   thorpej 	printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
    125        1.1   thorpej 	printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
    126        1.1   thorpej 
    127        1.6   thorpej 	board_init();
    128        1.1   thorpej 
    129        1.1   thorpej 	printf(">> Load address: 0x%x\n", md_root_loadaddr);
    130        1.7   thorpej 
    131        1.7   thorpej 	/*
    132        1.7   thorpej 	 * If md_root_size is 0, then it means that we are simply
    133        1.7   thorpej 	 * decompressing from an image which was concatenated onto
    134        1.7   thorpej 	 * the end of the gzboot binary.
    135        1.7   thorpej 	 */
    136        1.7   thorpej 	if (md_root_size != 0)
    137        1.7   thorpej 		printf(">> Image size: %u\n", md_root_size);
    138        1.1   thorpej 
    139        1.1   thorpej 	printf("Uncompressing image...");
    140        1.1   thorpej 	gzcopy((void *) loadaddr, md_root_image, md_root_size);
    141        1.1   thorpej 	printf("done.\n");
    142        1.1   thorpej 
    143        1.1   thorpej 	printf("Jumping to image @ 0x%x...\n", md_root_loadaddr);
    144        1.6   thorpej 
    145        1.6   thorpej 	board_fini();
    146        1.6   thorpej 
    147        1.1   thorpej 	(*loadaddr)();
    148        1.1   thorpej 
    149        1.1   thorpej 	_rtt();
    150        1.1   thorpej }
    151        1.1   thorpej 
    152        1.1   thorpej void abort(void);
    153        1.1   thorpej void
    154        1.1   thorpej abort(void)
    155        1.1   thorpej {
    156        1.1   thorpej 
    157        1.1   thorpej 	for (;;) ;
    158        1.1   thorpej }
    159        1.1   thorpej 
    160        1.1   thorpej __dead void
    161        1.1   thorpej _rtt(void)
    162        1.1   thorpej {
    163        1.1   thorpej 
    164        1.1   thorpej 	for (;;) ;
    165        1.1   thorpej }
    166        1.1   thorpej 
    167        1.1   thorpej /* internal utility routines */
    168        1.1   thorpej 
    169        1.1   thorpej static ssize_t
    170        1.1   thorpej readbuf(struct state *s, void *buf, size_t len)
    171        1.1   thorpej {
    172        1.1   thorpej 
    173        1.7   thorpej 	if (s->srcsize != 0 && len > (s->srcsize - s->srcoff))
    174        1.1   thorpej 		len = s->srcsize - s->srcoff;
    175        1.1   thorpej 
    176        1.2   thorpej 	if ((s->spinny++ & 7) == 0)
    177        1.1   thorpej 		twiddle();
    178  1.11.90.1       jym 	memcpy( buf, s->srcbuf + s->srcoff, len);
    179        1.1   thorpej 	s->srcoff += len;
    180        1.1   thorpej 
    181        1.1   thorpej 	return (len);
    182        1.1   thorpej }
    183        1.1   thorpej 
    184        1.1   thorpej static ssize_t
    185        1.1   thorpej readgz(struct state *s, void *buf, size_t len)
    186        1.1   thorpej {
    187        1.1   thorpej 	unsigned char *start = buf;	/* start for CRC computation */
    188        1.1   thorpej 
    189        1.1   thorpej 	if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)
    190        1.1   thorpej 		return (-1);
    191        1.1   thorpej 	if (s->z_err == Z_STREAM_END)
    192        1.1   thorpej 		return (0);	/* EOF */
    193        1.1   thorpej 
    194        1.1   thorpej 	s->stream.next_out = buf;
    195        1.1   thorpej 	s->stream.avail_out = len;
    196        1.1   thorpej 
    197        1.1   thorpej 	while (s->stream.avail_out != 0) {
    198        1.1   thorpej 		if (s->stream.avail_in == 0 && s->z_eof == 0) {
    199        1.1   thorpej 			ssize_t got;
    200        1.1   thorpej 			got = readbuf(s, s->inbuf, Z_BUFSIZE);
    201        1.1   thorpej 			if (got <= 0)
    202        1.1   thorpej 				s->z_eof = 1;
    203        1.1   thorpej 			s->stream.avail_in = got;
    204        1.1   thorpej 			s->stream.next_in = s->inbuf;
    205        1.1   thorpej 		}
    206        1.1   thorpej 
    207        1.1   thorpej 		s->z_err = inflate(&s->stream, Z_NO_FLUSH);
    208        1.1   thorpej 
    209        1.1   thorpej 		if (s->z_err == Z_STREAM_END) {
    210        1.1   thorpej 			/* Check CRC and original size */
    211        1.1   thorpej 			s->crc = crc32(s->crc, start, (unsigned int)
    212        1.1   thorpej 			    (s->stream.next_out - start));
    213        1.1   thorpej 			start = s->stream.next_out;
    214        1.1   thorpej 
    215        1.1   thorpej 			if (get_u32(s) != s->crc) {
    216        1.1   thorpej 				printf("FATAL: CRC checksum mismatch\n");
    217        1.1   thorpej 				s->z_err = Z_DATA_ERROR;
    218        1.1   thorpej 			}
    219        1.1   thorpej 			if (get_u32(s) != s->stream.total_out) {
    220        1.1   thorpej 				printf("FATAL: total output mismatch\n");
    221        1.1   thorpej 				s->z_err = Z_DATA_ERROR;
    222        1.1   thorpej 			}
    223        1.1   thorpej 			s->z_eof = 1;
    224        1.5   thorpej 		}
    225        1.5   thorpej 		if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) {
    226        1.5   thorpej 			printf("FATAL: error %d from zlib\n",
    227        1.5   thorpej 			    s->z_err);
    228        1.5   thorpej 			return (-1);
    229        1.1   thorpej 		}
    230        1.1   thorpej 		if (s->z_err != Z_OK || s->z_eof)
    231        1.1   thorpej 			break;
    232        1.1   thorpej 	}
    233        1.1   thorpej 
    234        1.1   thorpej 	s->crc = crc32(s->crc, start,
    235        1.1   thorpej 	    (unsigned int)(s->stream.next_out - start));
    236        1.1   thorpej 
    237        1.1   thorpej 	return ((ssize_t) (len - s->stream.avail_out));
    238        1.1   thorpej }
    239        1.1   thorpej 
    240        1.1   thorpej /* util routines for zlib */
    241        1.1   thorpej 
    242        1.1   thorpej void
    243        1.1   thorpej zmemcpy(unsigned char *dst, unsigned char *src, unsigned int len)
    244        1.1   thorpej {
    245        1.1   thorpej 
    246  1.11.90.1       jym 	memcpy( dst, src, len);
    247        1.1   thorpej }
    248        1.1   thorpej 
    249        1.1   thorpej /* gzip utility routines */
    250        1.1   thorpej 
    251        1.1   thorpej static uint32_t
    252        1.1   thorpej get_u8(struct state *s)
    253        1.1   thorpej {
    254        1.1   thorpej 
    255        1.1   thorpej 	if (s->z_eof)
    256        1.1   thorpej 		return (EOF);
    257        1.1   thorpej 
    258        1.1   thorpej 	if (s->stream.avail_in == 0) {
    259        1.1   thorpej 		ssize_t got;
    260        1.1   thorpej 
    261        1.1   thorpej 		got = readbuf(s, s->inbuf, Z_BUFSIZE);
    262        1.1   thorpej 		if (got <= 0) {
    263        1.1   thorpej 			s->z_eof = 1;
    264        1.1   thorpej 			return (EOF);
    265        1.1   thorpej 		}
    266        1.1   thorpej 		s->stream.avail_in = got;
    267        1.1   thorpej 		s->stream.next_in = s->inbuf;
    268        1.1   thorpej 	}
    269        1.1   thorpej 	s->stream.avail_in--;
    270        1.1   thorpej 	return (*(s->stream.next_in)++);
    271        1.1   thorpej }
    272        1.1   thorpej 
    273        1.1   thorpej static uint32_t
    274        1.1   thorpej get_u32(struct state *s)
    275        1.1   thorpej {
    276        1.1   thorpej 	uint32_t x, c;
    277        1.1   thorpej 
    278        1.1   thorpej 	x  = get_u8(s);
    279        1.1   thorpej 	x |= get_u8(s) << 8;
    280        1.1   thorpej 	x |= get_u8(s) << 16;
    281        1.1   thorpej 	c = get_u8(s);
    282        1.1   thorpej 	if (c == EOF)
    283        1.1   thorpej 		s->z_err = Z_DATA_ERROR;
    284        1.1   thorpej 	x |= c << 24;
    285        1.1   thorpej 	return (x);
    286        1.1   thorpej }
    287        1.1   thorpej 
    288        1.1   thorpej static int
    289        1.1   thorpej check_header(struct state *s)
    290        1.1   thorpej {
    291        1.1   thorpej 	int method;	/* method byte */
    292        1.1   thorpej 	int flags;	/* flags byte */
    293        1.1   thorpej 	unsigned int len;
    294        1.1   thorpej 	int c;
    295        1.1   thorpej 
    296        1.1   thorpej 	/* Check the gzip magic header */
    297        1.1   thorpej 	for (len = 0; len < 2; len++) {
    298        1.1   thorpej 		c = get_u8(s);
    299        1.1   thorpej 		if (c == gz_magic[len])
    300        1.1   thorpej 			continue;
    301        1.1   thorpej 		printf("FATAL: not a Gzip'd image\n");
    302        1.1   thorpej 		return (1);
    303        1.1   thorpej 	}
    304        1.1   thorpej 
    305        1.1   thorpej 	method = get_u8(s);
    306        1.1   thorpej 	flags = get_u8(s);
    307        1.1   thorpej 	if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
    308        1.1   thorpej 		printf("FATAL: invalid Gzip header\n");
    309        1.1   thorpej 		return (1);
    310        1.1   thorpej 	}
    311        1.1   thorpej 
    312        1.1   thorpej 	/* Discard time, xflags, and OS code: */
    313        1.1   thorpej 	for (len = 0; len < 6; len++)
    314        1.1   thorpej 		(void) get_u8(s);
    315        1.1   thorpej 
    316        1.1   thorpej 	if (flags & EXTRA_FIELD) {
    317        1.1   thorpej 		/* skip the extra field */
    318        1.1   thorpej 		len  = get_u8(s);
    319        1.1   thorpej 		len |= get_u8(s) << 8;
    320        1.1   thorpej 		/* len is garbage if EOF, but the loop below will quit anyway */
    321        1.1   thorpej 		while (len-- && get_u8(s) != EOF)
    322        1.1   thorpej 			/* loop */;
    323        1.1   thorpej 	}
    324        1.1   thorpej 	if (flags & ORIG_NAME) {
    325        1.1   thorpej 		/* skip the original file name */
    326        1.1   thorpej 		while ((c = get_u8(s)) != 0 && c != EOF)
    327        1.1   thorpej 			/* loop */;
    328        1.1   thorpej 	}
    329        1.1   thorpej 	if (flags & COMMENT) {
    330        1.1   thorpej 		/* skip the file comment */
    331        1.1   thorpej 		while ((c = get_u8(s)) != 0 && c != EOF)
    332        1.1   thorpej 			/* loop */;
    333        1.1   thorpej 	}
    334        1.1   thorpej 	if (flags & HEAD_CRC) {
    335        1.1   thorpej 		/* skip header CRC */
    336        1.1   thorpej 		for (len = 0; len < 2; len++)
    337        1.1   thorpej 			(void) get_u8(s);
    338        1.1   thorpej 	}
    339        1.1   thorpej 
    340        1.1   thorpej 	if (s->z_eof) {
    341        1.1   thorpej 		printf("FATAL: end of image encountered parsing Gzip header\n");
    342        1.1   thorpej 		return (1);
    343        1.1   thorpej 	}
    344        1.1   thorpej 
    345        1.1   thorpej 	/* OK! */
    346        1.1   thorpej 	return (0);
    347        1.1   thorpej }
    348        1.1   thorpej 
    349        1.1   thorpej /* the actual gzcopy routine */
    350        1.1   thorpej 
    351        1.1   thorpej void
    352        1.1   thorpej gzcopy(void *dst, const void *src, size_t srclen)
    353        1.1   thorpej {
    354        1.1   thorpej 	struct state state;
    355        1.1   thorpej 	unsigned char *cp = dst;
    356        1.1   thorpej 	ssize_t len;
    357        1.1   thorpej 
    358  1.11.90.1       jym 	memset(&state, 0, sizeof(state));
    359        1.1   thorpej 
    360        1.1   thorpej 	state.z_err = Z_OK;
    361        1.1   thorpej 	state.srcbuf = src;
    362        1.1   thorpej 	state.srcsize = srclen;
    363        1.1   thorpej 
    364        1.1   thorpej 	if (inflateInit2(&state.stream, -15) != Z_OK) {
    365        1.1   thorpej 		printf("FATAL: inflateInit2 failed\n");
    366        1.1   thorpej 		_rtt();
    367        1.1   thorpej 	}
    368        1.1   thorpej 
    369        1.1   thorpej 	state.stream.next_in = state.inbuf = alloc(Z_BUFSIZE);
    370        1.1   thorpej 	if (state.inbuf == NULL) {
    371        1.1   thorpej 		inflateEnd(&state.stream);
    372        1.1   thorpej 		printf("FATAL: unable to allocate Z buffer\n");
    373        1.1   thorpej 		_rtt();
    374        1.1   thorpej 	}
    375        1.1   thorpej 
    376        1.1   thorpej 	/* Skip the Gzip header. */
    377        1.1   thorpej 	if (check_header(&state)) {
    378        1.1   thorpej 		inflateEnd(&state.stream);
    379       1.11  christos 		dealloc(state.inbuf, Z_BUFSIZE);
    380        1.1   thorpej 		_rtt();
    381        1.1   thorpej 	}
    382        1.1   thorpej 
    383        1.1   thorpej 	/* Uncompress the image! */
    384        1.1   thorpej 	while ((len = readgz(&state, cp, Z_BUFSIZE)) > 0)
    385        1.1   thorpej 		cp += len;
    386        1.1   thorpej 	if (len == -1)
    387        1.1   thorpej 		_rtt();
    388        1.1   thorpej 
    389        1.1   thorpej 	/* All done! */
    390        1.1   thorpej 	inflateEnd(&state.stream);
    391       1.11  christos 	dealloc(state.inbuf, Z_BUFSIZE);
    392        1.1   thorpej }
    393