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/flash.h>
31 #include <boot/board.h>
32 #include <boot/usb.h>
33
34 #include <boot/bootimg.h>
35 #include <boot/tags.h>
36
37 #include <boot/gpio.h>
38
39 #define VERSION "0.5"
40
41 #define REQUIRE_SIGNATURE 0
42
43 #if REQUIRE_SIGNATURE
44 unsigned key_engineering[2 + 64 + 64] = {
45 64,0x5b022317,-60769447,648742897,-13657530,585562035,591851935,
46 454860199,-1809625305,1868200692,-155297008,-1688439840,-1333607631,
47 -483027189,-2051438457,1030069735,819944365,2133377257,-1978924214,
48 2109678622,1974978919,-1811463608,765849268,1984092281,921245328,
49 -1055062768,1487475997,1209618652,871985152,-611178965,-2057018571,
50 335641539,-1196119550,1550548229,-356223887,1909799623,1281016007,
51 957001635,1005656532,-1027634024,-1576447610,-1917246637,589192795,
52 -1137386186,-1958135372,1933245070,64958951,-1820428322,-1577697840,
53 1824253519,555306239,-1588272058,-1925773018,1205934271,-836584444,
54 -1140961670,-185198349,1293769947,37045923,1516796974,-297288651,
55 651582073,-1337054592,-543971216,-1706823885,-1040652818,-594113104,
56 260093481,-1277656496,56493468,1577037283,773995876,244894933,
57 -2075797967,783894843,880611008,-1433369702,380946504,-2081431477,
58 1377832804,2089455451,-410001201,1245307237,-1228170341,-2062569137,
59 -1327614308,-1671042654,1242248660,-418803721,40890010,-1806767460,
60 -1468529145,-1058158532,1243817302,-527795003,175453645,-210650325,
61 -827053868,-571422860,886300657,2129677324,846504590,-1413102805,
62 -1287448511,-1991140134,56194155,1375685594,-129884114,1393568535,
63 -1098719620,-935279550,1717137954,-1782544741,272581921,-669183778,
64 584824755,1434974827,-1122387971,-810584927,-2147338547,-937541680,
65 -313561073,5506366,-1594059648,-1744451574,1896015834,1496367069,
66 1742853908,508461291,1905056764
67 };
68 #endif
69
get_fastboot_version(void)70 const char *get_fastboot_version(void)
71 {
72 return VERSION;
73 }
74
75 unsigned linux_type = 0;
76 unsigned linux_tags = 0;
77
78 unsigned ramdisk_addr = 0x10400000;
79 unsigned ramdisk_size = 0;
80 unsigned kernel_addr = 0x10008000;
81 unsigned kernel_size = 0;
82
fixup_tags(unsigned * tags,unsigned * out,const char * cmdline)83 static void fixup_tags(unsigned *tags, unsigned *out, const char *cmdline)
84 {
85 unsigned *newtags = (unsigned *) 0x10004000;
86 unsigned *np = newtags;
87 unsigned n;
88 char *oldcmdline = "";
89
90 if(cmdline == 0) cmdline = "";
91
92 /* CORE */
93 *np++ = 2;
94 *np++ = 0x54410001;
95
96 if(tags != 0) {
97 while(*tags) {
98 if(tags[1] == 0x54410001) {
99 /* skip core tag */
100 tags += tags[0];
101 } else if((tags[1] == 0x54420005) && (ramdisk_size != 0)) {
102 /* skip ramdisk if we have one of our own */
103 tags += tags[0];
104 } else if((tags[1] == 0x54410009) && (cmdline[0])) {
105 /* skip existing cmdline so we can replace it */
106 oldcmdline = (char*) (tags + 2);
107 tags += tags[0];
108 } else {
109 /* copy any unknown tags */
110 n = tags[0];
111 while(n-- > 0) {
112 *np++ = *tags++;
113 }
114 }
115 }
116 }
117
118 /* create a ramdisk tag if we need to */
119 if(ramdisk_size) {
120 *np++ = 4;
121 *np++ = 0x54420005;
122 *np++ = ramdisk_addr;
123 *np++ = ramdisk_size;
124 }
125
126 dprintf("cmdline: '%s'\n", oldcmdline);
127 dprintf("cmdline: '%s'\n", cmdline);
128
129 /* create a cmdline tag if we need to */
130 if(cmdline[0]) {
131 int len;
132 char *str = (char*) (np + 2);
133
134 len = strlen(oldcmdline);
135 if(len) {
136 memcpy(str, oldcmdline, len);
137 str += len;
138 *str++ = ' ';
139 }
140
141 len = strlen(cmdline);
142 memcpy(str, cmdline, len);
143 str += len;
144 *str++ = 0;
145
146 /* length in words */
147 len = ((str - ((char*) (np + 2))) + 3) / 4;
148
149 dprintf("CMDLINE: '%s'\n", ((char*) (np + 2)));
150
151 *np++ = 2 + len;
152 *np++ = 0x54410009;
153
154 np += len;
155 }
156
157 /* add footer tag */
158 *np++ = 0;
159 *np++ = 0;
160
161 /* copy it all back to the original tags area */
162 while(newtags < np) {
163 *out++ = *newtags++;
164 }
165 }
166
167 static char cmdline[BOOT_ARGS_SIZE];
168
boot_linux(void)169 static void boot_linux(void)
170 {
171 unsigned *tags = (unsigned*) 0x10000100;
172 void (*entry)(unsigned,unsigned,unsigned) = (void*) kernel_addr;
173
174 if(linux_type == 0) {
175 linux_type = board_machtype();
176 }
177
178 fixup_tags((unsigned*) linux_tags, tags, cmdline);
179
180 entry(0, linux_type, tags);
181
182 for(;;);
183 }
184
185 /* convert a boot_image at kernel_addr into a kernel + ramdisk + tags */
init_boot_linux(void)186 static int init_boot_linux(void)
187 {
188 boot_img_hdr *hdr = (void*) kernel_addr;
189 unsigned page_mask = 2047;
190 unsigned kernel_actual;
191 unsigned ramdisk_actual;
192 unsigned second_actual;
193
194 if((kernel_size < 2048) || memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)){
195 dprintf("bootimg: bad header\n");
196 return -1;
197 }
198
199 if(hdr->page_size != 2048) {
200 dprintf("bootimg: invalid page size\n");
201 return -1;
202 }
203
204 kernel_actual = (hdr->kernel_size + page_mask) & (~page_mask);
205 ramdisk_actual = (hdr->ramdisk_size + page_mask) & (~page_mask);
206 second_actual = (hdr->second_size + page_mask) & (~page_mask);
207
208 if(kernel_size != (kernel_actual + ramdisk_actual + second_actual + 2048)) {
209 dprintf("bootimg: invalid image size");
210 return -1;
211 }
212
213 /* XXX process commandline here */
214 if(hdr->cmdline[0]){
215 hdr->cmdline[BOOT_ARGS_SIZE - 1] = 0;
216 memcpy(cmdline, hdr->cmdline, BOOT_ARGS_SIZE);
217 }
218
219 /* XXX how to validate addresses? */
220 ramdisk_addr = hdr->ramdisk_addr;
221 ramdisk_size = hdr->ramdisk_size;
222
223 kernel_addr = hdr->kernel_addr;
224 kernel_size = hdr->kernel_size;
225
226 dprintf("bootimg: kernel addr=%x size=%x\n",
227 kernel_addr, kernel_size);
228 dprintf("bootimg: ramdisk addr=%x size=%x\n",
229 ramdisk_addr, ramdisk_size);
230
231 memcpy((void*) ramdisk_addr,
232 hdr->magic + 2048 + kernel_actual,
233 ramdisk_size);
234
235 memcpy((void*) kernel_addr,
236 hdr->magic + 2048,
237 kernel_size);
238
239 return 0;
240 }
241
242 static struct usb_endpoint *ep1in, *ep1out;
243 static struct usb_request *rx_req, *tx_req;
244 static unsigned rx_addr;
245 static unsigned rx_length;
246
247 static char *cmdbuf;
248
249 static void usb_rx_cmd_complete(struct usb_request *req, unsigned actual, int status);
250 static void usb_rx_data_complete(struct usb_request *req, unsigned actual, int status);
251
rx_cmd(void)252 static void rx_cmd(void)
253 {
254 struct usb_request *req = rx_req;
255 req->buf = cmdbuf;
256 req->length = 4096;
257 req->complete = usb_rx_cmd_complete;
258 usb_queue_req(ep1out, req);
259 }
260
rx_data(void)261 static void rx_data(void)
262 {
263 struct usb_request *req = rx_req;
264 req->buf = (void*) rx_addr;
265 req->length = (rx_length > 4096) ? 4096 : rx_length;
266 req->complete = usb_rx_data_complete;
267 usb_queue_req(ep1out, req);
268 }
269
tx_status(const char * status)270 static void tx_status(const char *status)
271 {
272 struct usb_request *req = tx_req;
273 int len = strlen(status);
274 // dprintf("tx_status('%s')\n", status);
275 memcpy(req->buf, status, len);
276 req->length = len;
277 req->complete = 0;
278 usb_queue_req(ep1in, req);
279 }
280
usb_rx_data_complete(struct usb_request * req,unsigned actual,int status)281 static void usb_rx_data_complete(struct usb_request *req, unsigned actual, int status)
282 {
283 if(status != 0) return;
284
285 if(actual > rx_length) {
286 actual = rx_length;
287 }
288
289 rx_addr += actual;
290 rx_length -= actual;
291
292 if(rx_length > 0) {
293 rx_data();
294 } else {
295 tx_status("OKAY");
296 rx_cmd();
297 }
298 }
299
hex2unsigned(char * x)300 static unsigned hex2unsigned(char *x)
301 {
302 unsigned n = 0;
303
304 while(*x) {
305 switch(*x) {
306 case '0': case '1': case '2': case '3': case '4':
307 case '5': case '6': case '7': case '8': case '9':
308 n = (n << 4) | (*x - '0');
309 break;
310 case 'a': case 'b': case 'c':
311 case 'd': case 'e': case 'f':
312 n = (n << 4) | (*x - 'a' + 10);
313 break;
314 case 'A': case 'B': case 'C':
315 case 'D': case 'E': case 'F':
316 n = (n << 4) | (*x - 'A' + 10);
317 break;
318 default:
319 return n;
320 }
321 x++;
322 }
323
324 return n;
325 }
326
num_to_hex8(unsigned n,char * out)327 static void num_to_hex8(unsigned n, char *out)
328 {
329 static char tohex[16] = "0123456789abcdef";
330 int i;
331 for(i = 7; i >= 0; i--) {
332 out[i] = tohex[n & 15];
333 n >>= 4;
334 }
335 out[8] = 0;
336 }
337
338 extern char serialno[];
339
340 static char signature[SIGNATURE_SIZE];
341
usb_rx_cmd_complete(struct usb_request * req,unsigned actual,int status)342 static void usb_rx_cmd_complete(struct usb_request *req, unsigned actual, int status)
343 {
344 if(status != 0) return;
345
346 if(actual > 4095) actual = 4095;
347 cmdbuf[actual] = 0;
348
349 dprintf("\n> %s\n",cmdbuf);
350
351 // dprintf("usb_rx_cmd_complete() '%s'\n", cmdbuf);
352
353 if(memcmp(cmdbuf, "reboot", 6) == 0) {
354 tx_status("OKAY");
355 rx_cmd();
356 mdelay(100);
357 board_reboot();
358 }
359 #if 0
360 if(memcmp(cmdbuf, "debug:", 6) == 0) {
361 void debug(char *cmd, char *resp);
362 memcpy(cmdbuf, "OKAY", 5);
363 tx_status(cmdbuf);
364 rx_cmd();
365 mdelay(5000);
366 dprintf("NOW!\n");
367 debug(cmdbuf + 6, cmdbuf + 4);
368 return;
369 }
370 #endif
371 if(memcmp(cmdbuf, "getvar:", 7) == 0) {
372 char response[64];
373 strcpy(response,"OKAY");
374
375 if(!strcmp(cmdbuf + 7, "version")) {
376 strcpy(response + 4, VERSION);
377 } else if(!strcmp(cmdbuf + 7, "product")) {
378 strcpy(response + 4, PRODUCTNAME);
379 } else if(!strcmp(cmdbuf + 7, "serialno")) {
380 strcpy(response + 4, serialno);
381 } else {
382 board_getvar(cmdbuf + 7, response + 4);
383 }
384 tx_status(response);
385 rx_cmd();
386 return;
387 }
388
389 if(memcmp(cmdbuf, "download:", 9) == 0) {
390 char status[16];
391 rx_addr = kernel_addr;
392 rx_length = hex2unsigned(cmdbuf + 9);
393 if (rx_length > (64*1024*1024)) {
394 tx_status("FAILdata too large");
395 rx_cmd();
396 return;
397 }
398 kernel_size = rx_length;
399 dprintf("recv data addr=%x size=%x\n", rx_addr, rx_length);
400 strcpy(status,"DATA");
401 num_to_hex8(rx_length, status + 4);
402 tx_status(status);
403 rx_data();
404 return;
405 }
406
407 if(memcmp(cmdbuf, "erase:", 6) == 0){
408 struct ptentry *ptn;
409 ptn = flash_find_ptn(cmdbuf + 6);
410 if(ptn == 0) {
411 tx_status("FAILpartition does not exist");
412 rx_cmd();
413 return;
414 }
415 dprintf("erasing '%s'\n", ptn->name);
416 cprintf("erasing '%s'", ptn->name);
417 if(flash_erase(ptn)) {
418 tx_status("FAILfailed to erase partition");
419 rx_cmd();
420 cprintf(" - FAIL\n");
421 return;
422 } else {
423 dprintf("partition '%s' erased\n", ptn->name);
424 cprintf(" - OKAY\n");
425 }
426 tx_status("OKAY");
427 rx_cmd();
428 return;
429 }
430
431 if(memcmp(cmdbuf, "flash:", 6) == 0){
432 struct ptentry *ptn;
433 int extra = 0;
434 ptn = flash_find_ptn(cmdbuf + 6);
435 if(kernel_size == 0) {
436 tx_status("FAILno image downloaded");
437 rx_cmd();
438 return;
439 }
440 if(ptn == 0) {
441 tx_status("FAILpartition does not exist");
442 rx_cmd();
443 return;
444 }
445 if(!strcmp(ptn->name,"boot") || !strcmp(ptn->name,"recovery")) {
446 if(memcmp((void*) kernel_addr, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
447 tx_status("FAILimage is not a boot image");
448 rx_cmd();
449 return;
450 }
451 }
452 #if REQUIRE_SIGNATURE
453 {
454 unsigned char digest[DIGEST_SIZE];
455 compute_digest((void*) kernel_addr, kernel_size, digest);
456 if (is_signature_okay(digest, signature, key_engineering)) {
457 dprintf("verified by engineering key\n");
458 } else {
459 tx_status("FAILsignature did not verify");
460 rx_cmd();
461 return;
462 }
463 }
464 #endif
465 if(!strcmp(ptn->name,"system") || !strcmp(ptn->name,"userdata")) {
466 extra = 64;
467 } else {
468 kernel_size = (kernel_size + 2047) & (~2047);
469 }
470 dprintf("writing %d bytes to '%s'\n",
471 kernel_size, ptn->name);
472 cprintf("writing '%s' (%d bytes)", ptn->name, kernel_size);
473 if(flash_write(ptn, extra, (void*) kernel_addr, kernel_size)) {
474 tx_status("FAILflash write failure");
475 rx_cmd();
476 cprintf(" - FAIL\n");
477 return;
478 } else {
479 dprintf("partition '%s' updated\n", ptn->name);
480 cprintf(" - OKAY\n");
481 }
482 tx_status("OKAY");
483 rx_cmd();
484 return;
485 }
486 if(memcmp(cmdbuf, "boot", 4) == 0) {
487 if(init_boot_linux()) {
488 tx_status("FAILinvalid boot image");
489 rx_cmd();
490 return;
491 }
492 dprintf("booting linux...\n");
493 cprintf("\nbooting linux...\n");
494 tx_status("OKAY");
495 mdelay(10);
496 usb_shutdown();
497 boot_linux();
498 return;
499 }
500 if(memcmp(cmdbuf, "signature", 9) == 0) {
501 if (kernel_size != SIGNATURE_SIZE) {
502 tx_status("FAILsignature not 256 bytes long");
503 rx_cmd();
504 return;
505 }
506 memcpy(signature, (void*)kernel_addr, SIGNATURE_SIZE);
507 tx_status("OKAY");
508 rx_cmd();
509 return;
510 }
511
512 tx_status("FAILinvalid command");
513 rx_cmd();
514 }
515
usb_status(unsigned online,unsigned highspeed)516 void usb_status(unsigned online, unsigned highspeed)
517 {
518 if(online) {
519 dprintf("usb: online (%s)\n", highspeed ? "highspeed" : "fullspeed");
520 rx_cmd();
521 }
522 }
523
usbloader_init(void)524 void usbloader_init(void)
525 {
526 usb_init();
527
528 ep1out = usb_endpoint_alloc(1, 0, 512);
529 ep1in = usb_endpoint_alloc(1, 1, 512);
530 rx_req = usb_request_alloc(4096);
531 tx_req = usb_request_alloc(4096);
532 cmdbuf = rx_req->buf;
533
534 boot_register_poll_func(usb_poll);
535 }
536