2 * (C) Copyright 2008 Openmoko, Inc.
3 * Author: Andy Green <andy@openmoko.org>
5 * Parse the U-Boot header and Boot Linux
6 * based on various code from U-Boot
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 #include <neo_gta02.h>
26 #include "blink_led.h"
31 #include "nand_read.h"
34 unsigned long partition_offset_blocks = 0;
35 unsigned long partition_length_blocks = 0;
37 struct kernel_source const * this_kernel = 0;
40 void bootloader_second_phase(void)
42 void (*the_kernel)(int zero, int arch, uint params);
44 const struct board_variant * board_variant =
45 (this_board->get_board_variant)();
47 /* we try the possible kernels for this board in order */
49 this_kernel = &this_board->kernel_source[kernel++];
51 while (this_kernel->name) {
53 struct tag *params = (struct tag *)this_board->linux_tag_placement;
54 void * kernel_dram = (void *)(TEXT_BASE - (8 * 1024 * 1024));
59 partition_offset_blocks = 0;
60 partition_length_blocks = 0;
62 /* eat leading white space */
63 for (p = this_kernel->commandline; *p == ' '; p++);
65 puts("\n\nTrying kernel: ");
66 puts(this_kernel->name);
69 /* if this device needs initializing, try to init it */
70 if (this_kernel->block_init)
71 if ((this_kernel->block_init)()) {
72 puts("block device init failed\n");
73 this_kernel = &this_board->
74 kernel_source[kernel++];
78 /* if there's a partition table implied, parse it, otherwise
79 * just use a fixed offset
81 if (this_kernel->partition_index) {
82 unsigned char *p = kernel_dram;
84 if (this_kernel->block_read(kernel_dram, 0, 4) < 0) {
85 puts("Bad partition read\n");
86 this_kernel = &this_board->
87 kernel_source[kernel++];
91 if ((p[0x1fe] != 0x55) || (p[0x1ff] != 0xaa)) {
92 puts("partition signature missing\n");
93 this_kernel = &this_board->
94 kernel_source[kernel++];
98 p += 0x1be + 8 + (0x10 *
99 (this_kernel->partition_index - 1));
101 partition_offset_blocks = (((u32)p[3]) << 24) |
102 (((u32)p[2]) << 16) |
105 partition_length_blocks = (((u32)p[7]) << 24) |
106 (((u32)p[6]) << 16) |
110 puts(" Partition: ");
111 printdec(this_kernel->partition_index);
113 printdec(partition_offset_blocks);
114 puts(" 512-byte blocks, size ");
115 printdec(partition_length_blocks / 2048);
119 partition_offset_blocks =
120 this_kernel->offset_blocks512_if_no_partition;
122 switch (this_kernel->filesystem) {
124 if (!ext2fs_mount()) {
125 puts("Unable to mount ext2 filesystem\n");
126 this_kernel = &this_board->
127 kernel_source[kernel++];
130 puts(" EXT2 open: ");
131 puts(this_kernel->filepath);
133 if (ext2fs_open(this_kernel->filepath) < 0) {
134 puts("Open failed\n");
135 this_kernel = &this_board->
136 kernel_source[kernel++];
139 ext2fs_read(kernel_dram, 4096);
144 puts(" RAW open: +");
145 printdec(partition_offset_blocks);
146 puts(" 512-byte blocks\n");
147 if (this_kernel->block_read(kernel_dram,
148 partition_offset_blocks, 8) < 0) {
149 puts ("Bad kernel header\n");
150 this_kernel = &this_board->
151 kernel_source[kernel++];
157 hdr = (image_header_t *)kernel_dram;
159 if (__be32_to_cpu(hdr->ih_magic) != IH_MAGIC) {
161 print32(hdr->ih_magic);
163 this_kernel = &this_board->kernel_source[kernel++];
168 puts((const char *)hdr->ih_name);
170 printdec(__be32_to_cpu(hdr->ih_size) >> 10);
173 kernel_size = ((__be32_to_cpu(hdr->ih_size) +
174 sizeof(image_header_t) + 2048) & ~(2048 - 1));
176 switch (this_kernel->filesystem) {
178 /* This read API always restarts from beginning */
179 ext2fs_read(kernel_dram, kernel_size);
184 if ((this_kernel->block_read)(
185 kernel_dram, partition_offset_blocks,
186 kernel_size >> 9) < 0) {
187 puts ("Bad kernel read\n");
188 this_kernel = &this_board->
189 kernel_source[kernel++];
200 * It's good for now to know that our kernel is intact from
201 * the storage before we jump into it and maybe crash silently
202 * even though it costs us some time
204 crc = crc32(0, kernel_dram + sizeof(image_header_t),
205 __be32_to_cpu(hdr->ih_size));
206 if (crc != __be32_to_cpu(hdr->ih_dcrc)) {
207 puts("\nKernel CRC ERROR: read 0x");
209 puts(" vs hdr CRC 0x");
210 print32(__be32_to_cpu(hdr->ih_dcrc));
212 this_kernel = &this_board->kernel_source[kernel++];
216 the_kernel = (void (*)(int, int, uint))
217 (((char *)hdr) + sizeof(image_header_t));
220 params->hdr.tag = ATAG_CORE;
221 params->hdr.size = tag_size (tag_core);
222 params->u.core.flags = 0;
223 params->u.core.pagesize = 0;
224 params->u.core.rootdev = 0;
225 params = tag_next(params);
228 params->hdr.tag = ATAG_REVISION;
229 params->hdr.size = tag_size (tag_revision);
230 params->u.revision.rev = board_variant->machine_revision;
231 params = tag_next(params);
234 params->hdr.tag = ATAG_MEM;
235 params->hdr.size = tag_size (tag_mem32);
236 params->u.mem.start = this_board->linux_mem_start;
237 params->u.mem.size = this_board->linux_mem_size;
238 params = tag_next(params);
240 /* kernel commandline */
243 params->hdr.tag = ATAG_CMDLINE;
244 params->hdr.size = (sizeof (struct tag_header) +
245 strlen (p) + 1 + 4) >> 2;
246 strcpy (params->u.cmdline.cmdline, p);
247 params = tag_next (params);
250 /* needs to always be the last tag */
251 params->hdr.tag = ATAG_NONE;
252 params->hdr.size = 0;
254 puts ("Starting --->\n\n");
257 * ooh that's it, we're gonna try boot this image!
258 * never mind the cache, Linux will take care of it
260 the_kernel(0, this_board->linux_machine_id,
261 this_board->linux_tag_placement);
263 /* we won't come back here no matter what */
266 /* none of the kernels worked out */
268 puts("No usable kernel image found, we've had it :-(\n");