boot.c revision 48907
1/*
2 * Copyright (c) 1999 Global Technology Associates, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
19 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
20 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 *	$Id:$
27 */
28
29#include <sys/types.h>
30#include <sys/reboot.h>
31#include <sys/inflate.h>
32
33#include "kgzldr.h"
34
35#define KGZ_HEAD   0xa          /* leading bytes to ignore */
36#define KGZ_TAIL   0x8          /* trailing bytes to ignore */
37
38#define E_FMT  1		/* Error: Invalid format */
39#define E_MEM  2		/* Error: Out of memory */
40
41struct kgz_hdr {
42    char	ident[4];	/* identification */
43    uint32_t	dload;		/* decoded image load address */
44    uint32_t	dsize;		/* decoded image size */
45    uint32_t	isize;		/* image size in memory */
46    uint32_t	entry;		/* program entry point */
47    uint32_t	nsize;		/* encoded image size */
48};
49extern struct kgz_hdr kgz;	/* header */
50extern uint8_t kgz_ndata[];	/* encoded image */
51
52static const char *const msg[] = {
53    "done",
54    "invalid format",
55    "out of memory"
56};
57
58static const u_char *ip;        /* input pointer */
59static u_char *op;              /* output pointer */
60
61static struct inflate infl;	/* inflate() parameters */
62
63static int decode(void);
64static int input(void *);
65static int output(void *, u_char *, u_long);
66
67/*
68 * Uncompress and boot a kernel.
69 */
70int
71boot(int howto)
72{
73    int err;
74
75    kgz_con = howto & RB_SERIAL ? KGZ_SIO : KGZ_CRT;
76    putstr("Uncompressing ... ");
77    err = decode();
78    putstr(msg[err]);
79    putstr("\n");
80    if (err) {
81        putstr("System halted");
82	for (;;)
83	    ;
84    }
85    return err;
86}
87
88/*
89 * Interface with inflate() to uncompress the data.
90 */
91static int
92decode(void)
93{
94    static u_char slide[GZ_WSIZE];
95    int err;
96
97    ip = kgz_ndata + KGZ_HEAD;
98    op = (u_char *)kgz.dload;
99    infl.gz_input = input;
100    infl.gz_output = output;
101    infl.gz_slide = slide;
102    err = inflate(&infl);
103    return err ? err == 3 ? E_MEM : E_FMT : 0;
104}
105
106/*
107 * Read a byte.
108 */
109static int
110input(void *dummy)
111{
112    if ((size_t)(ip - kgz_ndata) + KGZ_TAIL > kgz.nsize)
113        return GZ_EOF;
114    return *ip++;
115}
116
117/*
118 * Write some bytes.
119 */
120static int
121output(void *dummy, u_char * ptr, u_long len)
122{
123    if (op - (u_char *)kgz.dload + len > kgz.dsize)
124        return -1;
125    while (len--)
126        *op++ = *ptr++;
127    return 0;
128}
129