1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <boot/boot.h>
30 #include <boot/uart.h>
31 #include <boot/tags.h>
32 #include <boot/flash.h>
33 #include <boot/board.h>
34
35 #include <bootimg.h>
36
37 #define FLASH_PAGE_SIZE 2048
38 #define FLASH_PAGE_BITS 11
39
40 #define ADDR_TAGS 0x10000100
41
create_atags(unsigned taddr,const char * cmdline,unsigned raddr,unsigned rsize)42 static void create_atags(unsigned taddr, const char *cmdline,
43 unsigned raddr, unsigned rsize)
44 {
45 unsigned n = 0;
46 unsigned pcount;
47 unsigned *tags = (unsigned *) taddr;
48
49 // ATAG_CORE
50 tags[n++] = 2;
51 tags[n++] = 0x54410001;
52
53 if(rsize) {
54 // ATAG_INITRD2
55 tags[n++] = 4;
56 tags[n++] = 0x54420005;
57 tags[n++] = raddr;
58 tags[n++] = rsize;
59 }
60
61 if((pcount = flash_get_ptn_count())){
62 ptentry *ptn;
63 unsigned pn;
64 unsigned m = n + 2;
65
66 for(pn = 0; pn < pcount; pn++) {
67 ptn = flash_get_ptn(pn);
68 memcpy(tags + m, ptn, sizeof(ptentry));
69 m += (sizeof(ptentry) / sizeof(unsigned));
70 }
71
72 tags[n + 0] = m - n;
73 tags[n + 1] = 0x4d534d70;
74 n = m;
75 }
76 if(cmdline && cmdline[0]) {
77 const char *src;
78 char *dst;
79 unsigned len = 0;
80
81 dst = (char*) (tags + n + 2);
82 src = cmdline;
83 while((*dst++ = *src++)) len++;
84
85 len++;
86 len = (len + 3) & (~3);
87
88 // ATAG_CMDLINE
89 tags[n++] = 2 + (len / 4);
90 tags[n++] = 0x54410009;
91
92 n += (len / 4);
93 }
94
95 // ATAG_NONE
96 tags[n++] = 0;
97 tags[n++] = 0;
98 }
99
boot_linux(unsigned kaddr)100 static void boot_linux(unsigned kaddr)
101 {
102 void (*entry)(unsigned,unsigned,unsigned) = (void*) kaddr;
103
104 entry(0, board_machtype(), ADDR_TAGS);
105 }
106
107 unsigned char raw_header[2048];
108
boot_linux_from_flash(void)109 int boot_linux_from_flash(void)
110 {
111 boot_img_hdr *hdr = (void*) raw_header;
112 unsigned n;
113 ptentry *p;
114 unsigned offset = 0;
115 const char *cmdline;
116
117 if((p = flash_find_ptn("boot")) == 0) {
118 cprintf("NO BOOT PARTITION\n");
119 return -1;
120 }
121
122 if(flash_read(p, offset, raw_header, 2048)) {
123 cprintf("CANNOT READ BOOT IMAGE HEADER\n");
124 return -1;
125 }
126 offset += 2048;
127
128 if(memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
129 cprintf("INVALID BOOT IMAGE HEADER\n");
130 return -1;
131 }
132
133 n = (hdr->kernel_size + (FLASH_PAGE_SIZE - 1)) & (~(FLASH_PAGE_SIZE - 1));
134 if(flash_read(p, offset, (void*) hdr->kernel_addr, n)) {
135 cprintf("CANNOT READ KERNEL IMAGE\n");
136 return -1;
137 }
138 offset += n;
139
140 n = (hdr->ramdisk_size + (FLASH_PAGE_SIZE - 1)) & (~(FLASH_PAGE_SIZE - 1));
141 if(flash_read(p, offset, (void*) hdr->ramdisk_addr, n)) {
142 cprintf("CANNOT READ RAMDISK IMAGE\n");
143 return -1;
144 }
145 offset += n;
146
147 dprintf("\nkernel @ %x (%d bytes)\n", hdr->kernel_addr, hdr->kernel_size);
148 dprintf("ramdisk @ %x (%d bytes)\n\n\n", hdr->ramdisk_addr, hdr->ramdisk_size);
149
150 if(hdr->cmdline[0]) {
151 cmdline = (char*) hdr->cmdline;
152 } else {
153 cmdline = board_cmdline();
154 if(cmdline == 0) {
155 cmdline = "mem=50M console=null";
156 }
157 }
158 cprintf("cmdline = '%s'\n", cmdline);
159
160 cprintf("\nBooting Linux\n");
161
162 create_atags(ADDR_TAGS, cmdline,
163 hdr->ramdisk_addr, hdr->ramdisk_size);
164
165 boot_linux(hdr->kernel_addr);
166 return 0;
167 }
168
169 void usbloader_init(void);
170 void uart_putc(unsigned);
171 const char *get_fastboot_version(void);
172
173 extern unsigned linux_type;
174 extern unsigned linux_tags;
175
176 static unsigned revision = 0;
177
178 char serialno[32];
179
180 void dump_smem_info(void);
181
tag_dump(unsigned tag,void * data,unsigned sz,void * cookie)182 static void tag_dump(unsigned tag, void *data, unsigned sz, void *cookie)
183 {
184 dprintf("tag type=%x data=%x size=%x\n", tag, (unsigned) data, sz);
185 }
186
187 static struct tag_handler tag_dump_handler = {
188 .func = tag_dump,
189 .type = 0,
190 };
191
xdcc_putc(unsigned x)192 void xdcc_putc(unsigned x)
193 {
194 while (dcc_putc(x) < 0) ;
195 }
196
197 #define SERIALNO_STR "androidboot.serialno="
198 #define SERIALNO_LEN strlen(SERIALNO_STR)
199
200 static int boot_from_flash = 1;
201
key_changed(unsigned int key,unsigned int down)202 void key_changed(unsigned int key, unsigned int down)
203 {
204 if(!down) return;
205 if(key == BOOT_KEY_STOP_BOOT) boot_from_flash = 0;
206 }
207
tags_okay(unsigned taddr)208 static int tags_okay(unsigned taddr)
209 {
210 unsigned *tags = (unsigned*) taddr;
211
212 if(taddr != ADDR_TAGS) return 0;
213 if(tags[0] != 2) return 0;
214 if(tags[1] != 0x54410001) return 0;
215
216 return 1;
217 }
218
_main(unsigned zero,unsigned type,unsigned tags)219 int _main(unsigned zero, unsigned type, unsigned tags)
220 {
221 const char *cmdline = 0;
222 int n;
223
224 arm11_clock_init();
225
226 /* must do this before board_init() so that we
227 ** use the partition table in the tags if it
228 ** already exists
229 */
230 if((zero == 0) && (type != 0) && tags_okay(tags)) {
231 linux_type = type;
232 linux_tags = tags;
233
234 cmdline = tags_get_cmdline((void*) linux_tags);
235
236 tags_import_partitions((void*) linux_tags);
237 revision = tags_get_revision((void*) linux_tags);
238 if(revision == 1) {
239 console_set_colors(0x03E0, 0xFFFF);
240 }
241 if(revision == 2) {
242 console_set_colors(0x49B2, 0xFFFF);
243 }
244
245 /* we're running as a second-stage, so wait for interrupt */
246 boot_from_flash = 0;
247 } else {
248 linux_type = board_machtype();
249 linux_tags = 0;
250 }
251
252 board_init();
253 keypad_init();
254
255 console_init();
256 dprintf_set_putc(uart_putc);
257
258 if(linux_tags == 0) {
259 /* generate atags containing partitions
260 * from the bootloader, etc
261 */
262 linux_tags = ADDR_TAGS;
263 create_atags(linux_tags, 0, 0, 0);
264 }
265
266 if (cmdline) {
267 char *sn = strstr(cmdline, SERIALNO_STR);
268 if (sn) {
269 char *s = serialno;
270 sn += SERIALNO_LEN;
271 while (*sn && (*sn != ' ') && ((s - serialno) < 31)) {
272 *s++ = *sn++;
273 }
274 *s++ = 0;
275 }
276 }
277
278 cprintf("\n\nUSB FastBoot: V%s\n", get_fastboot_version());
279 cprintf("Machine ID: %d v%d\n", linux_type, revision);
280 cprintf("Build Date: "__DATE__", "__TIME__"\n\n");
281
282 cprintf("Serial Number: %s\n\n", serialno[0] ? serialno : "UNKNOWN");
283
284 flash_dump_ptn();
285
286 flash_init();
287
288 /* scan the keyboard a bit */
289 for(n = 0; n < 50; n++) {
290 boot_poll();
291 }
292
293 if (boot_from_flash) {
294 cprintf("\n ** BOOTING LINUX FROM FLASH **\n");
295 boot_linux_from_flash();
296 }
297
298 usbloader_init();
299
300 for(;;) {
301 usb_poll();
302 }
303 return 0;
304 }
305