162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
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 * Adapted for SH by Stuart Menefy, Aug 1999
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * Based on arch/sh/boot/compressed/misc.c
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <linux/string.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/*
2062306a36Sopenharmony_ci * gzip declarations
2162306a36Sopenharmony_ci */
2262306a36Sopenharmony_ci#define OF(args)  args
2362306a36Sopenharmony_ci#define STATIC static
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#undef memset
2662306a36Sopenharmony_ci#undef memcpy
2762306a36Sopenharmony_ci#define memzero(s, n)		memset((s), 0, (n))
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_citypedef unsigned char  uch;
3062306a36Sopenharmony_citypedef unsigned short ush;
3162306a36Sopenharmony_citypedef unsigned long  ulg;
3262306a36Sopenharmony_ci#define WSIZE 0x8000		/* Window size must be at least 32k, */
3362306a36Sopenharmony_ci				/* and a power of two */
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistatic uch *inbuf;		/* input buffer */
3662306a36Sopenharmony_cistatic uch window[WSIZE];	/* Sliding window buffer */
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic unsigned insize;	/* valid bytes in inbuf */
3962306a36Sopenharmony_cistatic unsigned inptr;	/* index of next byte to be processed in inbuf */
4062306a36Sopenharmony_cistatic unsigned outcnt;	/* bytes in output buffer */
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/* gzip flag byte */
4362306a36Sopenharmony_ci#define ASCII_FLAG	0x01 /* bit 0 set: file probably ASCII text */
4462306a36Sopenharmony_ci#define CONTINUATION	0x02 /* bit 1 set: continuation of multi-part gzip
4562306a36Sopenharmony_ci				file */
4662306a36Sopenharmony_ci#define EXTRA_FIELD	0x04 /* bit 2 set: extra field present */
4762306a36Sopenharmony_ci#define ORIG_NAME	0x08 /* bit 3 set: original file name present */
4862306a36Sopenharmony_ci#define COMMENT		0x10 /* bit 4 set: file comment present */
4962306a36Sopenharmony_ci#define ENCRYPTED	0x20 /* bit 5 set: file is encrypted */
5062306a36Sopenharmony_ci#define RESERVED	0xC0 /* bit 6,7:   reserved */
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#ifdef DEBUG
5562306a36Sopenharmony_ci#  define Assert(cond, msg) {if (!(cond)) error(msg); }
5662306a36Sopenharmony_ci#  define Trace(x) fprintf x
5762306a36Sopenharmony_ci#  define Tracev(x) {if (verbose) fprintf x ; }
5862306a36Sopenharmony_ci#  define Tracevv(x) {if (verbose > 1) fprintf x ; }
5962306a36Sopenharmony_ci#  define Tracec(c, x) {if (verbose && (c)) fprintf x ; }
6062306a36Sopenharmony_ci#  define Tracecv(c, x) {if (verbose > 1 && (c)) fprintf x ; }
6162306a36Sopenharmony_ci#else
6262306a36Sopenharmony_ci#  define Assert(cond, msg)
6362306a36Sopenharmony_ci#  define Trace(x)
6462306a36Sopenharmony_ci#  define Tracev(x)
6562306a36Sopenharmony_ci#  define Tracevv(x)
6662306a36Sopenharmony_ci#  define Tracec(c, x)
6762306a36Sopenharmony_ci#  define Tracecv(c, x)
6862306a36Sopenharmony_ci#endif
6962306a36Sopenharmony_cistatic int  fill_inbuf(void);
7062306a36Sopenharmony_cistatic void flush_window(void);
7162306a36Sopenharmony_cistatic void error(char *m);
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ciextern char input_data[];
7462306a36Sopenharmony_ciextern int input_len;
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic long bytes_out;
7762306a36Sopenharmony_cistatic uch *output_data;
7862306a36Sopenharmony_cistatic unsigned long output_ptr;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#include "console.c"
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic void error(char *m);
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ciint puts(const char *);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ciextern int _end;
8762306a36Sopenharmony_cistatic unsigned long free_mem_ptr;
8862306a36Sopenharmony_cistatic unsigned long free_mem_end_ptr;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#define HEAP_SIZE			0x10000
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci#include "../../../../lib/inflate.c"
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_civoid *memset(void *s, int c, size_t n)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	int i;
9762306a36Sopenharmony_ci	char *ss = (char *)s;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	for (i = 0; i < n; i++)
10062306a36Sopenharmony_ci		ss[i] = c;
10162306a36Sopenharmony_ci	return s;
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_civoid *memcpy(void *__dest, __const void *__src, size_t __n)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	int i;
10762306a36Sopenharmony_ci	char *d = (char *)__dest, *s = (char *)__src;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	for (i = 0; i < __n; i++)
11062306a36Sopenharmony_ci		d[i] = s[i];
11162306a36Sopenharmony_ci	return __dest;
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci/*
11562306a36Sopenharmony_ci * Fill the input buffer. This is called only when the buffer is empty
11662306a36Sopenharmony_ci * and at least one byte is really needed.
11762306a36Sopenharmony_ci */
11862306a36Sopenharmony_cistatic int fill_inbuf(void)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	if (insize != 0)
12162306a36Sopenharmony_ci		error("ran out of input data");
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	inbuf = input_data;
12462306a36Sopenharmony_ci	insize = input_len;
12562306a36Sopenharmony_ci	inptr = 1;
12662306a36Sopenharmony_ci	return inbuf[0];
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci/*
13062306a36Sopenharmony_ci * Write the output window window[0..outcnt-1] and update crc and bytes_out.
13162306a36Sopenharmony_ci * (Used for the decompressed data only.)
13262306a36Sopenharmony_ci */
13362306a36Sopenharmony_cistatic void flush_window(void)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	ulg c = crc;	/* temporary variable */
13662306a36Sopenharmony_ci	unsigned n;
13762306a36Sopenharmony_ci	uch *in, *out, ch;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	in = window;
14062306a36Sopenharmony_ci	out = &output_data[output_ptr];
14162306a36Sopenharmony_ci	for (n = 0; n < outcnt; n++) {
14262306a36Sopenharmony_ci		ch = *out++ = *in++;
14362306a36Sopenharmony_ci		c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
14462306a36Sopenharmony_ci	}
14562306a36Sopenharmony_ci	crc = c;
14662306a36Sopenharmony_ci	bytes_out += (ulg)outcnt;
14762306a36Sopenharmony_ci	output_ptr += (ulg)outcnt;
14862306a36Sopenharmony_ci	outcnt = 0;
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic void error(char *x)
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	puts("\nERROR\n");
15462306a36Sopenharmony_ci	puts(x);
15562306a36Sopenharmony_ci	puts("\n\n -- System halted");
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	while (1)	/* Halt */
15862306a36Sopenharmony_ci		;
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_civoid decompress_kernel(void)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	output_data = (void *) (CONFIG_NIOS2_MEM_BASE |
16462306a36Sopenharmony_ci				CONFIG_NIOS2_KERNEL_REGION_BASE);
16562306a36Sopenharmony_ci	output_ptr = 0;
16662306a36Sopenharmony_ci	free_mem_ptr = (unsigned long)&_end;
16762306a36Sopenharmony_ci	free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	console_init();
17062306a36Sopenharmony_ci	makecrc();
17162306a36Sopenharmony_ci	puts("Uncompressing Linux... ");
17262306a36Sopenharmony_ci	gunzip();
17362306a36Sopenharmony_ci	puts("Ok, booting the kernel.\n");
17462306a36Sopenharmony_ci}
175