18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * misc.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This is a collection of several routines from gzip-1.0.3 68c2ecf20Sopenharmony_ci * adapted for Linux. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Modified for ARM Linux by Russell King 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Nicolas Pitre <nico@visuaide.com> 1999/04/14 : 138c2ecf20Sopenharmony_ci * For this code to run directly from Flash, all constant variables must 148c2ecf20Sopenharmony_ci * be marked with 'const' and all other variables initialized at run-time 158c2ecf20Sopenharmony_ci * only. This way all non constant variables will end up in the bss segment, 168c2ecf20Sopenharmony_ci * which should point to addresses in RAM and cleared to 0 on start. 178c2ecf20Sopenharmony_ci * This allows for a much quicker boot time. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * Modified for Alpha, from the ARM version, by Jay Estabrook 2003. 208c2ecf20Sopenharmony_ci */ 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include <linux/kernel.h> 238c2ecf20Sopenharmony_ci#include <linux/slab.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define memzero(s,n) memset ((s),0,(n)) 288c2ecf20Sopenharmony_ci#define puts srm_printk 298c2ecf20Sopenharmony_ciextern long srm_printk(const char *, ...) 308c2ecf20Sopenharmony_ci __attribute__ ((format (printf, 1, 2))); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* 338c2ecf20Sopenharmony_ci * gzip delarations 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ci#define OF(args) args 368c2ecf20Sopenharmony_ci#define STATIC static 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_citypedef unsigned char uch; 398c2ecf20Sopenharmony_citypedef unsigned short ush; 408c2ecf20Sopenharmony_citypedef unsigned long ulg; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define WSIZE 0x8000 /* Window size must be at least 32k, */ 438c2ecf20Sopenharmony_ci /* and a power of two */ 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic uch *inbuf; /* input buffer */ 468c2ecf20Sopenharmony_cistatic uch *window; /* Sliding window buffer */ 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic unsigned insize; /* valid bytes in inbuf */ 498c2ecf20Sopenharmony_cistatic unsigned inptr; /* index of next byte to be processed in inbuf */ 508c2ecf20Sopenharmony_cistatic unsigned outcnt; /* bytes in output buffer */ 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* gzip flag byte */ 538c2ecf20Sopenharmony_ci#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 548c2ecf20Sopenharmony_ci#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ 558c2ecf20Sopenharmony_ci#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 568c2ecf20Sopenharmony_ci#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 578c2ecf20Sopenharmony_ci#define COMMENT 0x10 /* bit 4 set: file comment present */ 588c2ecf20Sopenharmony_ci#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ 598c2ecf20Sopenharmony_ci#define RESERVED 0xC0 /* bit 6,7: reserved */ 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* Diagnostic functions */ 648c2ecf20Sopenharmony_ci#ifdef DEBUG 658c2ecf20Sopenharmony_ci# define Assert(cond,msg) {if(!(cond)) error(msg);} 668c2ecf20Sopenharmony_ci# define Trace(x) fprintf x 678c2ecf20Sopenharmony_ci# define Tracev(x) {if (verbose) fprintf x ;} 688c2ecf20Sopenharmony_ci# define Tracevv(x) {if (verbose>1) fprintf x ;} 698c2ecf20Sopenharmony_ci# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} 708c2ecf20Sopenharmony_ci# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} 718c2ecf20Sopenharmony_ci#else 728c2ecf20Sopenharmony_ci# define Assert(cond,msg) 738c2ecf20Sopenharmony_ci# define Trace(x) 748c2ecf20Sopenharmony_ci# define Tracev(x) 758c2ecf20Sopenharmony_ci# define Tracevv(x) 768c2ecf20Sopenharmony_ci# define Tracec(c,x) 778c2ecf20Sopenharmony_ci# define Tracecv(c,x) 788c2ecf20Sopenharmony_ci#endif 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic int fill_inbuf(void); 818c2ecf20Sopenharmony_cistatic void flush_window(void); 828c2ecf20Sopenharmony_cistatic void error(char *m); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic char *input_data; 858c2ecf20Sopenharmony_cistatic int input_data_size; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic uch *output_data; 888c2ecf20Sopenharmony_cistatic ulg output_ptr; 898c2ecf20Sopenharmony_cistatic ulg bytes_out; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic void error(char *m); 928c2ecf20Sopenharmony_cistatic void gzip_mark(void **); 938c2ecf20Sopenharmony_cistatic void gzip_release(void **); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ciextern int end; 968c2ecf20Sopenharmony_cistatic ulg free_mem_ptr; 978c2ecf20Sopenharmony_cistatic ulg free_mem_end_ptr; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci#define HEAP_SIZE 0x3000 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci#include "../../../lib/inflate.c" 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci/* =========================================================================== 1048c2ecf20Sopenharmony_ci * Fill the input buffer. This is called only when the buffer is empty 1058c2ecf20Sopenharmony_ci * and at least one byte is really needed. 1068c2ecf20Sopenharmony_ci */ 1078c2ecf20Sopenharmony_ciint fill_inbuf(void) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci if (insize != 0) 1108c2ecf20Sopenharmony_ci error("ran out of input data"); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci inbuf = input_data; 1138c2ecf20Sopenharmony_ci insize = input_data_size; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci inptr = 1; 1168c2ecf20Sopenharmony_ci return inbuf[0]; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci/* =========================================================================== 1208c2ecf20Sopenharmony_ci * Write the output window window[0..outcnt-1] and update crc and bytes_out. 1218c2ecf20Sopenharmony_ci * (Used for the decompressed data only.) 1228c2ecf20Sopenharmony_ci */ 1238c2ecf20Sopenharmony_civoid flush_window(void) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci ulg c = crc; 1268c2ecf20Sopenharmony_ci unsigned n; 1278c2ecf20Sopenharmony_ci uch *in, *out, ch; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci in = window; 1308c2ecf20Sopenharmony_ci out = &output_data[output_ptr]; 1318c2ecf20Sopenharmony_ci for (n = 0; n < outcnt; n++) { 1328c2ecf20Sopenharmony_ci ch = *out++ = *in++; 1338c2ecf20Sopenharmony_ci c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); 1348c2ecf20Sopenharmony_ci } 1358c2ecf20Sopenharmony_ci crc = c; 1368c2ecf20Sopenharmony_ci bytes_out += (ulg)outcnt; 1378c2ecf20Sopenharmony_ci output_ptr += (ulg)outcnt; 1388c2ecf20Sopenharmony_ci outcnt = 0; 1398c2ecf20Sopenharmony_ci/* puts("."); */ 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic void error(char *x) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci puts("\n\n"); 1458c2ecf20Sopenharmony_ci puts(x); 1468c2ecf20Sopenharmony_ci puts("\n\n -- System halted"); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci while(1); /* Halt */ 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ciunsigned int 1528c2ecf20Sopenharmony_cidecompress_kernel(void *output_start, 1538c2ecf20Sopenharmony_ci void *input_start, 1548c2ecf20Sopenharmony_ci size_t ksize, 1558c2ecf20Sopenharmony_ci size_t kzsize) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci output_data = (uch *)output_start; 1588c2ecf20Sopenharmony_ci input_data = (uch *)input_start; 1598c2ecf20Sopenharmony_ci input_data_size = kzsize; /* use compressed size */ 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci /* FIXME FIXME FIXME */ 1628c2ecf20Sopenharmony_ci free_mem_ptr = (ulg)output_start + ksize; 1638c2ecf20Sopenharmony_ci free_mem_end_ptr = (ulg)output_start + ksize + 0x200000; 1648c2ecf20Sopenharmony_ci /* FIXME FIXME FIXME */ 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci /* put in temp area to reduce initial footprint */ 1678c2ecf20Sopenharmony_ci window = malloc(WSIZE); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci makecrc(); 1708c2ecf20Sopenharmony_ci/* puts("Uncompressing Linux..."); */ 1718c2ecf20Sopenharmony_ci gunzip(); 1728c2ecf20Sopenharmony_ci/* puts(" done, booting the kernel.\n"); */ 1738c2ecf20Sopenharmony_ci return output_ptr; 1748c2ecf20Sopenharmony_ci} 175