xref: /kernel/linux/linux-6.6/arch/alpha/boot/misc.c (revision 62306a36)
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