blob: 62465896db9beee89d7c7da6ad8c8278ecde87e0 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
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/*
30 * Copyright (c) 2010 Marvell Inc.
31 * Modified by Lei Wen <leiwen@marvell.com>
32 *
33 * SPDX-License-Identifier: GPL-2.0+
34 *
35 * ported from m2011.09 by yizhang@marvell.com, 28-Mar-2014
36 */
37#include <common.h>
38#include <fastboot.h>
39#include <sparse_format.h>
40#include <jffs2/load_kernel.h>
41#include <linux/mtd/mtd.h>
42#include <mmc.h>
43#include <malloc.h>
44
45#ifdef CONFIG_MRVL_BOOT
46#include <mv_boot.h>
47#endif
48
49DECLARE_GLOBAL_DATA_PTR;
50#define SECTOR_SIZE 512
51
52#ifdef CONFIG_TEE_OS
53#define FB_BUFF_ADDR 0x2800000 /* 40MB offset */
54#else
55#define FB_BUFF_ADDR 0x2000000 /* 32MB offset */
56#endif
57
58enum fb_dev {
59 FB_INVALID = 0,
60 FB_NOR = MTD_DEV_TYPE_NOR,
61 FB_NAND = MTD_DEV_TYPE_NAND,
62 FB_ONENAND = MTD_DEV_TYPE_ONENAND,
63 FB_SPIFLASH,
64 FB_MMC,
65 FB_MAX,
66};
67
68#ifndef CONFIG_FB_RESV
69#define CONFIG_FB_RESV 64
70#endif
71
72#define MAX_NAME_NUM 36
73#define UDC_OUT_PACKET_SIZE 0x200
74block_dev_desc_t *mmc_dev;
75static char commands[CONFIG_SYS_CBSIZE];
76/* For each part has four attributes:
77 * device type, device num, start address, size
78 */
79struct fb_part {
80 char name[MAX_NAME_NUM];
81#define PART_ATTR_YAFFS 1
82#define PART_NUM_MASK 0xE0000000
83#define PART_NUM(x) (((x) & PART_NUM_MASK) >> 29)
84 unsigned int attr;
85 unsigned long long start;
86 unsigned long long size;
87};
88
89struct fb_parts {
90 enum fb_dev dev;
91 int dev_num;
92 int part_num;
93 int align_len;
94 struct fb_part *part;
95};
96
97static struct fb_parts *parts;
98#ifdef CONFIG_MTD_DEVICE
99#ifdef CONFIG_SYS_FB_YAFFS
100static char *part_yaffs[] = CONFIG_SYS_FB_YAFFS;
101#else
102static char *part_yaffs[] = {NULL};
103#endif
104#endif
105
106static char *rcv_buf;
107static unsigned fb_mem, ramdisk_addr, ramdisk_size, kernel_addr, kernel_size;
108static int keep_running, is_yaffs, part_num, onfly;
109static int bootsp, first_rcv, need_unsparse;
110
111#define BOOT_MAGIC "ANDROID!"
112#define BOOT_MAGIC_SIZE 8
113#define BOOT_NAME_SIZE 16
114#define BOOT_ARGS_SIZE 512
115
116struct boot_img_hdr {
117 unsigned char magic[BOOT_MAGIC_SIZE];
118
119 unsigned kernel_size; /* size in bytes */
120 unsigned kernel_addr; /* physical load addr */
121
122 unsigned ramdisk_size; /* size in bytes */
123 unsigned ramdisk_addr; /* physical load addr */
124
125 unsigned second_size; /* size in bytes */
126 unsigned second_addr; /* physical load addr */
127
128 unsigned tags_addr; /* physical addr for kernel tags */
129 unsigned page_size; /* flash page size we assume */
130 unsigned unused[2]; /* future expansion: should be 0 */
131
132 unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
133
134 unsigned char cmdline[BOOT_ARGS_SIZE];
135
136 unsigned id[8]; /* timestamp / checksum / sha1 / etc */
137};
138
139static unsigned rx_addr;
140static unsigned rx_length;
141static unsigned long long flash_start;
142static unsigned long long flash_len;
143
144static int init_boot_linux(void)
145{
146 struct boot_img_hdr *hdr = (void *)(uintptr_t)fb_mem;
147 unsigned page_mask = 2047;
148 unsigned kernel_actual;
149 unsigned ramdisk_actual;
150 unsigned second_actual;
151
152 if (kernel_size < 2048) {
153 printf("bootimg: bad header, kernel_size is wrong\n");
154 return -1;
155 }
156
157 if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
158 printf("bootimg: bad header\n");
159 return -1;
160 }
161
162 if (hdr->page_size != 2048) {
163 printf("bootimg: invalid page size\n");
164 return -1;
165 }
166
167 kernel_actual = (hdr->kernel_size + page_mask) & (~page_mask);
168 ramdisk_actual = (hdr->ramdisk_size + page_mask) & (~page_mask);
169 second_actual = (hdr->second_size + page_mask) & (~page_mask);
170
171 if (kernel_size !=
172 (kernel_actual + ramdisk_actual + second_actual + 2048)) {
173 printf("bootimg: invalid image size");
174 return -1;
175 }
176
177 /* XXX process commandline here */
178 if (hdr->cmdline[0]) {
179 hdr->cmdline[BOOT_ARGS_SIZE - 1] = 0;
180 printf("cmdline is: %s\n", hdr->cmdline);
181 setenv("bootargs", (char *)hdr->cmdline);
182 }
183
184 /* XXX how to validate addresses? */
185 kernel_addr = (uintptr_t)hdr + 2048;
186 kernel_size = hdr->kernel_size;
187 ramdisk_size = hdr->ramdisk_size;
188 if (ramdisk_size > 0)
189 ramdisk_addr = kernel_addr + 2048 + kernel_size;
190 else
191 ramdisk_addr = 0;
192
193 printf("bootimg: kernel addr=0x%x size=0x%x\n",
194 kernel_addr, kernel_size);
195 printf("bootimg: ramdisk addr=0x%x size=0x%x\n",
196 ramdisk_addr, ramdisk_size);
197
198 return 0;
199}
200
201static int composite_command(int is_write)
202{
203 char tmp[CONFIG_SYS_CBSIZE];
204 ulong start, len;
205
206 if (need_unsparse) {
207 need_unsparse = 0;
208 sprintf(commands,
209 "mmc dev %d 0; unsparse mmc %d 0x%x 0x%llx 0x%llx",
210 parts->dev_num, parts->dev_num,
211 fb_mem, flash_start, parts->part[part_num].size);
212 goto DIRECT_BURN;
213 }
214
215 start = (parts->dev == FB_MMC)
216 ? flash_start / SECTOR_SIZE : flash_start;
217 len = (parts->dev == FB_MMC) ? flash_len / SECTOR_SIZE : flash_len;
218 if (is_write) {
219 if (is_yaffs)
220 sprintf(tmp, "write.yaffs 0x%x 0x%lx 0x%lx",
221 fb_mem, start, len);
222 else
223 sprintf(tmp, "write 0x%x 0x%lx 0x%lx",
224 fb_mem, start, len);
225 } else {
226 sprintf(tmp, "erase 0x%lx 0x%lx", start, len);
227 }
228
229 switch (parts->dev) {
230 case FB_NOR:
231 sprintf(commands, "sf %s", tmp); break;
232 case FB_NAND:
233#ifdef CONFIG_PXA182X
234 sprintf(commands, "nand device %d; nand %s",
235 parts->dev_num, tmp);
236#else
237 sprintf(commands, "spi_flash %s", tmp);
238#endif
239 break;
240 case FB_ONENAND:
241 sprintf(commands, "onenand %s", tmp); break;
242 case FB_SPIFLASH:
243 sprintf(commands, "spi_flash %s",
244 parts->dev_num, tmp); break;
245 case FB_MMC:
246 sprintf(commands, "mmc dev %d %d; mmc %s; mmc dev %d 0",
247 parts->dev_num, PART_NUM(parts->part[part_num].attr),
248 tmp, parts->dev_num);
249 break;
250 default:
251 printf("Err dev!! %d\n", parts->dev);
252 return 0;
253 }
254
255DIRECT_BURN:
256 printf("command::%s\n", commands);
257 run_command(commands, 0);
258 return 0;
259}
260
261static void burn_image(int force_burn)
262{
263 int len = rx_addr - fb_mem;
264 int checklen = (is_yaffs) ? ((CONFIG_SYS_FASTBOOT_ONFLY_SZ / 32) * 33)
265 : CONFIG_SYS_FASTBOOT_ONFLY_SZ;
266 if (len == checklen || force_burn) {
267 if (!is_yaffs) {
268 flash_len = len & ~(parts->align_len - 1);
269 if (flash_len != len) {
270 flash_len += parts->align_len;
271 memset((char *)(uintptr_t)rx_addr, 0xff,
272 flash_len - len);
273 }
274 } else {
275 flash_len = len;
276 }
277 composite_command(1);
278 flash_start += CONFIG_SYS_FASTBOOT_ONFLY_SZ;
279 fb_set_buf((void *)(uintptr_t)fb_mem);
280 rx_addr = fb_mem;
281 }
282}
283
284static int check_part(char *name)
285{
286 int i;
287 for (i = 0; i < parts->part_num; i++) {
288 if (strcmp(name, parts->part[i].name) == 0)
289 break;
290 }
291 if (i == parts->part_num) {
292 printf("!!!!!!!!!!There is no such part!\n");
293 fb_tx_status("FAILno such part");
294 return -1;
295 }
296
297 return i;
298}
299
300static int find_devnum(const char *p)
301{
302 int devnum;
303 if (*p == '\0') {
304 printf("no partition number specified\n");
305 return -1;
306 }
307 devnum = simple_strtoul(p, (char **)&p, 0);
308 if (*p != '\0') {
309 printf("unexpected trailing character '%c'\n", *p);
310 return -1;
311 }
312 return devnum;
313}
314
315static int init_partitions(void)
316{
317 struct mmc *mmc;
318 int i, pnum = 0;
319 disk_partition_t info;
320 const char *p;
321
322 mmc_dev = NULL;
323 p = getenv("fbenv");
324 if (0 == strncmp(p, "mmc", 3)) {
325#ifdef CONFIG_MMC
326 parts = malloc(sizeof(struct fb_parts));
327 if (!parts) {
328 printf("Out of memory %s:%d\n", __func__, __LINE__);
329 return 1;
330 }
331 i = find_devnum(p + 3);
332 if (i == -1)
333 return 1;
334 mmc = find_mmc_device(i);
335 if (!mmc)
336 return 1;
337 mmc_init(mmc);
338 parts->part_num = 0;
339 parts->part = 0;
340 parts->align_len = SECTOR_SIZE;
341 parts->dev = FB_MMC;
342 parts->dev_num = i;
343 mmc_dev = mmc_get_dev(i);
344 pnum = get_partition_num(mmc_dev);
345 if (pnum) {
346 parts->part = malloc(sizeof(struct fb_part)*pnum);
347 if (!parts->part) {
348 printf("Out of memory %s:%d\n", __func__, __LINE__);
349 return 1;
350 }
351 } else {
352 parts->part = NULL;
353 }
354 parts->part_num = pnum;
355 if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) {
356 for (i = 1; i <= pnum; i++) {
357 int len;
358 if (get_partition_info(mmc_dev, i, &info))
359 break;
360 len = strlen((char *)info.name);
361 len = (len < MAX_NAME_NUM)
362 ? len : MAX_NAME_NUM - 1;
363 memcpy(parts->part[i - 1].name, info.name, len);
364 parts->part[i - 1].name[len] = 0;
365 parts->part[i - 1].start =
366 (unsigned long long)info.start * info.blksz;
367 parts->part[i - 1].size =
368 (unsigned long long)info.size * info.blksz;
369 parts->part[i - 1].attr = 0;
370 }
371 }
372#else
373 printf("CONFIG_MMC not be defined!!\n");
374 return 1;
375#endif
376 } else {
377#ifdef CONFIG_MTD_DEVICE
378 enum fb_dev type;
379 struct mtd_device *dev;
380 struct part_info *part;
381 int j, align;
382 if (mtdparts_init()) {
383 printf("mtd part init fail!\n");
384 return 1;
385 }
386 if (0 == strncmp(p, "nand", 4)) {
387 p += 4;
388 type = FB_NAND;
389 align = CONFIG_SYS_FASTBOOT_ONFLY_SZ;
390 } else if (0 == strncmp(p, "onenand", 4)) {
391 p += 7;
392 type = FB_ONENAND;
393 align = CONFIG_SYS_FASTBOOT_ONFLY_SZ;
394 } else if (0 == strncmp(p, "nor", 3)) {
395 p += 3;
396 type = FB_NOR;
397 align = 1;
398 } else if (0 == strncmp(p, "spi_flash", 9)) {
399 p += 9;
400 type = MTD_DEV_TYPE_NAND;
401 align = CONFIG_SYS_FASTBOOT_ONFLY_SZ;
402 } else {
403 printf("fbenv must de defined!!");
404 return 1;
405 }
406
407 i = find_devnum(p);
408 if (i == -1)
409 return 1;
410
411 dev = device_find(type, i);
412 if (dev == NULL) {
413 printf("There is no device as %s\n", getenv("fbenv"));
414 return 1;
415 }
416 if (!dev->num_parts) {
417 printf("Dev num parts is 0\n");
418 return 1;
419 }
420 parts = malloc(sizeof(struct fb_parts));
421 if (!parts) {
422 printf("Out of memory %s:%d\n", __func__, __LINE__);
423 return 1;
424 }
425 parts->part = malloc(sizeof(struct fb_part)*dev->num_parts);
426 if (!parts->part) {
427 printf("Out of memory %s:%d\n", __func__, __LINE__);
428 return 1;
429 }
430 parts->dev = type;
431 parts->dev_num = i;
432 parts->part_num = dev->num_parts;
433 parts->align_len = align;
434 pnum = dev->num_parts;
435 for (i = 0; i < dev->num_parts; i++) {
436 part = mtd_part_info(dev, i);
437 if (part) {
438 int len;
439 len = strlen((char *)part->name);
440 len = (len < MAX_NAME_NUM)
441 ? len : MAX_NAME_NUM - 1;
442 memcpy(parts->part[i].name, part->name, len);
443 parts->part[i].name[len] = 0;
444 parts->part[i].start = part->offset;
445 parts->part[i].size = part->size;
446 parts->part[i].attr = 0;
447 for (j = 0; j < ARRAY_SIZE(part_yaffs); j++)
448 if (!memcmp(part_yaffs[j], part->name,
449 strlen(part->name))) {
450 parts->part[i].attr =
451 PART_ATTR_YAFFS;
452 break;
453 }
454 } else {
455 printf("fail to find part: %s\n", part->name);
456 return 1;
457 }
458 }
459#else
460 printf("CONFIG_MTD_DEVICE not be defined!!\n");
461 return 1;
462#endif
463 }
464
465 switch (parts->dev) {
466 case FB_NOR:
467 printf("nor\n"); break;
468 case FB_NAND:
469 printf("nand\n"); break;
470 case FB_ONENAND:
471 printf("onenand\n"); break;
472 case FB_MMC:
473 printf("mmc\n"); break;
474 case FB_SPIFLASH:
475 printf("spi_flash\n"); break;
476 default:
477 printf("error!!!\n"); break;
478 }
479 for (i = 0; i < pnum; i++)
480 printf("part %3d::attr 0x%x::%12s\t start 0x%08llx, size 0x%08llx\n",
481 i, parts->part[i].attr, parts->part[i].name, parts->part[i].start, parts->part[i].size);
482 return 0;
483}
484
485static int modify_part(char *name, unsigned long long x[3])
486{
487 int len = strlen(name);
488 parts->part = realloc(parts->part,
489 sizeof(struct fb_part)*(parts->part_num + 1));
490 if (!parts->part) {
491 printf("Out of memory %s:%d\n", __func__, __LINE__);
492 return 1;
493 }
494 len = (len < MAX_NAME_NUM) ? len : MAX_NAME_NUM - 1;
495 memcpy(parts->part[parts->part_num].name, name, len);
496 parts->part[parts->part_num].name[len] = 0;
497 parts->part[parts->part_num].attr = (unsigned int)x[0];
498 parts->part[parts->part_num].start = x[1];
499 parts->part[parts->part_num].size = x[2];
500 parts->part_num++;
501
502 return 0;
503}
504/* for test */
505/*
506#define RAMDISK_LOADADDR 0x2000000
507#define BOOTIMG_EMMC_ADDR 0x1000000
508#define CONFIG_MMC_BOOT_DEV "mmc dev 2 0"
509*/
510#ifdef CONFIG_ANDROID_BOOT_IMAGE
511static int mkbootimg(void *kernel, unsigned kernel_size)
512{
513#ifdef CONFIG_ANDROID_BOOT_IMAGE
514 unsigned long ramdisk_addr = RAMDISK_LOADADDR;
515#endif
516 struct boot_img_hdr *hdr = (struct boot_img_hdr *)kernel;
517 struct boot_img_hdr *ahdr = (void *)ramdisk_addr;
518 unsigned ramdisk_offsize;
519 char cmd[128];
520 unsigned long base_addr = BOOTIMG_EMMC_ADDR;
521 base_addr /= SECTOR_SIZE;
522
523 /* If the burning image is not bootimg or already have ramdisk*/
524 if (memcmp(BOOT_MAGIC, hdr->magic, BOOT_MAGIC_SIZE) ||
525 hdr->ramdisk_size) {
526 return 0;
527 }
528
529 /* parse the raw image header and read the ramdisk to memory*/
530 sprintf(cmd, "%s; mmc read %lx %lx 0x8",
531 CONFIG_MMC_BOOT_DEV, ramdisk_addr, base_addr);
532 run_command(cmd, 0);
533 if (!memcmp(BOOT_MAGIC, ahdr->magic, BOOT_MAGIC_SIZE) &&
534 ahdr->ramdisk_size) {
535 hdr->ramdisk_size = ahdr->ramdisk_size;
536 ramdisk_offsize = ALIGN(ahdr->kernel_size, ahdr->page_size)
537 + ahdr->page_size;
538 ramdisk_offsize = ramdisk_offsize / SECTOR_SIZE;
539
540 sprintf(cmd, "%s; mmc read 0x%08lx %lx 0x06000",
541 CONFIG_MMC_BOOT_DEV, ramdisk_addr, base_addr + ramdisk_offsize);
542 run_command(cmd, 0);
543 } else {
544 /*In the flash, there is no boot.img*/
545 return 0;
546 }
547 /*write ramdisk.img to flash */
548 ramdisk_offsize = hdr->page_size + ALIGN(hdr->kernel_size, hdr->page_size);
549 ramdisk_offsize = ramdisk_offsize / SECTOR_SIZE;
550 sprintf(cmd, "%s; mmc write %lx %lx 0x06000",
551 CONFIG_MMC_BOOT_DEV, ramdisk_addr, base_addr + ramdisk_offsize);
552 run_command(cmd, 0);
553 return 1;
554}
555#endif
556#define MAX_RESP_SZ 64
557void rcv_cmd(void)
558{
559 char status[MAX_RESP_SZ];
560 int len;
561 static char *cmdbuf;
562
563 len = fb_get_rcv_len();
564 cmdbuf = (char *)fb_get_buf();
565
566 if (rx_length) {
567 if (rx_length > len) {
568 rx_length -= len;
569 rx_addr += len;
570 } else {
571 printf("rx_length: 0x%x\n", rx_length);
572 rx_addr += rx_length;
573 rx_length = 0;
574 }
575
576 fb_set_buf(cmdbuf + len);
577 /* Here we do some check for the downloaded image header */
578#ifdef CONFIG_CMD_UNSPARSE
579 if (first_rcv) {
580 sparse_header_t *header;
581
582 first_rcv = 0;
583 header = (sparse_header_t *)(uintptr_t)fb_mem;
584 if (header->magic == SPARSE_HEADER_MAGIC) {
585 if (parts->dev == FB_MMC) {
586 if (onfly)
587 onfly = 0;
588 need_unsparse = 1;
589 } else {
590 printf("Only mmc support sparsed Image now!\n");
591 }
592 }
593 }
594#endif
595 if (!rx_length) {
596 if (onfly)
597 burn_image(1);
598 fb_tx_status("OKAY");
599 fb_set_buf(rcv_buf);
600 onfly = 0;
601 } else {
602 if (onfly)
603 burn_image(0);
604 }
605
606 return;
607 }
608 if (len >= UDC_OUT_PACKET_SIZE)
609 len = UDC_OUT_PACKET_SIZE - 1;
610 cmdbuf[len] = 0;
611
612 printf("\n> %s\n", cmdbuf);
613
614 if (memcmp(cmdbuf, "download:", 9) == 0) {
615 rx_addr = fb_mem;
616 first_rcv = 1;
617 fb_set_buf((void *)(uintptr_t)rx_addr);
618 rx_length = simple_strtoul(cmdbuf + 9, NULL, 16);
619 if ((onfly && (rx_length > flash_len)) ||
620 (!onfly && (rx_length > (CONFIG_FB_RESV*1024*1024)))) {
621 fb_tx_status("FAILdata too large");
622 rx_length = 0;
623 return;
624 }
625 kernel_size = rx_length;
626 printf("recv data addr=%x size=%x\n", rx_addr, rx_length);
627 strcpy(status, "DATA");
628 sprintf(status + 4, "%08x", rx_length);
629 fb_tx_status(status);
630 return;
631 }
632
633 if (memcmp(cmdbuf, "boot", 4) == 0) {
634 if (init_boot_linux()) {
635 fb_tx_status("FAIL invalid boot image");
636 } else {
637 printf("booting linux...\n");
638 fb_tx_status("OKAY");
639 if (!bootsp) {
640#ifdef CONFIG_MRVL_BOOT
641 image_load_notify(kernel_addr);
642 sprintf(status, "boot");
643#else
644 if (ramdisk_size > 0) {
645 printf("kernel_addr = 0x%x, ramdisk_addr = 0x%x, ramdisk_size = 0x%x",
646 kernel_addr, ramdisk_addr, ramdisk_size);
647 sprintf(status, "bootm 0x%x 0x%x 0x%x",
648 kernel_addr, ramdisk_addr, ramdisk_size);
649 } else {
650 printf("kernel_addr = 0x%x\n", kernel_addr);
651 sprintf(status, "bootm 0x%x", kernel_addr);
652 }
653#endif
654 } else {
655 sprintf(status, "go 0x%x", kernel_addr);
656 }
657
658 printf("cmd:%s\n", status);
659 run_command(status, 0);
660 fb_tx_status("FAILNot zImage, use bootsp oem cmd to boot special app");
661 }
662 return;
663 }
664 onfly = 0;
665 bootsp = 0;
666 if (memcmp(cmdbuf, "flash", 5) == 0) {
667 int ret = 0;
668 if (rx_addr > fb_mem) {
669 part_num = check_part(cmdbuf + 6);
670 if (part_num < 0)
671 return;
672 is_yaffs = parts->part[part_num].attr & PART_ATTR_YAFFS;
673 flash_start = parts->part[part_num].start;
674 flash_len = parts->part[part_num].size;
675#ifdef CONFIG_ANDROID_BOOT_IMAGE
676 if (mkbootimg((void *)(uintptr_t)fb_mem, kernel_size))
677 flash_len = kernel_size;
678#endif
679 if ((rx_addr - fb_mem) > flash_len) {
680 fb_tx_status("FAILdata too large");
681 return;
682 }
683 burn_image(1);
684 }
685 is_yaffs = 0;
686 if (!ret)
687 fb_tx_status("OKAY");
688 return;
689 }
690
691 if (memcmp(cmdbuf, "senddata", 8) == 0) {
692 int i, ret;
693 char *p;
694
695 ret = sprintf(status, "OKAY");
696 p = status + ret;
697 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
698 if (!gd->bd->bi_dram[i].size)
699 continue;
700
701 ret = sprintf(p, "%lx:%lx:",
702 gd->bd->bi_dram[i].start, gd->bd->bi_dram[i].size);
703 p += ret;
704 }
705
706 fb_tx_status(status);
707 return;
708 }
709
710 if (memcmp(cmdbuf, "upload", 6) == 0) {
711 char *s = cmdbuf + 6, *p;
712 unsigned long upload_start, upload_sz;
713
714 p = strchr(s, ':');
715 if (!p) {
716 fb_tx_status("FAILno valid start pos");
717 return;
718 }
719 *p = 0;
720 upload_start = simple_strtoul(s, (char **)&s, 16);
721 s = p + 1;
722 p = strchr(s, ':');
723 if (!p) {
724 fb_tx_status("FAILno valid start pos");
725 return;
726 }
727 *p = 0;
728 upload_sz = simple_strtoul(s, (char **)&s, 16);
729 if (!upload_sz) {
730 fb_tx_status("FAILno valid upload sz");
731 return;
732 }
733
734 fb_tx_data((void *)upload_start, upload_sz);
735 return;
736 }
737
738 if (memcmp(cmdbuf, "erase", 5) == 0) {
739 part_num = check_part(cmdbuf + 6);
740 if (part_num < 0)
741 return;
742 flash_start = parts->part[part_num].start;
743 flash_len = parts->part[part_num].size;
744 composite_command(0);
745 fb_tx_status("OKAY");
746 return;
747 }
748
749 if (memcmp(cmdbuf, "oem", 3) == 0) {
750 if (memcmp(cmdbuf + 4, "onfly", 5) == 0) {
751 onfly = 0;
752 part_num = check_part(cmdbuf + 10);
753 if (part_num < 0)
754 return;
755 is_yaffs = parts->part[part_num].attr & PART_ATTR_YAFFS;
756 flash_start = parts->part[part_num].start;
757 flash_len = parts->part[part_num].size;
758 onfly = 1;
759 fb_tx_status("OKAY");
760 return;
761 }
762 if (memcmp(cmdbuf + 4, "bootsp", 6) == 0) {
763 bootsp = 1;
764 fb_tx_status("OKAY");
765 return;
766 }
767 if (memcmp(cmdbuf + 4, "setno", 5) == 0) {
768 char *s = cmdbuf + 4, *p;
769 p = strchr(s, ':');
770 s = p + 1;
771 if (!p || !s) {
772 fb_tx_status("FAILno valid serial no");
773 return;
774 }
775 setenv("fb_serial", s);
776 fb_tx_status("OKAY");
777 fb_init();
778 return;
779 }
780 if (memcmp(cmdbuf + 4, "part", 4) == 0) {
781 unsigned int i;
782 unsigned long long x[3];
783 char *s = cmdbuf + 8, *p, *name;
784 p = strchr(s, ':');
785 if (p) {
786 s = p + 1;
787 p = strchr(s, ':');
788 *p = 0;
789 name = s;
790 if (!name) {
791 fb_tx_status("FAILno name specified");
792 return;
793 }
794 s = p + 1;
795 for (i = 0; i < 3 && s; i++) {
796 p = strchr(s, ':');
797 if (p)
798 *p = 0;
799 x[i] = simple_strtoull(s,
800 (char **)&s, 0);
801 if (p)
802 s = p + 1;
803 else
804 break;
805 }
806 if (i == 2) {
807 if (modify_part(name, x)) {
808 fb_tx_status("FAILadd part error");
809 return;
810 } else {
811 fb_tx_status("OKAY");
812 return;
813 }
814 }
815 }
816
817 i = 0;
818 init_partitions();
819 sprintf(status, "INFO::there %s %d partition",
820 (parts->part_num == 1) ? "is" : "are",
821 parts->part_num);
822 fb_tx_status(status);
823 do {
824 strcpy(status, "INFO");
825 status[4] = '\0';
826 for (; i < parts->part_num; i++) {
827 strcat(status, parts->part[i].name);
828 strcat(status, ",");
829 if ((i == (parts->part_num - 1)) ||
830 (strlen(status) + strlen(parts->part[i + 1].name) >= (MAX_RESP_SZ - 1))) {
831 i++;
832 fb_tx_status(status);
833 break;
834 }
835 }
836 } while (i < parts->part_num);
837 fb_tx_status("OKAY");
838 return;
839 }
840 fb_tx_status("FAILbad oem command");
841 return;
842 }
843 if (memcmp(cmdbuf, "reboot", 6) == 0) {
844 fb_tx_status("OKAY");
845 if (strncmp(cmdbuf + 6, "-bootloader", 11) == 0)
846 keep_running = 0;
847 else
848 reset_cpu(0);
849 return;
850 }
851
852 fb_tx_status("FAILinvalid command");
853}
854
855int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
856{
857 ALLOC_CACHE_ALIGN_BUFFER(char, cmd_pool, 512);
858 rx_length = 0;
859 part_num = -1;
860 onfly = 0;
861 bootsp = 0;
862 first_rcv = 0;
863 fb_mem = FB_BUFF_ADDR;
864 ramdisk_size = 0;
865 kernel_addr = 0;
866 kernel_size = 0;
867 keep_running = 1;
868 is_yaffs = 0;
869 need_unsparse = 0;
870
871 init_partitions();
872
873 rcv_buf = cmd_pool;
874 fb_init();
875 fb_set_buf((void *)rcv_buf);
876 while (keep_running)
877 fb_run();
878 keep_running = 1;
879 fb_halt();
880 return 0;
881}
882
883U_BOOT_CMD(
884 fb, 1, 1, do_fastboot,
885 "android fastboot client application",
886 ""
887 );