]>
Commit | Line | Data |
---|---|---|
5d3cc55e MB |
1 | /* |
2 | * (C) Copyright 2008 Semihalf | |
3 | * | |
4 | * (C) Copyright 2000-2006 | |
5 | * Wolfgang Denk, DENX Software Engineering, [email protected]. | |
6 | * | |
7 | * See file CREDITS for list of people who contributed to this | |
8 | * project. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU General Public License as | |
12 | * published by the Free Software Foundation; either version 2 of | |
13 | * the License, or (at your option) any later version. | |
14 | * | |
15 | * This program is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | * GNU General Public License for more details. | |
19 | * | |
20 | * You should have received a copy of the GNU General Public License | |
21 | * along with this program; if not, write to the Free Software | |
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
23 | * MA 02111-1307 USA | |
24 | */ | |
25 | ||
26 | #include <common.h> | |
27 | #include <watchdog.h> | |
28 | #include <command.h> | |
29 | #include <image.h> | |
30 | #include <malloc.h> | |
31 | #include <zlib.h> | |
32 | #include <bzlib.h> | |
33 | #include <environment.h> | |
34 | #include <asm/byteorder.h> | |
35 | ||
36 | #if defined(CONFIG_OF_LIBFDT) | |
37 | #include <fdt.h> | |
38 | #include <libfdt.h> | |
39 | #include <fdt_support.h> | |
d45d5a18 | 40 | #elif defined(CONFIG_OF_FLAT_TREE) |
5d3cc55e MB |
41 | #include <ft_build.h> |
42 | #endif | |
43 | ||
44 | #ifdef CONFIG_LOGBUFFER | |
45 | #include <logbuff.h> | |
46 | #endif | |
47 | ||
48 | #ifdef CFG_INIT_RAM_LOCK | |
49 | #include <asm/cache.h> | |
50 | #endif | |
51 | ||
5d3cc55e MB |
52 | DECLARE_GLOBAL_DATA_PTR; |
53 | extern image_header_t header; | |
54 | ||
55 | /*cmd_boot.c*/ | |
56 | extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); | |
57 | ||
58 | #if defined(CONFIG_CMD_BDI) | |
59 | extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); | |
60 | #endif | |
61 | ||
62 | void __attribute__((noinline)) | |
63 | do_bootm_linux (cmd_tbl_t *cmdtp, int flag, | |
64 | int argc, char *argv[], | |
65 | ulong addr, | |
66 | ulong *len_ptr, | |
67 | int verify) | |
68 | { | |
69 | ulong sp; | |
70 | ulong len; | |
71 | ulong initrd_start, initrd_end; | |
72 | ulong cmd_start, cmd_end; | |
73 | ulong initrd_high; | |
74 | ulong data; | |
75 | int initrd_copy_to_ram = 1; | |
76 | char *cmdline; | |
77 | char *s; | |
78 | bd_t *kbd; | |
79 | void (*kernel)(bd_t *, ulong, ulong, ulong, ulong); | |
80 | image_header_t *hdr = &header; | |
81 | #if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) | |
82 | char *of_flat_tree = NULL; | |
83 | ulong of_data = 0; | |
84 | #endif | |
85 | ||
86 | if ((s = getenv ("initrd_high")) != NULL) { | |
87 | /* a value of "no" or a similar string will act like 0, | |
88 | * turning the "load high" feature off. This is intentional. | |
89 | */ | |
90 | initrd_high = simple_strtoul(s, NULL, 16); | |
91 | if (initrd_high == ~0) | |
92 | initrd_copy_to_ram = 0; | |
93 | } else { /* not set, no restrictions to load high */ | |
94 | initrd_high = ~0; | |
95 | } | |
96 | ||
97 | #ifdef CONFIG_LOGBUFFER | |
98 | kbd=gd->bd; | |
99 | /* Prevent initrd from overwriting logbuffer */ | |
100 | if (initrd_high < (kbd->bi_memsize-LOGBUFF_LEN-LOGBUFF_OVERHEAD)) | |
101 | initrd_high = kbd->bi_memsize-LOGBUFF_LEN-LOGBUFF_OVERHEAD; | |
102 | debug ("## Logbuffer at 0x%08lX ", kbd->bi_memsize-LOGBUFF_LEN); | |
103 | #endif | |
104 | ||
105 | /* | |
106 | * Booting a (Linux) kernel image | |
107 | * | |
108 | * Allocate space for command line and board info - the | |
109 | * address should be as high as possible within the reach of | |
110 | * the kernel (see CFG_BOOTMAPSZ settings), but in unused | |
111 | * memory, which means far enough below the current stack | |
112 | * pointer. | |
113 | */ | |
114 | ||
115 | asm( "mr %0,1": "=r"(sp) : ); | |
116 | ||
117 | debug ("## Current stack ends at 0x%08lX ", sp); | |
118 | ||
119 | sp -= 2048; /* just to be sure */ | |
120 | if (sp > CFG_BOOTMAPSZ) | |
121 | sp = CFG_BOOTMAPSZ; | |
122 | sp &= ~0xF; | |
123 | ||
124 | debug ("=> set upper limit to 0x%08lX\n", sp); | |
125 | ||
126 | cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF); | |
127 | kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF); | |
128 | ||
129 | if ((s = getenv("bootargs")) == NULL) | |
130 | s = ""; | |
131 | ||
132 | strcpy (cmdline, s); | |
133 | ||
134 | cmd_start = (ulong)&cmdline[0]; | |
135 | cmd_end = cmd_start + strlen(cmdline); | |
136 | ||
137 | *kbd = *(gd->bd); | |
138 | ||
139 | #ifdef DEBUG | |
140 | printf ("## cmdline at 0x%08lX ... 0x%08lX\n", cmd_start, cmd_end); | |
141 | ||
142 | #if defined(CONFIG_CMD_BDI) | |
143 | do_bdinfo (NULL, 0, 0, NULL); | |
144 | #endif | |
145 | #endif | |
146 | ||
147 | if ((s = getenv ("clocks_in_mhz")) != NULL) { | |
148 | /* convert all clock information to MHz */ | |
149 | kbd->bi_intfreq /= 1000000L; | |
150 | kbd->bi_busfreq /= 1000000L; | |
151 | #if defined(CONFIG_MPC8220) | |
152 | kbd->bi_inpfreq /= 1000000L; | |
153 | kbd->bi_pcifreq /= 1000000L; | |
154 | kbd->bi_pevfreq /= 1000000L; | |
155 | kbd->bi_flbfreq /= 1000000L; | |
156 | kbd->bi_vcofreq /= 1000000L; | |
157 | #endif | |
158 | #if defined(CONFIG_CPM2) | |
159 | kbd->bi_cpmfreq /= 1000000L; | |
160 | kbd->bi_brgfreq /= 1000000L; | |
161 | kbd->bi_sccfreq /= 1000000L; | |
162 | kbd->bi_vco /= 1000000L; | |
163 | #endif | |
164 | #if defined(CONFIG_MPC5xxx) | |
165 | kbd->bi_ipbfreq /= 1000000L; | |
166 | kbd->bi_pcifreq /= 1000000L; | |
167 | #endif /* CONFIG_MPC5xxx */ | |
168 | } | |
169 | ||
170 | kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))image_get_ep (hdr); | |
171 | ||
172 | /* | |
173 | * Check if there is an initrd image | |
174 | */ | |
175 | ||
176 | #if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) | |
177 | /* Look for a '-' which indicates to ignore the ramdisk argument */ | |
178 | if (argc >= 3 && strcmp(argv[2], "-") == 0) { | |
179 | debug ("Skipping initrd\n"); | |
180 | len = data = 0; | |
181 | } | |
182 | else | |
183 | #endif | |
184 | if (argc >= 3) { | |
185 | debug ("Not skipping initrd\n"); | |
186 | show_boot_progress (9); | |
187 | ||
188 | addr = simple_strtoul(argv[2], NULL, 16); | |
189 | ||
190 | printf ("## Loading RAMDisk Image at %08lx ...\n", addr); | |
191 | hdr = (image_header_t *)addr; | |
192 | ||
193 | if (!image_check_magic (hdr)) { | |
194 | puts ("Bad Magic Number\n"); | |
195 | show_boot_progress (-10); | |
196 | do_reset (cmdtp, flag, argc, argv); | |
197 | } | |
198 | ||
199 | if (!image_check_hcrc (hdr)) { | |
200 | puts ("Bad Header Checksum\n"); | |
201 | show_boot_progress (-11); | |
202 | do_reset (cmdtp, flag, argc, argv); | |
203 | } | |
204 | show_boot_progress (10); | |
205 | ||
206 | print_image_hdr (hdr); | |
207 | ||
208 | if (verify) { | |
209 | puts (" Verifying Checksum ... "); | |
210 | ||
211 | if (!image_check_dcrc_wd (hdr, CHUNKSZ)) { | |
212 | puts ("Bad Data CRC\n"); | |
213 | show_boot_progress (-12); | |
214 | do_reset (cmdtp, flag, argc, argv); | |
215 | } | |
216 | puts ("OK\n"); | |
217 | } | |
218 | ||
219 | show_boot_progress (11); | |
220 | ||
221 | if (!image_check_os (hdr, IH_OS_LINUX) || | |
222 | !image_check_arch (hdr, IH_ARCH_PPC) || | |
223 | !image_check_type (hdr, IH_TYPE_RAMDISK)) { | |
224 | puts ("No Linux PPC Ramdisk Image\n"); | |
225 | show_boot_progress (-13); | |
226 | do_reset (cmdtp, flag, argc, argv); | |
227 | } | |
228 | ||
229 | data = image_get_data (hdr); | |
230 | len = image_get_data_size (hdr); | |
231 | ||
232 | /* | |
233 | * Now check if we have a multifile image | |
234 | */ | |
235 | } else if (image_check_type (hdr, IH_TYPE_MULTI) && (len_ptr[1])) { | |
236 | u_long tail = image_to_cpu (len_ptr[0]) % 4; | |
237 | int i; | |
238 | ||
239 | show_boot_progress (13); | |
240 | ||
241 | /* skip kernel length and terminator */ | |
242 | data = (ulong)(&len_ptr[2]); | |
243 | /* skip any additional image length fields */ | |
244 | for (i=1; len_ptr[i]; ++i) | |
245 | data += 4; | |
246 | /* add kernel length, and align */ | |
247 | data += image_to_cpu (len_ptr[0]); | |
248 | if (tail) { | |
249 | data += 4 - tail; | |
250 | } | |
251 | ||
252 | len = image_to_cpu (len_ptr[1]); | |
253 | ||
254 | } else { | |
255 | /* | |
256 | * no initrd image | |
257 | */ | |
258 | show_boot_progress (14); | |
259 | ||
260 | len = data = 0; | |
261 | } | |
262 | ||
263 | #if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) | |
264 | if(argc > 3) { | |
265 | of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16); | |
266 | hdr = (image_header_t *)of_flat_tree; | |
267 | #if defined(CONFIG_OF_FLAT_TREE) | |
268 | if (*((ulong *)(of_flat_tree + image_get_header_size ())) != OF_DT_HEADER) { | |
d45d5a18 | 269 | #elif defined(CONFIG_OF_LIBFDT) |
5d3cc55e MB |
270 | if (fdt_check_header (of_flat_tree + image_get_header_size ()) != 0) { |
271 | #endif | |
272 | #ifndef CFG_NO_FLASH | |
273 | if (addr2info((ulong)of_flat_tree) != NULL) | |
274 | of_data = (ulong)of_flat_tree; | |
275 | #endif | |
276 | } else if (image_check_magic (hdr)) { | |
277 | printf("## Flat Device Tree at %08lX\n", hdr); | |
278 | print_image_hdr (hdr); | |
279 | ||
280 | if ((image_get_load (hdr) < ((unsigned long)hdr + image_get_image_size (hdr))) && | |
281 | ((image_get_load (hdr) + image_get_data_size (hdr)) > (unsigned long)hdr)) { | |
282 | puts ("ERROR: fdt overwritten - " | |
283 | "must RESET the board to recover.\n"); | |
284 | do_reset (cmdtp, flag, argc, argv); | |
285 | } | |
286 | ||
287 | puts (" Verifying Checksum ... "); | |
288 | if (!image_check_hcrc (hdr)) { | |
289 | puts ("ERROR: fdt header checksum invalid - " | |
290 | "must RESET the board to recover.\n"); | |
291 | do_reset (cmdtp, flag, argc, argv); | |
292 | } | |
293 | ||
294 | if (!image_check_dcrc (hdr)) { | |
295 | puts ("ERROR: fdt checksum invalid - " | |
296 | "must RESET the board to recover.\n"); | |
297 | do_reset (cmdtp, flag, argc, argv); | |
298 | } | |
299 | puts ("OK\n"); | |
300 | ||
301 | if (!image_check_type (hdr, IH_TYPE_FLATDT)) { | |
302 | puts ("ERROR: uImage is not a fdt - " | |
303 | "must RESET the board to recover.\n"); | |
304 | do_reset (cmdtp, flag, argc, argv); | |
305 | } | |
306 | if (image_get_comp (hdr) != IH_COMP_NONE) { | |
307 | puts ("ERROR: uImage is compressed - " | |
308 | "must RESET the board to recover.\n"); | |
309 | do_reset (cmdtp, flag, argc, argv); | |
310 | } | |
311 | #if defined(CONFIG_OF_FLAT_TREE) | |
312 | if (*((ulong *)(of_flat_tree + image_get_header_size ())) != OF_DT_HEADER) { | |
d45d5a18 | 313 | #elif defined(CONFIG_OF_LIBFDT) |
5d3cc55e MB |
314 | if (fdt_check_header (of_flat_tree + image_get_header_size ()) != 0) { |
315 | #endif | |
316 | puts ("ERROR: uImage data is not a fdt - " | |
317 | "must RESET the board to recover.\n"); | |
318 | do_reset (cmdtp, flag, argc, argv); | |
319 | } | |
320 | ||
321 | memmove ((void *)image_get_load (hdr), | |
322 | (void *)(of_flat_tree + image_get_header_size ()), | |
323 | image_get_data_size (hdr)); | |
324 | ||
325 | of_flat_tree = (char *)image_get_load (hdr); | |
326 | } else { | |
327 | puts ("Did not find a flat Flat Device Tree.\n" | |
328 | "Must RESET the board to recover.\n"); | |
329 | do_reset (cmdtp, flag, argc, argv); | |
330 | } | |
331 | printf (" Booting using the fdt at 0x%x\n", | |
332 | of_flat_tree); | |
333 | } else if (image_check_type (hdr, IH_TYPE_MULTI) && (len_ptr[1]) && (len_ptr[2])) { | |
334 | u_long tail = image_to_cpu (len_ptr[0]) % 4; | |
335 | int i; | |
336 | ||
337 | /* skip kernel length, initrd length, and terminator */ | |
338 | of_flat_tree = (char *)(&len_ptr[3]); | |
339 | /* skip any additional image length fields */ | |
340 | for (i=2; len_ptr[i]; ++i) | |
341 | of_flat_tree += 4; | |
342 | /* add kernel length, and align */ | |
343 | of_flat_tree += image_to_cpu (len_ptr[0]); | |
344 | if (tail) { | |
345 | of_flat_tree += 4 - tail; | |
346 | } | |
347 | ||
348 | /* add initrd length, and align */ | |
349 | tail = image_to_cpu (len_ptr[1]) % 4; | |
350 | of_flat_tree += image_to_cpu (len_ptr[1]); | |
351 | if (tail) { | |
352 | of_flat_tree += 4 - tail; | |
353 | } | |
354 | ||
355 | #ifndef CFG_NO_FLASH | |
356 | /* move the blob if it is in flash (set of_data to !null) */ | |
357 | if (addr2info ((ulong)of_flat_tree) != NULL) | |
358 | of_data = (ulong)of_flat_tree; | |
359 | #endif | |
360 | ||
361 | ||
362 | #if defined(CONFIG_OF_FLAT_TREE) | |
363 | if (*((ulong *)(of_flat_tree)) != OF_DT_HEADER) { | |
d45d5a18 | 364 | #elif defined(CONFIG_OF_LIBFDT) |
5d3cc55e MB |
365 | if (fdt_check_header (of_flat_tree) != 0) { |
366 | #endif | |
367 | puts ("ERROR: image is not a fdt - " | |
368 | "must RESET the board to recover.\n"); | |
369 | do_reset (cmdtp, flag, argc, argv); | |
370 | } | |
371 | ||
372 | #if defined(CONFIG_OF_FLAT_TREE) | |
373 | if (((struct boot_param_header *)of_flat_tree)->totalsize != | |
374 | image_to_cpu (len_ptr[2])) { | |
d45d5a18 | 375 | #elif defined(CONFIG_OF_LIBFDT) |
5d3cc55e MB |
376 | if (be32_to_cpu (fdt_totalsize (of_flat_tree)) != |
377 | image_to_cpu (len_ptr[2])) { | |
378 | #endif | |
379 | puts ("ERROR: fdt size != image size - " | |
380 | "must RESET the board to recover.\n"); | |
381 | do_reset (cmdtp, flag, argc, argv); | |
382 | } | |
383 | } | |
384 | #endif | |
385 | if (!data) { | |
386 | debug ("No initrd\n"); | |
387 | } | |
388 | ||
389 | if (data) { | |
390 | if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ | |
391 | initrd_start = data; | |
392 | initrd_end = initrd_start + len; | |
393 | } else { | |
394 | initrd_start = (ulong)kbd - len; | |
395 | initrd_start &= ~(4096 - 1); /* align on page */ | |
396 | ||
397 | if (initrd_high) { | |
398 | ulong nsp; | |
399 | ||
400 | /* | |
401 | * the inital ramdisk does not need to be within | |
402 | * CFG_BOOTMAPSZ as it is not accessed until after | |
403 | * the mm system is initialised. | |
404 | * | |
405 | * do the stack bottom calculation again and see if | |
406 | * the initrd will fit just below the monitor stack | |
407 | * bottom without overwriting the area allocated | |
408 | * above for command line args and board info. | |
409 | */ | |
410 | asm( "mr %0,1": "=r"(nsp) : ); | |
411 | nsp -= 2048; /* just to be sure */ | |
412 | nsp &= ~0xF; | |
413 | if (nsp > initrd_high) /* limit as specified */ | |
414 | nsp = initrd_high; | |
415 | nsp -= len; | |
416 | nsp &= ~(4096 - 1); /* align on page */ | |
417 | if (nsp >= sp) | |
418 | initrd_start = nsp; | |
419 | } | |
420 | ||
421 | show_boot_progress (12); | |
422 | ||
423 | debug ("## initrd at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", | |
424 | data, data + len - 1, len, len); | |
425 | ||
426 | initrd_end = initrd_start + len; | |
427 | printf (" Loading Ramdisk to %08lx, end %08lx ... ", | |
428 | initrd_start, initrd_end); | |
429 | #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) | |
430 | { | |
431 | size_t l = len; | |
432 | void *to = (void *)initrd_start; | |
433 | void *from = (void *)data; | |
434 | ||
435 | while (l > 0) { | |
436 | size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l; | |
437 | WATCHDOG_RESET(); | |
438 | memmove (to, from, tail); | |
439 | to += tail; | |
440 | from += tail; | |
441 | l -= tail; | |
442 | } | |
443 | } | |
444 | #else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ | |
445 | memmove ((void *)initrd_start, (void *)data, len); | |
446 | #endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ | |
447 | puts ("OK\n"); | |
448 | } | |
449 | } else { | |
450 | initrd_start = 0; | |
451 | initrd_end = 0; | |
452 | } | |
453 | ||
454 | #if defined(CONFIG_OF_LIBFDT) | |
455 | ||
456 | #ifdef CFG_BOOTMAPSZ | |
457 | /* | |
458 | * The blob must be within CFG_BOOTMAPSZ, | |
459 | * so we flag it to be copied if it is not. | |
460 | */ | |
461 | if (of_flat_tree >= (char *)CFG_BOOTMAPSZ) | |
462 | of_data = (ulong)of_flat_tree; | |
463 | #endif | |
464 | ||
465 | /* move of_flat_tree if needed */ | |
466 | if (of_data) { | |
467 | int err; | |
468 | ulong of_start, of_len; | |
469 | ||
470 | of_len = be32_to_cpu(fdt_totalsize(of_data)); | |
471 | ||
472 | /* position on a 4K boundary before the kbd */ | |
473 | of_start = (ulong)kbd - of_len; | |
474 | of_start &= ~(4096 - 1); /* align on page */ | |
475 | debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", | |
476 | of_data, of_data + of_len - 1, of_len, of_len); | |
477 | ||
478 | of_flat_tree = (char *)of_start; | |
479 | printf (" Loading Device Tree to %08lx, end %08lx ... ", | |
480 | of_start, of_start + of_len - 1); | |
481 | err = fdt_open_into((void *)of_data, (void *)of_start, of_len); | |
482 | if (err != 0) { | |
483 | puts ("ERROR: fdt move failed - " | |
484 | "must RESET the board to recover.\n"); | |
485 | do_reset (cmdtp, flag, argc, argv); | |
486 | } | |
487 | puts ("OK\n"); | |
488 | } | |
489 | /* | |
490 | * Add the chosen node if it doesn't exist, add the env and bd_t | |
491 | * if the user wants it (the logic is in the subroutines). | |
492 | */ | |
493 | if (of_flat_tree) { | |
494 | if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) { | |
495 | puts ("ERROR: /chosen node create failed - " | |
496 | "must RESET the board to recover.\n"); | |
497 | do_reset (cmdtp, flag, argc, argv); | |
498 | } | |
499 | #ifdef CONFIG_OF_HAS_UBOOT_ENV | |
500 | if (fdt_env(of_flat_tree) < 0) { | |
501 | puts ("ERROR: /u-boot-env node create failed - " | |
502 | "must RESET the board to recover.\n"); | |
503 | do_reset (cmdtp, flag, argc, argv); | |
504 | } | |
505 | #endif | |
506 | #ifdef CONFIG_OF_HAS_BD_T | |
507 | if (fdt_bd_t(of_flat_tree) < 0) { | |
508 | puts ("ERROR: /bd_t node create failed - " | |
509 | "must RESET the board to recover.\n"); | |
510 | do_reset (cmdtp, flag, argc, argv); | |
511 | } | |
512 | #endif | |
513 | #ifdef CONFIG_OF_BOARD_SETUP | |
514 | /* Call the board-specific fixup routine */ | |
515 | ft_board_setup(of_flat_tree, gd->bd); | |
516 | #endif | |
517 | } | |
d45d5a18 MB |
518 | |
519 | #elif defined(CONFIG_OF_FLAT_TREE) | |
520 | ||
5d3cc55e MB |
521 | #ifdef CFG_BOOTMAPSZ |
522 | /* | |
523 | * The blob must be within CFG_BOOTMAPSZ, | |
524 | * so we flag it to be copied if it is not. | |
525 | */ | |
526 | if (of_flat_tree >= (char *)CFG_BOOTMAPSZ) | |
527 | of_data = (ulong)of_flat_tree; | |
528 | #endif | |
529 | ||
530 | /* move of_flat_tree if needed */ | |
531 | if (of_data) { | |
532 | ulong of_start, of_len; | |
533 | of_len = ((struct boot_param_header *)of_data)->totalsize; | |
534 | ||
535 | /* provide extra 8k pad */ | |
536 | of_start = (ulong)kbd - of_len - 8192; | |
537 | of_start &= ~(4096 - 1); /* align on page */ | |
538 | debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", | |
539 | of_data, of_data + of_len - 1, of_len, of_len); | |
540 | ||
541 | of_flat_tree = (char *)of_start; | |
542 | printf (" Loading Device Tree to %08lx, end %08lx ... ", | |
543 | of_start, of_start + of_len - 1); | |
544 | memmove ((void *)of_start, (void *)of_data, of_len); | |
545 | puts ("OK\n"); | |
546 | } | |
547 | /* | |
548 | * Create the /chosen node and modify the blob with board specific | |
549 | * values as needed. | |
550 | */ | |
551 | ft_setup(of_flat_tree, kbd, initrd_start, initrd_end); | |
552 | /* ft_dump_blob(of_flat_tree); */ | |
d45d5a18 MB |
553 | |
554 | #endif /* #if defined(CONFIG_OF_LIBFDT) #elif defined(CONFIG_OF_FLAT_TREE) */ | |
555 | ||
5d3cc55e MB |
556 | debug ("## Transferring control to Linux (at address %08lx) ...\n", |
557 | (ulong)kernel); | |
558 | ||
559 | show_boot_progress (15); | |
560 | ||
561 | #if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500) | |
562 | unlock_ram_in_cache(); | |
563 | #endif | |
564 | ||
565 | #if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) | |
566 | if (of_flat_tree) { /* device tree; boot new style */ | |
567 | /* | |
568 | * Linux Kernel Parameters (passing device tree): | |
569 | * r3: pointer to the fdt, followed by the board info data | |
570 | * r4: physical pointer to the kernel itself | |
571 | * r5: NULL | |
572 | * r6: NULL | |
573 | * r7: NULL | |
574 | */ | |
575 | (*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0); | |
576 | /* does not return */ | |
577 | } | |
578 | #endif | |
579 | /* | |
580 | * Linux Kernel Parameters (passing board info data): | |
581 | * r3: ptr to board info data | |
582 | * r4: initrd_start or 0 if no initrd | |
583 | * r5: initrd_end - unused if r4 is 0 | |
584 | * r6: Start of command line string | |
585 | * r7: End of command line string | |
586 | */ | |
587 | (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); | |
588 | /* does not return */ | |
589 | } |