1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
/* Self decompression and image decompression routines
Copyright (C) 1993 Hannu Savolainen
1996,1998 Jakub Jelinek
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 program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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 "silo.h"
#include "setjmp.h"
#ifndef NULL
#define NULL (void *)0
#endif
/*
* gzip declarations
*/
#define OF(args) args
#define STATIC static
#define memzero(s, n) memset ((s), 0, (n))
typedef unsigned char uch;
typedef unsigned short ush;
typedef unsigned long ulg;
#define WSIZE 0x8000 /* Window size must be at least 32k, */
/* and a power of two */
static uch window[WSIZE]; /* Sliding window buffer */
static unsigned outcnt = 0; /* bytes in output buffer */
/* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
#define RESERVED 0xC0 /* bit 6,7: reserved */
#define Assert(cond,msg)
#define Trace(x)
#define Tracev(x)
#define Tracevv(x)
#define Tracec(c,x)
#define Tracecv(c,x)
static void flush_window (void);
static void error (char *);
#define gzip_mark mark
inline void gzip_release (void **p)
{
release (*p);
}
static long bytes_out;
static uch *output_data, *output_limit;
static unsigned long output_ptr = 0;
static unsigned char (*get_input_fun) (void);
static void (*unget_input_fun) (void);
jmp_buf gunzip_env;
#define get_byte() (*get_input_fun)()
#define unget_byte() (*unget_input_fun)()
#include "inflate.c"
static void error (char *m)
{
printf ("\nDecompression error: %s\n", m);
longjmp (gunzip_env, 1);
}
static void flush_window ()
{
ulg c = crc;
unsigned n;
uch *in, ch;
in = window;
if (output_data + outcnt > output_limit)
error ("uncompressed image too long - wouldn't fit into destination");
for (n = 0; n < outcnt; n++) {
ch = *output_data++ = *in++;
c = crc_32_tab[((int) c ^ ch) & 0xff] ^ (c >> 8);
}
crc = c;
bytes_out += (ulg) outcnt;
outcnt = 0;
}
int decompress (char *outptr, char *outptrlim, unsigned char (*get_input) (void), void (*unget_input) (void))
{
void *save_ptr;
static int first = 1;
gzip_mark (&save_ptr);
if (setjmp (gunzip_env)) {
gzip_release (&save_ptr);
return -1;
}
output_data = outptr;
output_limit = outptrlim;
get_input_fun = get_input;
unget_input_fun = unget_input;
bytes_out = 0;
crc = 0xffffffffL;
if (first) {
makecrc ();
first = 0;
}
gunzip ();
gzip_release (&save_ptr);
return bytes_out;
}
static unsigned char *gzminp;
static unsigned char get_input(void)
{
return *gzminp++;
}
static void unget_input(void)
{
gzminp--;
}
extern char start, main_text_start, main_text_end, main_data_start, main_data_end, main_rodata_start, main_rodata_end, __bss_start;
/* This has to be in data section, so that it does not get cleared. See crt0.S for details. */
char *gzminpi = (char *)0xdeadbeef;
unsigned gunzipmain(struct linux_romvec *promvec, void *cifh, void *cifs)
{
prom_init(promvec, cifh, cifs);
#ifdef TFTP
prom_puts ("SILO", 4);
#else
prom_puts ("O", 1);
#endif
if (!cifh) {
unsigned short *pt = (unsigned short *)gzminpi;
while (*pt) pt++;
pt++;
while (*pt) pt++;
pt++;
gzminpi = (char *)pt;
}
gzminp = gzminpi;
if (decompress ((char *)0x200000, (char *)&start, get_input, unget_input) == -1) {
printf ("\nInternal error\n");
prom_halt();
}
memcpy (&main_text_start, (char *)0x200000, &main_text_end - &main_text_start);
memcpy (&main_rodata_start, (char *)0x200000 + (&main_text_end - &main_text_start), &main_rodata_end - &main_rodata_start);
memcpy (&main_data_start, (char *)0x200000 + (&main_text_end - &main_text_start) + (&main_rodata_end - &main_rodata_start), &main_data_end - &main_data_start);
if (cifh) {
unsigned char *cp = (char *)0x380000;
unsigned short *pt = (unsigned short *)((char *)0x200000 + (&main_text_end - &main_text_start) +
(&main_rodata_end - &main_rodata_start) + (&main_data_end - &main_data_start));
while (*pt) {
cp += *pt;
pt++;
*cp += 4;
}
pt++;
cp = (char *)0x380000;
while (*pt) {
cp += *pt;
pt++;
*cp += 16;
}
}
return bootmain();
}
|