misc.c 5.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * misc.c
 * 
 * This is a collection of several routines from gzip-1.0.3 
 * adapted for Linux.
 *
 * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
 *
 * Modified for ARM Linux by Russell King
 *
 * Nicolas Pitre <nico@visuaide.com>  1999/04/14 :
 *  For this code to run directly from Flash, all constant variables must
 *  be marked with 'const' and all other variables initialized at run-time 
 *  only.  This way all non constant variables will end up in the bss segment,
 *  which should point to addresses in RAM and cleared to 0 on start.
 *  This allows for a much quicker boot time.
 */

unsigned int __machine_arch_type;

21 22
#define _LINUX_STRING_H_

23 24 25 26
#include <linux/compiler.h>	/* for inline */
#include <linux/types.h>	/* for size_t */
#include <linux/stddef.h>	/* for NULL */
#include <asm/string.h>
27 28 29
#include <linux/linkage.h>

#include <asm/unaligned.h>
L
Linus Torvalds 已提交
30 31 32

#ifdef STANDALONE_DEBUG
#define putstr printf
33
#else
L
Linus Torvalds 已提交
34

35 36
static void putstr(const char *ptr);

37
#include <mach/uncompress.h>
L
Linus Torvalds 已提交
38

39
#ifdef CONFIG_DEBUG_ICEDCC
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

#ifdef CONFIG_CPU_V6

static void icedcc_putc(int ch)
{
	int status, i = 0x4000000;

	do {
		if (--i < 0)
			return;

		asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status));
	} while (status & (1 << 29));

	asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch));
}
56 57 58 59 60 61 62 63 64 65 66 67

#elif defined(CONFIG_CPU_V7)

static void icedcc_putc(int ch)
{
	asm(
	"wait:	mrc	p14, 0, pc, c0, c1, 0			\n\
		bcs	wait					\n\
		mcr     p14, 0, %0, c0, c5, 0			"
	: : "r" (ch));
}

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
#elif defined(CONFIG_CPU_XSCALE)

static void icedcc_putc(int ch)
{
	int status, i = 0x4000000;

	do {
		if (--i < 0)
			return;

		asm volatile ("mrc p14, 0, %0, c14, c0, 0" : "=r" (status));
	} while (status & (1 << 28));

	asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch));
}
83 84 85

#else

86 87 88 89 90 91 92 93
static void icedcc_putc(int ch)
{
	int status, i = 0x4000000;

	do {
		if (--i < 0)
			return;

94
		asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
95 96
	} while (status & 2);

97
	asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
98 99
}

100 101
#endif

102 103
#define putc(ch)	icedcc_putc(ch)
#endif
L
Linus Torvalds 已提交
104

105
static void putstr(const char *ptr)
L
Linus Torvalds 已提交
106
{
107 108 109 110 111 112
	char c;

	while ((c = *ptr++) != '\0') {
		if (c == '\n')
			putc('\r');
		putc(c);
L
Linus Torvalds 已提交
113
	}
114 115

	flush();
L
Linus Torvalds 已提交
116 117 118 119 120 121
}

#endif

#define __ptr_t void *

R
Russell King 已提交
122 123
#define memzero(s,n) __memzero(s,n)

L
Linus Torvalds 已提交
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
/*
 * Optimised C version of memzero for the ARM.
 */
void __memzero (__ptr_t s, size_t n)
{
	union { void *vp; unsigned long *ulp; unsigned char *ucp; } u;
	int i;

	u.vp = s;

	for (i = n >> 5; i > 0; i--) {
		*u.ulp++ = 0;
		*u.ulp++ = 0;
		*u.ulp++ = 0;
		*u.ulp++ = 0;
		*u.ulp++ = 0;
		*u.ulp++ = 0;
		*u.ulp++ = 0;
		*u.ulp++ = 0;
	}

	if (n & 1 << 4) {
		*u.ulp++ = 0;
		*u.ulp++ = 0;
		*u.ulp++ = 0;
		*u.ulp++ = 0;
	}

	if (n & 1 << 3) {
		*u.ulp++ = 0;
		*u.ulp++ = 0;
	}

	if (n & 1 << 2)
		*u.ulp++ = 0;

	if (n & 1 << 1) {
		*u.ucp++ = 0;
		*u.ucp++ = 0;
	}

	if (n & 1)
		*u.ucp++ = 0;
}

