Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[pandora-kernel.git] / arch / arm / boot / compressed / misc.c
1 /*
2  * misc.c
3  * 
4  * This is a collection of several routines from gzip-1.0.3 
5  * adapted for Linux.
6  *
7  * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
8  *
9  * Modified for ARM Linux by Russell King
10  *
11  * Nicolas Pitre <nico@visuaide.com>  1999/04/14 :
12  *  For this code to run directly from Flash, all constant variables must
13  *  be marked with 'const' and all other variables initialized at run-time 
14  *  only.  This way all non constant variables will end up in the bss segment,
15  *  which should point to addresses in RAM and cleared to 0 on start.
16  *  This allows for a much quicker boot time.
17  */
18
19 unsigned int __machine_arch_type;
20
21 #include <linux/compiler.h>     /* for inline */
22 #include <linux/types.h>
23 #include <linux/linkage.h>
24
25 static void putstr(const char *ptr);
26 extern void error(char *x);
27
28 #include <mach/uncompress.h>
29
30 #ifdef CONFIG_DEBUG_ICEDCC
31
32 #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
33
34 static void icedcc_putc(int ch)
35 {
36         int status, i = 0x4000000;
37
38         do {
39                 if (--i < 0)
40                         return;
41
42                 asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status));
43         } while (status & (1 << 29));
44
45         asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch));
46 }
47
48
49 #elif defined(CONFIG_CPU_XSCALE)
50
51 static void icedcc_putc(int ch)
52 {
53         int status, i = 0x4000000;
54
55         do {
56                 if (--i < 0)
57                         return;
58
59                 asm volatile ("mrc p14, 0, %0, c14, c0, 0" : "=r" (status));
60         } while (status & (1 << 28));
61
62         asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch));
63 }
64
65 #else
66
67 static void icedcc_putc(int ch)
68 {
69         int status, i = 0x4000000;
70
71         do {
72                 if (--i < 0)
73                         return;
74
75                 asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
76         } while (status & 2);
77
78         asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
79 }
80
81 #endif
82
83 #define putc(ch)        icedcc_putc(ch)
84 #endif
85
86 static void putstr(const char *ptr)
87 {
88         char c;
89
90         while ((c = *ptr++) != '\0') {
91                 if (c == '\n')
92                         putc('\r');
93                 putc(c);
94         }
95
96         flush();
97 }
98
99 /*
100  * gzip declarations
101  */
102 extern char input_data[];
103 extern char input_data_end[];
104
105 unsigned char *output_data;
106
107 unsigned long free_mem_ptr;
108 unsigned long free_mem_end_ptr;
109
110 #ifndef arch_error
111 #define arch_error(x)
112 #endif
113
114 void error(char *x)
115 {
116         arch_error(x);
117
118         putstr("\n\n");
119         putstr(x);
120         putstr("\n\n -- System halted");
121
122         while(1);       /* Halt */
123 }
124
125 asmlinkage void __div0(void)
126 {
127         error("Attempting division by 0!");
128 }
129
130 extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
131
132
133 void
134 decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
135                 unsigned long free_mem_ptr_end_p,
136                 int arch_id)
137 {
138         int ret;
139
140         output_data             = (unsigned char *)output_start;
141         free_mem_ptr            = free_mem_ptr_p;
142         free_mem_end_ptr        = free_mem_ptr_end_p;
143         __machine_arch_type     = arch_id;
144
145         arch_decomp_setup();
146
147         putstr("Uncompressing Linux...");
148         ret = do_decompress(input_data, input_data_end - input_data,
149                             output_data, error);
150         if (ret)
151                 error("decompressor returned an error");
152         else
153                 putstr(" done, booting the kernel.\n");
154 }