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