static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
			    size_t __n)
{
	int i = 0;
	unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;

	for (i = __n >> 3; i > 0; i--) {
		*d++ = *s++;
		*d++ = *s++;
		*d++ = *s++;
		*d++ = *s++;
		*d++ = *s++;
		*d++ = *s++;
		*d++ = *s++;
		*d++ = *s++;
	}

	if (__n & 1 << 2) {
		*d++ = *s++;
		*d++ = *s++;
		*d++ = *s++;
		*d++ = *s++;
	}

	if (__n & 1 << 1) {
		*d++ = *s++;
		*d++ = *s++;
	}

	if (__n & 1)
		*d++ = *s++;

	return __dest;
}

/*
 * gzip delarations
 */
#define STATIC static

/* Diagnostic functions */
#ifdef DEBUG
#  define Assert(cond,msg) {if(!(cond)) error(msg);}
#  define Trace(x) fprintf x
#  define Tracev(x) {if (verbose) fprintf x ;}
#  define Tracevv(x) {if (verbose>1) fprintf x ;}
#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
#else
#  define Assert(cond,msg)
#  define Trace(x)
#  define Tracev(x)
#  define Tracevv(x)
#  define Tracec(c,x)
#  define Tracecv(c,x)
#endif

static void error(char *m);

extern char input_data[];
extern char input_data_end[];

231 232
static unsigned char *output_data;
static unsigned long output_ptr;
L
Linus Torvalds 已提交
233 234 235 236 237

static void error(char *m);

static void putstr(const char *);

238 239
static unsigned long free_mem_ptr;
static unsigned long free_mem_end_ptr;
L
Linus Torvalds 已提交
240

241 242 243
#ifdef STANDALONE_DEBUG
#define NO_INFLATE_MALLOC
#endif
L
Linus Torvalds 已提交
244

245
#define ARCH_HAS_DECOMP_WDOG
L
Linus Torvalds 已提交
246

247 248 249
#ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/decompress_inflate.c"
#endif
L
Linus Torvalds 已提交
250

251 252 253
#ifdef CONFIG_KERNEL_LZO
#include "../../../../lib/decompress_unlzo.c"
#endif
L
Linus Torvalds 已提交
254

255 256 257 258
#ifndef arch_error
#define arch_error(x)
#endif

L
Linus Torvalds 已提交
259 260
static void error(char *x)
{
261 262
	arch_error(x);

L
Linus Torvalds 已提交
263 264 265 266 267 268 269
	putstr("\n\n");
	putstr(x);
	putstr("\n\n -- System halted");

	while(1);	/* Halt */
}

270 271 272 273 274
asmlinkage void __div0(void)
{
	error("Attempting division by 0!");
}

L
Linus Torvalds 已提交
275 276
#ifndef STANDALONE_DEBUG

277 278 279 280
unsigned long
decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
		unsigned long free_mem_ptr_end_p,
		int arch_id)
L
Linus Torvalds 已提交
281
{
282 283 284
	unsigned char *tmp;

	output_data		= (unsigned char *)output_start;
L
Linus Torvalds 已提交
285
	free_mem_ptr		= free_mem_ptr_p;
286
	free_mem_end_ptr	= free_mem_ptr_end_p;
L
Linus Torvalds 已提交
287 288 289 290
	__machine_arch_type	= arch_id;

	arch_decomp_setup();

291 292 293
	tmp = (unsigned char *) (((unsigned long)input_data_end) - 4);
	output_ptr = get_unaligned_le32(tmp);

L
Linus Torvalds 已提交
294
	putstr("Uncompressing Linux...");
295 296
	decompress(input_data, input_data_end - input_data,
			NULL, NULL, output_data, NULL, error);
L
Linus Torvalds 已提交
297 298 299 300 301 302 303 304 305 306 307 308
	putstr(" done, booting the kernel.\n");
	return output_ptr;
}
#else

char output_buffer[1500*1024];

int main()
{
	output_data = output_buffer;

	putstr("Uncompressing Linux...");
309 310
	decompress(input_data, input_data_end - input_data,
			NULL, NULL, output_data, NULL, error);
L
Linus Torvalds 已提交
311 312 313 314
	putstr("done.\n");
	return 0;
}
#endif