1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * "Compressed" file system File: zipstart_readz.c 5 * 6 * This module calls ZLIB to read a compressed file so we 7 * can boot compressed versions of CFE. 8 * 9 * Author: Mitch Lichtenberg (mpl@broadcom.com) 10 * 11 ********************************************************************* 12 * 13 * Copyright 2000,2001,2002,2003 14 * Broadcom Corporation. All rights reserved. 15 * 16 * This software is furnished under license and may be used and 17 * copied only in accordance with the following terms and 18 * conditions. Subject to these conditions, you may download, 19 * copy, install, use, modify and distribute modified or unmodified 20 * copies of this software in source and/or binary form. No title 21 * or ownership is transferred hereby. 22 * 23 * 1) Any source code used, modified or distributed must reproduce 24 * and retain this copyright notice and list of conditions 25 * as they appear in the source file. 26 * 27 * 2) No right is granted to use any trade name, trademark, or 28 * logo of Broadcom Corporation. The "Broadcom Corporation" 29 * name may not be used to endorse or promote products derived 30 * from this software without the prior written permission of 31 * Broadcom Corporation. 32 * 33 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 34 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 35 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 36 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 37 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 38 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 39 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 40 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 41 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 42 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 43 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 44 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 45 * THE POSSIBILITY OF SUCH DAMAGE. 46 ********************************************************************* */ 47 48#if CFG_ZLIB 49 50#include "cfe.h" 51#include "zipstart.h" 52#include "zlib.h" 53 54/* ********************************************************************* 55 * ZLIBFS context 56 ********************************************************************* */ 57 58/* 59 * File context - describes an open file on the file system. 60 * For raw devices, this is pretty meaningless, but we do 61 * keep track of where we are. 62 */ 63 64#define ZLIBFS_BUFSIZE 1024 65typedef struct zlibfs_file_s { 66 int zlibfs_fileoffset; 67 z_stream zlibfs_stream; 68 uint8_t *zlibfs_inbuf; 69 uint8_t *zlibfs_outbuf; 70 int zlibfs_outlen; 71 uint8_t *zlibfs_outptr; 72 int zlibfs_eofseen; 73 74 /* Pointers to zip data we are reading */ 75 uint8_t *zlibfs_inptr; 76 int zlibfs_inlen; 77} zlibfs_file_t; 78 79/* ********************************************************************* 80 * Globals 81 ********************************************************************* */ 82 83zlibfs_file_t rz_file; 84uint8_t rz_inbuf[ZLIBFS_BUFSIZE]; 85uint8_t rz_outbuf[ZLIBFS_BUFSIZE]; 86 87/* ********************************************************************* 88 * Prototypes 89 ********************************************************************* */ 90 91voidpf zcalloc(voidpf opaque,unsigned items, unsigned size); 92void zcfree(voidpf opaque,voidpf ptr); 93 94/* ********************************************************************* 95 * ZLIB fileio dispatch table 96 ********************************************************************* */ 97 98 99static uint8_t gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ 100 101 102/* gzip flag byte */ 103#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 104#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ 105#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 106#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 107#define COMMENT 0x10 /* bit 4 set: file comment present */ 108#define RESERVED 0xE0 /* bits 5..7: reserved */ 109 110 111static void rz_memcpy(uint8_t *dst,uint8_t *src,int len) 112{ 113 while (len > 0) { 114 *dst++ = *src++; 115 len--; 116 } 117} 118 119static void rz_memset(uint8_t *dst,int c,int cnt) 120{ 121 while (cnt > 0) { 122 *dst++ = (uint8_t) c; 123 cnt--; 124 } 125} 126 127/* 128 * Utility functions needed by the ZLIB routines 129 */ 130voidpf zcalloc(voidpf opaque,unsigned items, unsigned size) 131{ 132 void *ptr; 133 134 ptr = zs_malloc(items*size); 135 if (ptr) rz_memset(ptr,0,items*size); 136 return ptr; 137} 138 139void zcfree(voidpf opaque,voidpf ptr) 140{ 141 return zs_free(ptr); 142} 143 144 145 146static int get_byte(zlibfs_file_t *file,uint8_t *ch) 147{ 148 if (file->zlibfs_inlen > 0) { 149 *ch = *(file->zlibfs_inptr++); 150 file->zlibfs_inlen--; 151 return 1; 152 } 153 else { 154 return 0; 155 } 156 157} 158 159 160static int check_header(zlibfs_file_t *file) 161{ 162 int method; /* method byte */ 163 int flags; /* flags byte */ 164 uInt len; 165 uint8_t c; 166 int res; 167 168 /* Check the gzip magic header */ 169 for (len = 0; len < 2; len++) { 170 res = get_byte(file,&c); 171 if (c != gz_magic[len]) { 172 return -1; 173 } 174 } 175 176 get_byte(file,&c); method = (int) c; 177 get_byte(file,&c); flags = (int) c; 178 179 if (method != Z_DEFLATED || (flags & RESERVED) != 0) { 180 return -1; 181 } 182 183 /* Discard time, xflags and OS code: */ 184 for (len = 0; len < 6; len++) (void)get_byte(file,&c); 185 186 if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ 187 get_byte(file,&c); 188 len = (uInt) c; 189 get_byte(file,&c); 190 len += ((uInt)c)<<8; 191 /* len is garbage if EOF but the loop below will quit anyway */ 192 while ((len-- != 0) && (get_byte(file,&c) == 1)) ; 193 } 194 if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ 195 while ((get_byte(file,&c) == 1) && (c != 0)) ; 196 } 197 if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ 198 while ((get_byte(file,&c) == 1) && (c != 0)) ; 199 } 200 if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ 201 for (len = 0; len < 2; len++) (void)get_byte(file,&c); 202 } 203 204 return 0; 205} 206 207int rz_init(uint8_t *inptr,int len) 208{ 209 zlibfs_file_t *file = &rz_file; 210 int err; 211 212 213 file->zlibfs_fileoffset = 0; 214 file->zlibfs_inbuf = NULL; 215 file->zlibfs_outbuf = NULL; 216 file->zlibfs_eofseen = 0; 217 218 file->zlibfs_inptr = inptr; 219 file->zlibfs_inlen = len; 220 221 /* Open the zstream */ 222 223 file->zlibfs_inbuf = rz_inbuf; 224 file->zlibfs_outbuf = rz_outbuf; 225 226 file->zlibfs_stream.next_in = NULL; 227 file->zlibfs_stream.avail_in = 0; 228 file->zlibfs_stream.next_out = file->zlibfs_outbuf; 229 file->zlibfs_stream.avail_out = ZLIBFS_BUFSIZE; 230 file->zlibfs_stream.zalloc = (alloc_func)0; 231 file->zlibfs_stream.zfree = (free_func)0; 232 233 file->zlibfs_outlen = 0; 234 file->zlibfs_outptr = file->zlibfs_outbuf; 235 236 err = inflateInit2(&(file->zlibfs_stream),-15); 237 if (err != Z_OK) { 238 return -1; 239 } 240 241 check_header(file); 242 243 return 0; 244} 245 246int rz_read(uint8_t *buf,int len) 247{ 248 zlibfs_file_t *file = &rz_file; 249 int res = 0; 250 int err; 251 int amtcopy; 252 int ttlcopy = 0; 253 254 if (len == 0) return 0; 255 256 while (len) { 257 258 /* Figure the amount to copy. This is the min of what we 259 have left to do and what is available. */ 260 amtcopy = len; 261 if (amtcopy > file->zlibfs_outlen) { 262 amtcopy = file->zlibfs_outlen; 263 } 264 265 /* Copy the data. */ 266 267 if (buf) { 268 rz_memcpy(buf,file->zlibfs_outptr,amtcopy); 269 buf += amtcopy; 270 } 271 272 /* Update the pointers. */ 273 file->zlibfs_outptr += amtcopy; 274 file->zlibfs_outlen -= amtcopy; 275 len -= amtcopy; 276 ttlcopy += amtcopy; 277 278 /* If we've eaten all of the output, reset and call inflate 279 again. */ 280 281 if (file->zlibfs_outlen == 0) { 282 /* If no input data to decompress, get some more if we can. */ 283 if (file->zlibfs_eofseen) break; 284 if (file->zlibfs_stream.avail_in == 0) { 285 int amtcopy; 286 uint8_t *src,*dst; 287 288 amtcopy = file->zlibfs_inlen; 289 if (amtcopy > ZLIBFS_BUFSIZE) amtcopy = ZLIBFS_BUFSIZE; 290 res = amtcopy; 291 292 if (amtcopy > 0) { 293 src = file->zlibfs_inptr; 294 dst = file->zlibfs_inbuf; 295 file->zlibfs_inptr += amtcopy; 296 file->zlibfs_inlen -= amtcopy; 297 file->zlibfs_stream.next_in = file->zlibfs_inbuf; 298 file->zlibfs_stream.avail_in = amtcopy; 299 rz_memcpy(dst,src,amtcopy); 300 } 301 else break; 302 } 303 304 /* inflate the input data. */ 305 file->zlibfs_stream.next_out = file->zlibfs_outbuf; 306 file->zlibfs_stream.avail_out = ZLIBFS_BUFSIZE; 307 file->zlibfs_outptr = file->zlibfs_outbuf; 308 err = inflate(&(file->zlibfs_stream),Z_SYNC_FLUSH); 309 if (err == Z_STREAM_END) { 310 /* We can get a partial buffer fill here. */ 311 file->zlibfs_eofseen = 1; 312 } 313 else if (err != Z_OK) { 314 putstr("rz_read error"); putdec(0-err); 315 316 res = -1; 317 break; 318 } 319 file->zlibfs_outlen = file->zlibfs_stream.next_out - 320 file->zlibfs_outptr; 321 } 322 323 } 324 325 file->zlibfs_fileoffset += ttlcopy; 326 327 return (res < 0) ? res : ttlcopy; 328} 329 330 331void rz_close(void) 332{ 333 zlibfs_file_t *file = &rz_file; 334 335 inflateEnd(&(file->zlibfs_stream)); 336} 337 338 339#endif 340