boot.c revision 48907
1183840Sraj/*
2183840Sraj * Copyright (c) 1999 Global Technology Associates, Inc.
3183840Sraj * All rights reserved.
4183840Sraj *
5183840Sraj * Redistribution and use in source and binary forms, with or without
6183840Sraj * modification, are permitted provided that the following conditions
7183840Sraj * are met:
8183840Sraj * 1. Redistributions of source code must retain the above copyright
9183840Sraj *    notice, this list of conditions and the following disclaimer.
10183840Sraj * 2. Redistributions in binary form must reproduce the above copyright
11183840Sraj *    notice, this list of conditions and the following disclaimer in the
12183840Sraj *    documentation and/or other materials provided with the distribution.
13183840Sraj *
14183840Sraj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND
15183840Sraj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16183840Sraj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17183840Sraj * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
18183840Sraj * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
19183840Sraj * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
20183840Sraj * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21183840Sraj * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22183840Sraj * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23183840Sraj * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24183840Sraj * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25183840Sraj *
26183840Sraj *	$Id:$
27183840Sraj */
28183840Sraj
29183840Sraj#include <sys/types.h>
30183840Sraj#include <sys/reboot.h>
31183840Sraj#include <sys/inflate.h>
32183840Sraj
33183840Sraj#include "kgzldr.h"
34183840Sraj
35183840Sraj#define KGZ_HEAD   0xa          /* leading bytes to ignore */
36183840Sraj#define KGZ_TAIL   0x8          /* trailing bytes to ignore */
37183840Sraj
38183840Sraj#define E_FMT  1		/* Error: Invalid format */
39183840Sraj#define E_MEM  2		/* Error: Out of memory */
40209131Sraj
41183840Srajstruct kgz_hdr {
42183840Sraj    char	ident[4];	/* identification */
43183840Sraj    uint32_t	dload;		/* decoded image load address */
44194072Smarcel    uint32_t	dsize;		/* decoded image size */
45183840Sraj    uint32_t	isize;		/* image size in memory */
46209131Sraj    uint32_t	entry;		/* program entry point */
47186932Sraj    uint32_t	nsize;		/* encoded image size */
48185089Sraj};
49185089Srajextern struct kgz_hdr kgz;	/* header */
50185089Srajextern uint8_t kgz_ndata[];	/* encoded image */
51185089Sraj
52185089Srajstatic const char *const msg[] = {
53183840Sraj    "done",
54183840Sraj    "invalid format",
55185089Sraj    "out of memory"
56185089Sraj};
57185089Sraj
58185089Srajstatic const u_char *ip;        /* input pointer */
59185089Srajstatic u_char *op;              /* output pointer */
60186932Sraj
61183840Srajstatic struct inflate infl;	/* inflate() parameters */
62185089Sraj
63185089Srajstatic int decode(void);
64183840Srajstatic int input(void *);
65209131Srajstatic int output(void *, u_char *, u_long);
66183840Sraj
67186909Sraj/*
68183840Sraj * Uncompress and boot a kernel.
69183840Sraj */
70183840Srajint
71183840Srajboot(int howto)
72183840Sraj{
73183840Sraj    int err;
74183840Sraj
75183840Sraj    kgz_con = howto & RB_SERIAL ? KGZ_SIO : KGZ_CRT;
76183840Sraj    putstr("Uncompressing ... ");
77209131Sraj    err = decode();
78183840Sraj    putstr(msg[err]);
79183840Sraj    putstr("\n");
80209131Sraj    if (err) {
81186899Sraj        putstr("System halted");
82186899Sraj	for (;;)
83186899Sraj	    ;
84186899Sraj    }
85186899Sraj    return err;
86186899Sraj}
87186899Sraj
88186899Sraj/*
89186899Sraj * Interface with inflate() to uncompress the data.
90186899Sraj */
91209131Srajstatic int
92209131Srajdecode(void)
93186899Sraj{
94186899Sraj    static u_char slide[GZ_WSIZE];
95186899Sraj    int err;
96186899Sraj
97186899Sraj    ip = kgz_ndata + KGZ_HEAD;
98186899Sraj    op = (u_char *)kgz.dload;
99186899Sraj    infl.gz_input = input;
100186899Sraj    infl.gz_output = output;
101186899Sraj    infl.gz_slide = slide;
102186899Sraj    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