162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * misc.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This is a collection of several routines from gzip-1.0.3 662306a36Sopenharmony_ci * adapted for Linux. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Modified for ARM Linux by Russell King 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Nicolas Pitre <nico@visuaide.com> 1999/04/14 : 1362306a36Sopenharmony_ci * For this code to run directly from Flash, all constant variables must 1462306a36Sopenharmony_ci * be marked with 'const' and all other variables initialized at run-time 1562306a36Sopenharmony_ci * only. This way all non constant variables will end up in the bss segment, 1662306a36Sopenharmony_ci * which should point to addresses in RAM and cleared to 0 on start. 1762306a36Sopenharmony_ci * This allows for a much quicker boot time. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * Modified for Alpha, from the ARM version, by Jay Estabrook 2003. 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <linux/kernel.h> 2362306a36Sopenharmony_ci#include <linux/slab.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include <linux/uaccess.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define memzero(s,n) memset ((s),0,(n)) 2862306a36Sopenharmony_ci#define puts srm_printk 2962306a36Sopenharmony_ciextern long srm_printk(const char *, ...) 3062306a36Sopenharmony_ci __attribute__ ((format (printf, 1, 2))); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* 3362306a36Sopenharmony_ci * gzip declarations 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci#define OF(args) args 3662306a36Sopenharmony_ci#define STATIC static 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_citypedef unsigned char uch; 3962306a36Sopenharmony_citypedef unsigned short ush; 4062306a36Sopenharmony_citypedef unsigned long ulg; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define WSIZE 0x8000 /* Window size must be at least 32k, */ 4362306a36Sopenharmony_ci /* and a power of two */ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic uch *inbuf; /* input buffer */ 4662306a36Sopenharmony_cistatic uch *window; /* Sliding window buffer */ 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic unsigned insize; /* valid bytes in inbuf */ 4962306a36Sopenharmony_cistatic unsigned inptr; /* index of next byte to be processed in inbuf */ 5062306a36Sopenharmony_cistatic unsigned outcnt; /* bytes in output buffer */ 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* gzip flag byte */ 5362306a36Sopenharmony_ci#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 5462306a36Sopenharmony_ci#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ 5562306a36Sopenharmony_ci#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 5662306a36Sopenharmony_ci#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 5762306a36Sopenharmony_ci#define COMMENT 0x10 /* bit 4 set: file comment present */ 5862306a36Sopenharmony_ci#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ 5962306a36Sopenharmony_ci#define RESERVED 0xC0 /* bit 6,7: reserved */ 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/* Diagnostic functions */ 6462306a36Sopenharmony_ci#ifdef DEBUG 6562306a36Sopenharmony_ci# define Assert(cond,msg) {if(!(cond)) error(msg);} 6662306a36Sopenharmony_ci# define Trace(x) fprintf x 6762306a36Sopenharmony_ci# define Tracev(x) {if (verbose) fprintf x ;} 6862306a36Sopenharmony_ci# define Tracevv(x) {if (verbose>1) fprintf x ;} 6962306a36Sopenharmony_ci# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} 7062306a36Sopenharmony_ci# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} 7162306a36Sopenharmony_ci#else 7262306a36Sopenharmony_ci# define Assert(cond,msg) 7362306a36Sopenharmony_ci# define Trace(x) 7462306a36Sopenharmony_ci# define Tracev(x) 7562306a36Sopenharmony_ci# define Tracevv(x) 7662306a36Sopenharmony_ci# define Tracec(c,x) 7762306a36Sopenharmony_ci# define Tracecv(c,x) 7862306a36Sopenharmony_ci#endif 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic int fill_inbuf(void); 8162306a36Sopenharmony_cistatic void flush_window(void); 8262306a36Sopenharmony_cistatic void error(char *m); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic char *input_data; 8562306a36Sopenharmony_cistatic int input_data_size; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic uch *output_data; 8862306a36Sopenharmony_cistatic ulg output_ptr; 8962306a36Sopenharmony_cistatic ulg bytes_out; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic void error(char *m); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ciextern int end; 9462306a36Sopenharmony_cistatic ulg free_mem_ptr; 9562306a36Sopenharmony_cistatic ulg free_mem_end_ptr; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define HEAP_SIZE 0x3000 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci#include "../../../lib/inflate.c" 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/* =========================================================================== 10262306a36Sopenharmony_ci * Fill the input buffer. This is called only when the buffer is empty 10362306a36Sopenharmony_ci * and at least one byte is really needed. 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_ciint fill_inbuf(void) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci if (insize != 0) 10862306a36Sopenharmony_ci error("ran out of input data"); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci inbuf = input_data; 11162306a36Sopenharmony_ci insize = input_data_size; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci inptr = 1; 11462306a36Sopenharmony_ci return inbuf[0]; 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/* =========================================================================== 11862306a36Sopenharmony_ci * Write the output window window[0..outcnt-1] and update crc and bytes_out. 11962306a36Sopenharmony_ci * (Used for the decompressed data only.) 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_civoid flush_window(void) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci ulg c = crc; 12462306a36Sopenharmony_ci unsigned n; 12562306a36Sopenharmony_ci uch *in, *out, ch; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci in = window; 12862306a36Sopenharmony_ci out = &output_data[output_ptr]; 12962306a36Sopenharmony_ci for (n = 0; n < outcnt; n++) { 13062306a36Sopenharmony_ci ch = *out++ = *in++; 13162306a36Sopenharmony_ci c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci crc = c; 13462306a36Sopenharmony_ci bytes_out += (ulg)outcnt; 13562306a36Sopenharmony_ci output_ptr += (ulg)outcnt; 13662306a36Sopenharmony_ci outcnt = 0; 13762306a36Sopenharmony_ci/* puts("."); */ 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic void error(char *x) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci puts("\n\n"); 14362306a36Sopenharmony_ci puts(x); 14462306a36Sopenharmony_ci puts("\n\n -- System halted"); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci while(1); /* Halt */ 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ciunsigned int 15062306a36Sopenharmony_cidecompress_kernel(void *output_start, 15162306a36Sopenharmony_ci void *input_start, 15262306a36Sopenharmony_ci size_t ksize, 15362306a36Sopenharmony_ci size_t kzsize) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci output_data = (uch *)output_start; 15662306a36Sopenharmony_ci input_data = (uch *)input_start; 15762306a36Sopenharmony_ci input_data_size = kzsize; /* use compressed size */ 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci /* FIXME FIXME FIXME */ 16062306a36Sopenharmony_ci free_mem_ptr = (ulg)output_start + ksize; 16162306a36Sopenharmony_ci free_mem_end_ptr = (ulg)output_start + ksize + 0x200000; 16262306a36Sopenharmony_ci /* FIXME FIXME FIXME */ 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci /* put in temp area to reduce initial footprint */ 16562306a36Sopenharmony_ci window = malloc(WSIZE); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci makecrc(); 16862306a36Sopenharmony_ci/* puts("Uncompressing Linux..."); */ 16962306a36Sopenharmony_ci gunzip(); 17062306a36Sopenharmony_ci/* puts(" done, booting the kernel.\n"); */ 17162306a36Sopenharmony_ci return output_ptr; 17262306a36Sopenharmony_ci} 173