1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19unsigned int __machine_arch_type;
20
21#include <linux/compiler.h>
22#include <linux/types.h>
23#include <linux/linkage.h>
24
25static void putstr(const char *ptr);
26extern void error(char *x);
27
28#ifdef CONFIG_ARCH_MULTIPLATFORM
29static inline void putc(int c) {}
30static inline void flush(void) {}
31static inline void arch_decomp_setup(void) {}
32#else
33#include <mach/uncompress.h>
34#endif
35
36#ifdef CONFIG_DEBUG_ICEDCC
37
38#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
39
40static void icedcc_putc(int ch)
41{
42 int status, i = 0x4000000;
43
44 do {
45 if (--i < 0)
46 return;
47
48 asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status));
49 } while (status & (1 << 29));
50
51 asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch));
52}
53
54
55#elif defined(CONFIG_CPU_XSCALE)
56
57static void icedcc_putc(int ch)
58{
59 int status, i = 0x4000000;
60
61 do {
62 if (--i < 0)
63 return;
64
65 asm volatile ("mrc p14, 0, %0, c14, c0, 0" : "=r" (status));
66 } while (status & (1 << 28));
67
68 asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch));
69}
70
71#else
72
73static void icedcc_putc(int ch)
74{
75 int status, i = 0x4000000;
76
77 do {
78 if (--i < 0)
79 return;
80
81 asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
82 } while (status & 2);
83
84 asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
85}
86
87#endif
88
89#define putc(ch) icedcc_putc(ch)
90#endif
91
92static void putstr(const char *ptr)
93{
94 char c;
95
96 while ((c = *ptr++) != '\0') {
97 if (c == '\n')
98 putc('\r');
99 putc(c);
100 }
101
102 flush();
103}
104
105
106
107
108extern char input_data[];
109extern char input_data_end[];
110
111unsigned char *output_data;
112
113unsigned long free_mem_ptr;
114unsigned long free_mem_end_ptr;
115
116#ifndef arch_error
117#define arch_error(x)
118#endif
119
120void error(char *x)
121{
122 arch_error(x);
123
124 putstr("\n\n");
125 putstr(x);
126 putstr("\n\n -- System halted");
127
128 while(1);
129}
130
131asmlinkage void __div0(void)
132{
133 error("Attempting division by 0!");
134}
135
136extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
137
138
139void
140decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
141 unsigned long free_mem_ptr_end_p,
142 int arch_id)
143{
144 int ret;
145
146 output_data = (unsigned char *)output_start;
147 free_mem_ptr = free_mem_ptr_p;
148 free_mem_end_ptr = free_mem_ptr_end_p;
149 __machine_arch_type = arch_id;
150
151 arch_decomp_setup();
152
153 putstr("Uncompressing Linux...");
154 ret = do_decompress(input_data, input_data_end - input_data,
155 output_data, error);
156 if (ret)
157 error("decompressor returned an error");
158 else
159 putstr(" done, booting the kernel.\n");
160}
161