boot.c revision 50477
11590Srgrimes/*
21590Srgrimes * Copyright (c) 1999 Global Technology Associates, Inc.
31590Srgrimes * All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes *
141590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND
151590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
171590Srgrimes * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
181590Srgrimes * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
191590Srgrimes * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
201590Srgrimes * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
211590Srgrimes * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
221590Srgrimes * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
231590Srgrimes * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
241590Srgrimes * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
251590Srgrimes *
261590Srgrimes * $FreeBSD: head/sys/boot/i386/kgzldr/boot.c 50477 1999-08-28 01:08:13Z peter $
271590Srgrimes */
281590Srgrimes
291590Srgrimes#include <sys/types.h>
301590Srgrimes#include <sys/reboot.h>
311590Srgrimes#include <sys/inflate.h>
321590Srgrimes
331590Srgrimes#include "kgzldr.h"
341590Srgrimes
3541568Sarchie#define KGZ_HEAD   0xa          /* leading bytes to ignore */
361590Srgrimes#define KGZ_TAIL   0x8          /* trailing bytes to ignore */
371590Srgrimes
381590Srgrimes#define E_FMT  1		/* Error: Invalid format */
391590Srgrimes#define E_MEM  2		/* Error: Out of memory */
401590Srgrimes
4141568Sarchiestruct kgz_hdr {
421590Srgrimes    char	ident[4];	/* identification */
4399112Sobrien    uint32_t	dload;		/* decoded image load address */
4499112Sobrien    uint32_t	dsize;		/* decoded image size */
451590Srgrimes    uint32_t	isize;		/* image size in memory */
4665508Sdes    uint32_t	entry;		/* program entry point */
4765414Sdes    uint32_t	nsize;		/* encoded image size */
481590Srgrimes};
4978717Sddextern struct kgz_hdr kgz;	/* header */
5023693Speterextern uint8_t kgz_ndata[];	/* encoded image */
511590Srgrimes
5292920Simpstatic const char *const msg[] = {
531590Srgrimes    "done",
541590Srgrimes    "invalid format",
551590Srgrimes    "out of memory"
561590Srgrimes};
571590Srgrimes
581590Srgrimesstatic const u_char *ip;        /* input pointer */
5965508Sdesstatic u_char *op;              /* output pointer */
601590Srgrimes
611590Srgrimesstatic struct inflate infl;	/* inflate() parameters */
6224360Simp
631590Srgrimesstatic int decode(void);
641590Srgrimesstatic int input(void *);
651590Srgrimesstatic int output(void *, u_char *, u_long);
661590Srgrimes
671590Srgrimes/*
681590Srgrimes * Uncompress and boot a kernel.
691590Srgrimes */
701590Srgrimesint
711590Srgrimesboot(int howto)
721590Srgrimes{
731590Srgrimes    int err;
7465508Sdes
7565508Sdes    kgz_con = howto & RB_SERIAL ? KGZ_SIO : KGZ_CRT;
7665508Sdes    putstr("Uncompressing ... ");
771590Srgrimes    err = decode();
781590Srgrimes    putstr(msg[err]);
791590Srgrimes    putstr("\n");
801590Srgrimes    if (err) {
811590Srgrimes        putstr("System halted");
821590Srgrimes	for (;;)
831590Srgrimes	    ;
841590Srgrimes    }
851590Srgrimes    return err;
861590Srgrimes}
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