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 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) Helge Deller <deller@gmx.de>
*/
#ifdef __hpux
# define _LINUX_TYPES_H
#endif
#include "common.h"
#include "load.h"
#include <stdio.h>
#ifndef NULL
#define NULL (void *)0
#endif
/*
* gzip declarations
*/
#ifdef IPL_LOADER
# include "bootloader.h"
#else
# include <setjmp.h>
# include <string.h>
# include <stdlib.h>
# define pa_memcpy memcpy
# define mark gzip_mark
# define release gzip_release
#endif
# define gzip_mark(ptr) do { *ptr = 0UL; } while (0)
# define gzip_release(x) do { } while (0)
static void pa_free(void *ptr) { }
#define pa_malloc malloc
#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 *);
static long bytes_out;
static uch *output_data, *output_limit;
/* gzbuffer is the buffer in which we keep the uncompressed gzip data */
#define GZBUFFER_SIZE (4096*2)
static unsigned char gzbuffer[GZBUFFER_SIZE];
static int orig_fd; /* file descriptor for seekread */
static int blocknr;
static int gzminp;
static unsigned char get_byte(void)
{
if (gzminp == GZBUFFER_SIZE) {
blocknr++;
STRUCTREAD(orig_fd, gzbuffer, blocknr * GZBUFFER_SIZE);
gzminp = 0;
}
return gzbuffer[gzminp++];
}
static void unget_byte(void)
{
if (gzminp == 0) {
blocknr--;
STRUCTREAD(orig_fd, gzbuffer, blocknr * GZBUFFER_SIZE);
gzminp = GZBUFFER_SIZE;
}
gzminp--;
}
static jmp_buf gunzip_env;
#include "../lib/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 ("\nuncompressed 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;
/* show progress indicator */
printf(".");
bytes_out += (ulg) outcnt;
outcnt = 0;
}
static long decompress(char *outptr, char *outptrlim)
{
void *save_ptr;
static int first = 1;
gzip_mark (&save_ptr);
if (setjmp (gunzip_env)) {
gzip_release (&save_ptr);
return -1;
}
output_data = (uch *)outptr;
output_limit = (uch *)outptrlim;
bytes_out = 0;
outcnt = 0;
crc = 0xffffffffL;
if (first) {
makecrc ();
first = 0;
}
gunzip ();
gzip_release (&save_ptr);
return bytes_out;
}
#define GZIP_MAGIC0 0x1f
#define GZIP_MAGIC1 0x8b
#define GZIP_MAGIC2 0x08 /* DEFLATED */
int prepare_GZIP_loadable(int fd, struct loadable *loadable, int *wide)
{
unsigned char flags;
long bytes_len;
char *orig_filename = "unknown";
char *outptr, *outptrlim;
int i;
void *release_all_mallocs, *keep_unzipped;
blocknr = 0;
gzminp = 0;
orig_fd = fd;
STRUCTREAD(orig_fd, gzbuffer, 0);
if (gzbuffer[0] != GZIP_MAGIC0 ||
gzbuffer[1] != GZIP_MAGIC1 ||
gzbuffer[2] != GZIP_MAGIC2)
{
return PREPARE_CONTINUE;
}
flags = gzbuffer[3]; /* general flags */
if (flags & ORIG_NAME)
orig_filename = (char *) &gzbuffer[10];
mark(&release_all_mallocs);
#define MAX_GZ_LEN (100*1024*1024)
outptr = (char *) pa_malloc(MAX_GZ_LEN);
mark(&keep_unzipped);
outptrlim = outptr + MAX_GZ_LEN;
if (0)
printf("uncompressing %s to 0x%p", orig_filename, outptr);
else
printf("uncompressing Linux kernel");
bytes_len = decompress(outptr, outptrlim);
if (bytes_len > MAX_GZ_LEN)
printf("\nERROR: Internal buffer MAX_GZ_LEN too small!");
if (bytes_len < 0) {
release(release_all_mallocs);
return PREPARE_CONTINUE;
}
release(keep_unzipped);
loadable->uncompressed_size = bytes_len;
loadable->uncompressed_data = outptr;
if (0)
printf("\nGZIP compressed file size = %lu\n", bytes_len);
else
printf("\n");
/* try to detect real 32 or 64bit kernel now */
i = prepare_ELF32_loadable(fd, loadable, wide);
if (i != PREPARE_OK)
i = prepare_ELF64_loadable(fd, loadable, wide);
if (i != PREPARE_OK)
release(release_all_mallocs);
return i;
}
|