1
2
3
4
5
6
7
8
9#include <linux/types.h>
10#include <linux/string.h>
11#include <asm/bootinfo.h>
12#include <asm/mmu.h>
13#include <asm/page.h>
14#include <asm/residual.h>
15#if defined(CONFIG_4xx)
16#include <asm/ibm4xx.h>
17#elif defined(CONFIG_8xx)
18#include <asm/mpc8xx.h>
19#elif defined(CONFIG_8260)
20#include <asm/mpc8260.h>
21#endif
22
23#include "nonstdio.h"
24
25
26extern char __image_begin, __image_end;
27extern char __ramdisk_begin, __ramdisk_end;
28extern char _end[];
29
30
31
32
33
34
35
36
37
38char cmd_buf[256];
39char *cmd_line = cmd_buf;
40char *avail_ram;
41char *end_avail;
42char *zimage_start;
43
44
45
46
47char *bootrom_cmdline = "";
48
49
50
51
52#ifdef CONFIG_CMDLINE_BOOL
53char compiled_string[] = CONFIG_CMDLINE;
54#endif
55char ramroot_string[] = "root=/dev/ram";
56char netroot_string[] = "root=/dev/nfs rw ip=on";
57
58
59unsigned long com_port;
60
61
62
63bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot")));
64bd_t *hold_residual = &hold_resid_buf;
65
66extern unsigned long serial_init(int chan, bd_t *bp);
67extern void serial_close(unsigned long com_port);
68extern unsigned long start;
69extern void flush_instruction_cache(void);
70extern void gunzip(void *, int, unsigned char *, int *);
71extern void embed_config(bd_t **bp);
72
73
74
75
76void __attribute__ ((weak))
77embed_config(bd_t **bdp)
78{
79}
80
81unsigned long
82load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp)
83{
84 char *cp, ch;
85 int timer = 0, zimage_size;
86 unsigned long initrd_size;
87
88
89
90
91 embed_config(&bp);
92#if defined(CONFIG_SERIAL_CPM_CONSOLE) || \
93 defined(CONFIG_SERIAL_8250_CONSOLE) || \
94 defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
95 com_port = serial_init(0, bp);
96#endif
97
98
99
100
101
102#ifdef CONFIG_MBX
103
104
105
106
107 load_addr = *(uint *)0xfa000020;
108 load_addr += 0x10000;
109#endif
110
111 if (bp)
112 memcpy(hold_residual,bp,sizeof(bd_t));
113
114
115
116
117 end_avail = (char *)(bp->bi_memsize);
118
119 puts("\nloaded at: "); puthex(load_addr);
120 puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
121 if ( (unsigned long)load_addr != (unsigned long)&start ) {
122 puts("relocated to: "); puthex((unsigned long)&start);
123 puts(" ");
124 puthex((unsigned long)((unsigned long)&start + (4*num_words)));
125 puts("\n");
126 }
127
128 if ( bp ) {
129 puts("board data at: "); puthex((unsigned long)bp);
130 puts(" ");
131 puthex((unsigned long)((unsigned long)bp + sizeof(bd_t)));
132 puts("\nrelocated to: ");
133 puthex((unsigned long)hold_residual);
134 puts(" ");
135 puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t)));
136 puts("\n");
137 }
138
139
140
141
142
143
144 zimage_start = (char *)(unsigned long)(&__image_begin);
145 zimage_size = (unsigned long)(&__image_end) -
146 (unsigned long)(&__image_begin);
147
148 initrd_size = (unsigned long)(&__ramdisk_end) -
149 (unsigned long)(&__ramdisk_begin);
150
151
152
153
154
155 puts("zimage at: "); puthex((unsigned long)zimage_start);
156 puts(" "); puthex((unsigned long)(zimage_size+zimage_start));
157 puts("\n");
158
159 if ( initrd_size ) {
160 puts("initrd at: ");
161 puthex((unsigned long)(&__ramdisk_begin));
162 puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n");
163 }
164
165
166
167
168
169
170 avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
171
172 puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" ");
173 puthex((unsigned long)end_avail); puts("\n");
174 puts("\nLinux/PPC load: ");
175 cp = cmd_line;
176
177
178
179
180
181#ifdef CONFIG_CMDLINE_BOOL
182 memcpy (cmd_line, compiled_string, sizeof(compiled_string));
183#else
184 if ( initrd_size )
185 memcpy (cmd_line, ramroot_string, sizeof(ramroot_string));
186 else
187 memcpy (cmd_line, netroot_string, sizeof(netroot_string));
188#endif
189 while ( *cp )
190 putc(*cp++);
191 while (timer++ < 5*1000) {
192 if (tstc()) {
193 while ((ch = getc()) != '\n' && ch != '\r') {
194 if (ch == '\b' || ch == '\177') {
195 if (cp != cmd_line) {
196 cp--;
197 puts("\b \b");
198 }
199 } else if (ch == '\030'
200 || ch == '\025') {
201 while (cp != cmd_line) {
202 cp--;
203 puts("\b \b");
204 }
205 } else {
206 *cp++ = ch;
207 putc(ch);
208 }
209 }
210 break;
211 }
212 udelay(1000);
213 }
214 *cp = 0;
215 puts("\nUncompressing Linux...");
216
217 gunzip(0, 0x400000, zimage_start, &zimage_size);
218 flush_instruction_cache();
219 puts("done.\n");
220 {
221 struct bi_record *rec;
222 unsigned long initrd_loc = 0;
223 unsigned long rec_loc = _ALIGN((unsigned long)(zimage_size) +
224 (1 << 20) - 1, (1 << 20));
225 rec = (struct bi_record *)rec_loc;
226
227
228
229 if ( initrd_size ) {
230 initrd_loc = (unsigned long)(&__ramdisk_begin);
231
232
233
234 if ((rec_loc > initrd_loc) &&
235 ((initrd_loc + initrd_size)
236 > rec_loc)) {
237 initrd_loc = _ALIGN((unsigned long)(zimage_size)
238 + (2 << 20) - 1, (2 << 20));
239 memmove((void *)initrd_loc, &__ramdisk_begin,
240 initrd_size);
241 puts("initrd moved: "); puthex(initrd_loc);
242 puts(" "); puthex(initrd_loc + initrd_size);
243 puts("\n");
244 }
245 }
246
247 rec->tag = BI_FIRST;
248 rec->size = sizeof(struct bi_record);
249 rec = (struct bi_record *)((unsigned long)rec + rec->size);
250
251 rec->tag = BI_CMD_LINE;
252 memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
253 rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
254 rec = (struct bi_record *)((unsigned long)rec + rec->size);
255
256 if ( initrd_size ) {
257 rec->tag = BI_INITRD;
258 rec->data[0] = initrd_loc;
259 rec->data[1] = initrd_size;
260 rec->size = sizeof(struct bi_record) + 2 *
261 sizeof(unsigned long);
262 rec = (struct bi_record *)((unsigned long)rec +
263 rec->size);
264 }
265
266 rec->tag = BI_LAST;
267 rec->size = sizeof(struct bi_record);
268 rec = (struct bi_record *)((unsigned long)rec + rec->size);
269 }
270 puts("Now booting the kernel\n");
271#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
272 serial_close(com_port);
273#endif
274
275 return (unsigned long)hold_residual;
276}
277