1 /* SPDX-License-Identifier: GPL-2.0+ */
3 * Copyright 2019 Broadcom Ltd.
8 #include <asm/arch/ddr.h>
9 #include <linux/ctype.h>
14 #include <environment.h>
16 #include <linux/bitops.h>
17 #include <linux/crc32.h>
18 #include <ubi_uboot.h>
19 #include "bca_common.h"
24 static struct reimager rei
= { 0 };
26 DECLARE_GLOBAL_DATA_PTR
;
28 __weak
void boost_cpu_clock(void)
32 int board_sdk_late_init_e(void)
36 /* CUSTOMIZE -- set default behavior here */
37 env_set("bootdelay", "5");
38 env_set("bootcmd", "reimage auto");
42 void hook_dram_init(void)
46 #if defined(CONFIG_BCM63138) || defined(CONFIG_BCM63148) || defined(CONFIG_BCM4908) || defined(CONFIG_BCM6858)
48 (MEMC
->GLB_GCFG
& MEMC_GLB_GCFG_SIZE1_MASK
) >>
49 MEMC_GLB_GCFG_SIZE1_SHIFT
;
52 (MEMC
->GLB_FSBL_STATE
& MEMC_GLB_FSBL_DRAM_SIZE_MASK
) >>
53 MEMC_GLB_FSBL_DRAM_SIZE_SHIFT
;
55 size
= 1 << shift
; // in MB
56 printf("DDR size from controller %dMB\n", size
);
57 gd
->ram_size
= (phys_size_t
) (size
<< 20);
59 gd
->bd
->bi_dram
[0].start
= 0;
60 gd
->bd
->bi_dram
[0].size
= (phys_size_t
) gd
->ram_size
;
63 static int check_nv_crc(struct nvram_s
*nv
);
65 static int check_nv_crc(struct nvram_s
*nv
)
68 printf("original CRC 0x%x\n", nv
->ulCheckSum
);
69 orig
= nv
->ulCheckSum
;
71 /* use crc32_le to get standard CRC rather than the unusual one
72 * used for uboot environment files */
73 new = crc32_le(0xffffffff, nv
, 1024);
74 printf("computed CRC 0x%x\n", new);
75 nv
->ulCheckSum
= orig
;
79 static int ubi_dev_scan(struct mtd_info
*info
, const char *vid_header_offset
);
81 static int ubi_dev_scan(struct mtd_info
*info
, const char *vid_header_offset
)
83 char ubi_mtd_param_buffer
[80];
86 if (!vid_header_offset
)
87 sprintf(ubi_mtd_param_buffer
, "%s", info
->name
);
89 sprintf(ubi_mtd_param_buffer
, "%s,%s", info
->name
,
92 err
= ubi_mtd_param_parse(ubi_mtd_param_buffer
, NULL
);
103 static int erase(struct mtd_info
*mtd
, int first
, int blocks
);
105 static int erase(struct mtd_info
*mtd
, int first
, int blocks
)
107 struct erase_info erase_op
= { };
111 erase_op
.addr
= first
* mtd
->erasesize
;
112 erase_op
.len
= blocks
* mtd
->erasesize
;
114 printf("Erasing %d blocks from block %d\n", blocks
, first
);
116 while (erase_op
.len
) {
117 ret
= mtd_erase(mtd
, &erase_op
);
119 /* Abort if its not a bad block error */
123 printf("Skipping bad block at 0x%08llx\n", erase_op
.fail_addr
);
125 /* Skip bad block and continue behind it */
126 erase_op
.len
-= erase_op
.fail_addr
- erase_op
.addr
;
127 erase_op
.len
-= mtd
->erasesize
;
128 erase_op
.addr
= erase_op
.fail_addr
+ mtd
->erasesize
;
131 if (ret
&& ret
!= -EIO
)
138 static int do_nvram_parse(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
140 static int do_prepare(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
142 static int do_finish(cmd_tbl_t
* cmdtp
, int flag
, int argc
, char *const argv
[]);
144 static int do_prepare(cmd_tbl_t
* cmdtp
, int flag
, int argc
, char *const argv
[])
146 struct erase_info erase_op
= { };
157 if (!rei
.payload_blocks
) {
158 printf("parse first\n");
161 struct mtd_info
*mtd
= NULL
;
162 wblk
= rei
.burn_first_start
;
163 bp
= rei
.loader_payload
=
164 malloc(rei
.blocksizeK
* 1024 * rei
.loader_blocks
);
166 printf("loader payload malloc failed\n");
170 if (rei
.pure_payload_image
) {
175 m
= rei
.pure_payload_volume_index
;
176 s
= rei
.ubi
->volumes
[m
]->usable_leb_size
;
177 cp
= CONFIG_SYS_LOAD_ADDR
;
179 leb
* s
< 2048 + rei
.blocksizeK
* 1024 * rei
.loader_blocks
;
182 ubi_eba_read_leb(rei
.ubi
, rei
.ubi
->volumes
[m
], leb
,
183 cp
+ leb
* s
, 0, s
, 0);
185 memcpy(rei
.loader_payload
, cp
+ 2048,
186 rei
.blocksizeK
* 1024 * rei
.loader_blocks
);
187 printf("start of image device = 0x%x\n",
188 2048 + rei
.blocksizeK
* 1024 * rei
.loader_blocks
);
189 leb
= (2048 + rei
.blocksizeK
* 1024 * rei
.loader_blocks
) / s
;
190 offset
= (2048 + rei
.blocksizeK
* 1024 * rei
.loader_blocks
) % s
;
192 mtd
= get_mtd_device_nm("nand0");
193 if (IS_ERR_OR_NULL(mtd
)) {
194 printf("failed to get mtd\n");
197 erase(mtd
, rei
.erase_first_start
, rei
.erase_first_blocks
);
199 while (count
< rei
.payload_blocks
* rei
.blocksizeK
* 1024) {
200 cp
= CONFIG_SYS_LOAD_ADDR
;
201 while (((int)cp
< CONFIG_SYS_LOAD_ADDR
+ SZ_16M
)
203 rei
.payload_blocks
* rei
.blocksizeK
*
206 ubi_eba_read_leb(rei
.ubi
,
207 rei
.ubi
->volumes
[m
], leb
,
208 cp
, offset
, s
- offset
, 0);
211 // (" leb %d off 0x%x new 0x%x count %x --> %p\n",
212 // leb, offset, s - offset, count, cp);
213 count
= count
+ s
- offset
;
214 cp
= cp
+ s
- offset
;
218 // printf("final cp is %p next leb %d\n", cp, leb);
219 if ((int)cp
> CONFIG_SYS_LOAD_ADDR
+ SZ_16M
) {
222 (CONFIG_SYS_LOAD_ADDR
+ SZ_16M
));
225 // ("adjusted offset to 0x%x and next leb to %d\n",
228 mtd
= get_mtd_device_nm("nand0");
229 if (IS_ERR_OR_NULL(mtd
)) {
230 printf("failed to get mtd\n");
233 cp
= CONFIG_SYS_LOAD_ADDR
;
234 while (((int)cp
+ mtd
->erasesize
) <=
235 CONFIG_SYS_LOAD_ADDR
+ SZ_16M
) {
237 (rei
.burn_first_start
+
238 rei
.burn_first_blocks
)) {
240 (mtd
, wblk
* mtd
->erasesize
)) {
248 // (" 0x%x bytes at %p -> blk %d\n",
257 ("\nFIXME -- remainder not implemented\n");
265 mtd
= get_mtd_device_nm("nand0");
266 if (IS_ERR_OR_NULL(mtd
)) {
267 printf("failed to get mtd\n");
270 // FIXME -- loop on payload until we have enough data
271 // first --> loader (DDR)
272 // next --> burn_first (until exhausted)
273 // finally --> allocate remainder and copy to DDR
274 rblk
= rei
.payload_start
;
276 (rei
.loader_payload
+
277 mtd
->erasesize
* rei
.loader_blocks
)) {
278 i
= mtd_read(mtd
, rblk
* mtd
->erasesize
, mtd
->erasesize
,
281 mtd
->erasesize
* (rblk
-
283 printf("read loader -> mem %d bytes ret %d\n", sz
, i
);
287 printf("loader in memory buffer at 0x%x and size 0x%x\n",
288 rei
.loader_payload
, mtd
->erasesize
* rei
.loader_blocks
);
289 erase(mtd
, rei
.erase_first_start
, rei
.erase_first_blocks
);
290 // rblk = rei.payload_start + rei.loader_blocks;
291 block
= rei
.loader_blocks
;
292 while (block
< (rei
.loader_blocks
+ rei
.payload_blocks
)) {
293 i
= mtd_read(mtd
, rblk
* mtd
->erasesize
, mtd
->erasesize
,
294 &sz
, (char *)CONFIG_SYS_LOAD_ADDR
);
301 (rei
.burn_first_start
+
302 rei
.burn_first_blocks
)) {
305 wblk
* mtd
->erasesize
)) {
314 CONFIG_SYS_LOAD_ADDR
);
321 if (!rei
.remaining_payload
) {
322 rei
.remaining_payload
=
329 rei
.remaining_payload_len
= 0;
333 ("malloc for remaining failed\n");
337 memcpy(rei
.remaining_payload
+
339 remaining_payload_len
,
341 CONFIG_SYS_LOAD_ADDR
,
343 rei
.remaining_payload_len
+=
360 cp
+= sprintf(cp
, "ethaddr=%x:%x:%x:%x:%x:%x",
361 rei
.nvram
.ucaBaseMacAddr
[0],
362 rei
.nvram
.ucaBaseMacAddr
[1],
363 rei
.nvram
.ucaBaseMacAddr
[2],
364 rei
.nvram
.ucaBaseMacAddr
[3],
365 rei
.nvram
.ucaBaseMacAddr
[4], rei
.nvram
.ucaBaseMacAddr
[5]);
370 "bootcmd=printenv;run once;run check_flashback;printenv;sdk boot_img");
373 cp
+= sprintf(cp
, "tries=3");
378 "check_flashback=test $tries -eq 0 || echo $tries ; setexpr tries $tries - 1 ; saveenv ; test $tries -eq 0 && run do_flashback");
383 "do_flashback=echo here is where I would have run flashback");
386 cp
+= sprintf(cp
, "once=sdk metadata 1 1;setenv once true;saveenv");
390 more_env_size
= cp
- more_env
+ 1;
392 for (bp
= rei
.loader_payload
;
393 bp
< rei
.loader_payload
+ mtd
->erasesize
* rei
.loader_blocks
;
399 printf("env check at %x\r", bp
- rei
.loader_payload
);
400 if (tenv
[0] == BOOT_MAGIC_MAGIC
) {
401 printf("\nGOT IT\n");
402 ep
= (env_t
*) & tenv
[2];
403 memcpy(&crc
, &ep
->crc
, sizeof(crc
));
404 /* specifically use uboot's env crc function
405 * even though we have included the standard
407 new = the_env_crc32(0, ep
->data
, tenv
[1] - 4);
413 for (i
= 0; i
< tenv
[1] - 4; i
++) {
414 if ((ep
->data
[i
] == '\0')
415 && (ep
->data
[i
+ 1] == '\0')) {
416 memcpy(&ep
->data
[i
+ 1],
417 more_env
, more_env_size
);
421 new = the_env_crc32(0, ep
->data
, tenv
[1] - 4);
422 memcpy(&ep
->crc
, &new, sizeof(new));
431 static int do_finish(cmd_tbl_t
* cmdtp
, int flag
, int argc
, char *const argv
[])
434 unsigned long time_start
, time_mid
, time_end
;
441 if (!rei
.payload_blocks
) {
442 printf("parse first\n");
445 run_command("ubifsumount", 0);
446 run_command("ubi detach", 0);
447 struct mtd_info
*mtd
= NULL
;
449 mtd
= get_mtd_device_nm("nand0");
450 if (IS_ERR_OR_NULL(mtd
)) {
451 printf("failed to get mtd\n");
454 if (!rei
.loader_payload
) {
455 printf("loader payload isn't set\n");
458 time_start
= get_timer(0);
459 erase(mtd
, 0, rei
.loader_blocks
);
460 for (i
= 0; i
< rei
.loader_blocks
; i
++) {
461 offset
= i
* mtd
->erasesize
;
465 &rei
.loader_payload
[i
* mtd
->erasesize
]);
466 printf("w mem->ldr %d b ret %d\n", sz
, ret
);
468 erase(mtd
, rei
.burn_remaining_start
, rei
.burn_remaining_blocks
);
469 wblk
= rei
.burn_remaining_start
;
471 while (i
< rei
.remaining_payload_len
) {
472 printf("rp %x => %d\n", i
, wblk
);
474 wblk
* mtd
->erasesize
,
475 mtd
->erasesize
, &sz
, &rei
.remaining_payload
[i
]);
480 erase(mtd
, rei
.erase_last_start
, rei
.erase_last_blocks
);
482 time_mid
= get_timer(0);
483 sprintf(cmd
, "%s:%lld(loader),%lld@%lld(image)",
485 (long long)(rei
.loader_blocks
* (long long)mtd
->erasesize
),
486 (long long)(mtd
->size
-
487 (rei
.loader_blocks
+ 8) * mtd
->erasesize
),
488 (long long)(rei
.loader_blocks
* mtd
->erasesize
));
489 run_command("mtdparts delall", 0);
490 env_set("mtdparts", cmd
);
491 run_command("mtdparts", 0);
492 if (rei
.preserved_data_max_len
) {
493 run_command("ubi part image", 0);
495 sprintf(cmd
, "ubi create transition 0x%x dynamic 33",
496 rei
.preserved_data_max_len
);
498 sprintf(cmd
, "ubi write 0x%x transition 0x%x",
499 rei
.preserved_data
, rei
.preserved_data_max_len
);
503 time_end
= get_timer(0);
504 run_command("ubi detach", 0);
505 printf("start %ld\nsafe %ld\ndone %\ld\nHZ %d\n", time_start
,
506 time_mid
, time_end
, CONFIG_SYS_HZ
);
511 static void set_rei_ranges(int i
);
513 static void set_rei_ranges(int i
)
518 printf("ranges for image %d\n", i
);
519 rei
.erase_first_start
= nv
->ulNandPartOfsKb
[3 - i
] / rei
.blocksizeK
;
520 rei
.erase_first_blocks
= nv
->ulNandPartSizeKb
[3 - i
] / rei
.blocksizeK
;
521 if (rei
.erase_first_start
< rei
.loader_blocks
) {
522 rei
.burn_first_start
= rei
.loader_blocks
;
523 rei
.burn_first_blocks
=
524 rei
.erase_first_blocks
-
525 (rei
.loader_blocks
- rei
.erase_first_start
);
527 rei
.burn_first_start
= rei
.erase_first_start
;
528 rei
.burn_first_blocks
= rei
.erase_first_blocks
;
530 if (cp
= env_get("burn_first_blocks")) {
531 rei
.burn_first_blocks
= simple_strtoul(cp
, NULL
, 0);
533 printf("rei.erase_first_start=%d\n", rei
.erase_first_start
);
534 printf("rei.erase_first_blocks=%d\n", rei
.erase_first_blocks
);
535 printf("rei.burn_first_start=%d\n", rei
.burn_first_start
);
536 printf("rei.burn_first_blocks=%d\n", rei
.burn_first_blocks
);
537 rei
.burn_remaining_start
= nv
->ulNandPartOfsKb
[i
] / rei
.blocksizeK
;
538 rei
.burn_remaining_blocks
= nv
->ulNandPartSizeKb
[i
] / rei
.blocksizeK
;
539 if (rei
.burn_remaining_start
< rei
.loader_blocks
) {
540 rei
.burn_remaining_start
= rei
.loader_blocks
;
541 rei
.burn_remaining_blocks
=
542 rei
.burn_remaining_blocks
-
543 (rei
.loader_blocks
- rei
.burn_remaining_start
);
547 static int do_nvram_parse(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
550 // int *haystack = (int *)0x1000000;
558 int payload_loader_size
= 0;
559 int payload_size
= 0;
564 struct mtd_info
*mtd
;
568 memcpy(&needle
, NVRAM_MAGIC
, 8);
570 mtd
= get_mtd_device_nm("nand0");
571 if (IS_ERR_OR_NULL(mtd
)) {
572 printf("failed to get mtd\n");
575 i
= mtd_read(mtd
, 0, 2 << 20, &sz
, (u_char
*) CONFIG_SYS_LOAD_ADDR
);
577 if (!check_nv_crc(nv
)) {
579 for (ip
= (long int *)CONFIG_SYS_LOAD_ADDR
;
580 ip
< (long int *)(CONFIG_SYS_LOAD_ADDR
+ SZ_2M
);
581 ip
= ip
+ (2048 / sizeof(long int))) {
583 printf("got it %p\n", ip
);
585 if (check_nv_crc(nv
)) {
586 printf("nvram CRC OK\n");
588 printf("nvram CRC failed\n");
597 memcpy(&rei
.nvram
, nv
, sizeof(rei
.nvram
));
598 printf("version %d\n", nv
->version
);
600 strncpy(tmp
, nv
->boardid
, 16);
601 printf("boardid %s\n", tmp
);
602 printf("bootline %s\n", nv
->bootline
);
603 printf("afeids %x,%x\n", nv
->afeId
[0], nv
->afeId
[1]);
604 printf("MCB %x\n", nv
->ulMemoryConfig
);
605 for (i
= 0; i
< NP_TOTAL
; i
++) {
606 printf("part %d offset %dK size %dK\n", i
,
607 nv
->ulNandPartOfsKb
[i
], nv
->ulNandPartSizeKb
[i
]);
610 strncpy(tmp
, nv
->szVoiceBoardId
, 16);
611 printf("voiceboardid %s\n", tmp
);
613 blocksize
= mtd
->erasesize
;
614 rei
.blocksizeK
= mtd
->erasesize
>> 10;
616 env_set("mtdids", "nand0=brcmnand.0");
617 sprintf(tmp
, "%s:%dK@%dK(nvram)ro,%dK@%dK(image1)ro,%dK@%dK(image2)ro,",
619 nv
->ulNandPartSizeKb
[0], nv
->ulNandPartOfsKb
[0],
620 nv
->ulNandPartSizeKb
[1], nv
->ulNandPartOfsKb
[1],
621 nv
->ulNandPartSizeKb
[2], nv
->ulNandPartOfsKb
[2]
623 k
= nv
->ulNandPartSizeKb
[2] + nv
->ulNandPartOfsKb
[2];
624 for (i
= 0; i
< 3; i
++) {
625 j
= nv
->part_info
[i
].size
;
626 j
= (j
& 0xc000 == 0xc000) ? 0 : j
;
627 printf("misc%d size is %d\n", i
+ 1, j
);
629 sprintf(tmp
+ strlen(tmp
), "%dK@%dK(misc%d),",
634 sprintf(tmp
+ strlen(tmp
), "%dK@%dK(data)",
635 nv
->ulNandPartSizeKb
[3], nv
->ulNandPartOfsKb
[3]
637 printf("setting mtdparts to %s\n", tmp
);
638 env_set("mtdparts", tmp
);
639 run_command("mtdparts", 0);
640 sprintf(tmp
, "0x%x", nv
->ulNandPartSizeKb
[0] * 1024);
641 env_set("nvram_size", tmp
);
642 run_command("nand info", 0);
643 printf("erase block %d\n", blocksize
);
644 strcpy(split
, MASQ_SPLIT_A
);
645 strcat(split
, MASQ_SPLIT_B
);
647 for (i
= 1; i
< 3; i
++) {
648 sprintf(tmp
, "image%d", i
);
649 mtd
= get_mtd_device_nm(tmp
);
650 if (IS_ERR_OR_NULL(mtd
)) {
651 printf("failed to get mtd\n");
654 for (j
= 0; j
< 20; j
++) {
655 // printf("read i=%d j=%d\n",i,j);
656 ret
= mtd_read(mtd
, j
* blocksize
, 2048, &sz
, tmp
);
657 // printf("ret %d read %d\n",ret,sz);
658 if (0 == strncmp(split
, tmp
, strlen(split
) + 1)) {
659 printf("found image%d block %d\n", i
, j
);
660 cp
= &tmp
[strlen(split
) + 1];
661 payload_loader_size
=
662 simple_strtoul(cp
, NULL
, 0);
663 cp
= cp
+ strlen(cp
) + 1;
664 payload_size
= simple_strtoul(cp
, NULL
, 0);
665 printf("loader size %d payload size %d\n",
666 payload_loader_size
, payload_size
);
668 payload_loader_size
/ blocksize
;
669 rei
.payload_blocks
= payload_size
/ blocksize
;
670 rei
.split_image_start
=
671 (nv
->ulNandPartOfsKb
[i
] / rei
.blocksizeK
);
672 rei
.split_image_end
=
673 (nv
->ulNandPartOfsKb
[i
] +
674 nv
->ulNandPartSizeKb
[i
]) / rei
.blocksizeK
-
677 (nv
->ulNandPartOfsKb
[i
] / rei
.blocksizeK
) +
687 /* the following will probably be removed ... reimage will always be packaged as a split image */
688 /* if we do keep it, after attaching, it needs to check for volumes other than the rootfs */
689 /* or the number of volumes */
690 if ((0 == 1) && (i
< 3)) {
695 /* didn't find marker yet */
696 err
= ubi_dev_scan(mtd
, NULL
);
698 printf("UBI init error %d\n", err
);
700 ("Please check, if the correct MTD partition is used (size big enough?)\n");
703 rei
.ubi
= ubi_devices
[0];
705 sprintf(tmp
, "image%d", i
);
707 printf("part %s attaches as ubi\n", tmp
);
708 for (m
= 0; m
< (rei
.ubi
->vtbl_slots
+ 1); m
++) {
709 if (!rei
.ubi
->volumes
[m
])
710 continue; /* Empty record */
712 rei
.ubi
->volumes
[m
]->name
);
715 rei
.ubi
->volumes
[m
]->name
)) {
716 /* found payload volume */
717 rei
.pure_payload_image
= i
;
718 rei
.pure_payload_volume_index
=
725 if (rei
.pure_payload_image
) {
727 m
= rei
.pure_payload_volume_index
;
728 s
= rei
.ubi
->volumes
[m
]->usable_leb_size
;
730 ubi_eba_read_leb(rei
.ubi
, rei
.ubi
->volumes
[m
],
731 0, CONFIG_SYS_LOAD_ADDR
, 0, s
, 0);
732 cp
= CONFIG_SYS_LOAD_ADDR
;
733 t
= simple_strtoul(cp
, &cp
, 0);
734 rei
.loader_blocks
= t
/ blocksize
;
735 printf("loader size %d is %d blocks\n", t
, blocksize
);
737 t
= simple_strtoul(cp
, &cp
, 0);
738 rei
.payload_blocks
= t
/ blocksize
;
739 printf("payload size %d is %d blocks\n", t
, blocksize
);
740 set_rei_ranges(rei
.pure_payload_image
);
747 rei
.erase_last_start
=
748 (nv
->ulNandPartOfsKb
[2] + nv
->ulNandPartSizeKb
[2]) / rei
.blocksizeK
;
749 rei
.erase_last_blocks
=
750 ((nv
->ulNandPartOfsKb
[3] +
751 nv
->ulNandPartSizeKb
[3]) / rei
.blocksizeK
) - rei
.erase_last_start
;
755 static int do_preserve_allocate(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
758 static int do_preserve_save(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
760 static int do_preserve_allocate(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
765 len
= simple_strtoul(argv
[1], NULL
, 0);
768 printf("malloc failed\n");
772 rei
.preserved_data
= cp
;
773 rei
.preserved_data_len
= 0;
774 rei
.preserved_data_max_len
= len
;
775 printf("allocated 0x%x bytes at %x\n", len
, cp
);
779 static int do_preserve_save(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
785 printf("filename required\n");
788 if (cp
= env_get("filesize")) {
789 len
= simple_strtoul(cp
, NULL
, 16);
791 printf("filesize in env is not set\n");
794 if (rei
.preserved_data_len
+ strlen(argv
[1]) + 16 + len
>
795 rei
.preserved_data_max_len
) {
796 printf("allocated space exhausted\n");
799 rei
.preserved_data_len
+=
800 sprintf(rei
.preserved_data
+ rei
.preserved_data_len
, "%s\n%d\n",
802 memcpy(rei
.preserved_data
+ rei
.preserved_data_len
,
803 CONFIG_SYS_LOAD_ADDR
, len
);
804 rei
.preserved_data_len
+= len
;
805 *((char *)(rei
.preserved_data
+ rei
.preserved_data_len
)) = '\n';
806 printf("preserved %d bytes as %s\n", len
, argv
[1]);
810 static int do_commit(cmd_tbl_t
* cmdtp
, int flag
, int argc
, char *const argv
[]);
811 static int do_commit(cmd_tbl_t
* cmdtp
, int flag
, int argc
, char *const argv
[])
813 struct mtd_info
*mtd
= NULL
;
819 if (!rei
.loader_payload
) {
820 printf("prepare revertable first\n");
824 mtd
= get_mtd_device_nm("nand0");
825 erase(mtd
, rei
.erase_first_start
, rei
.erase_first_blocks
);
826 erase(mtd
, rei
.erase_last_start
, rei
.erase_last_blocks
);
827 erase(mtd
, 0, rei
.loader_blocks
);
829 for (i
= 0; i
< rei
.loader_blocks
; i
++) {
830 if (mtd_block_isbad(mtd
, (uint64_t) i
* mtd
->erasesize
)) {
831 printf("skip bad block %d\n", i
);
833 offset
= i
* mtd
->erasesize
;
837 &rei
.loader_payload
[rblk
* mtd
->erasesize
]);
838 printf("w mem->ldr %d b ret %d\n", sz
, ret
);
848 static int do_revertable(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
850 static int do_revertable(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
853 struct mtd_info
*mtd
= NULL
;
861 if (!rei
.payload_blocks
) {
862 printf("parse first\n");
866 mtd
= get_mtd_device_nm("nand0");
867 if (IS_ERR_OR_NULL(mtd
)) {
868 printf("failed to get mtd\n");
871 erase(mtd
, rei
.split_image_start
,
872 rei
.payload_start
- rei
.split_image_start
);
873 // read loader to ddr
874 bp
= rei
.loader_payload
=
875 malloc(rei
.blocksizeK
* 1024 * rei
.loader_blocks
);
877 printf("loader payload malloc failed\n");
880 rblk
= rei
.payload_start
;
881 while (bp
< (rei
.loader_payload
+ mtd
->erasesize
* rei
.loader_blocks
)) {
882 i
= mtd_read(mtd
, rblk
* mtd
->erasesize
, mtd
->erasesize
,
885 mtd
->erasesize
* (rblk
- rei
.payload_start
));
886 printf("read loader -> mem %d bytes ret %d\n", (int)sz
, i
);
890 // erase start of reimage image to end of loader
891 erase(mtd
, rei
.payload_start
, rei
.loader_blocks
);
893 // update loader in ddr (env)
894 reimage_env_append(&rei
);
899 static int do_read_recovery(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
901 static int do_read_recovery(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
904 struct mtd_info
*mtd
= NULL
;
912 int i
, j
, n
, z
, ret
= 0;
916 struct mtd_oob_ops oob_ops
;
918 mtd
= get_mtd_device_nm("nand0");
919 blocks
= (mtd
->size
/ mtd
->erasesize
);
920 pages
= (mtd
->erasesize
/ mtd
->writesize
);
921 rei
.recovery_chunks_list
= CONFIG_SYS_LOAD_ADDR
;
922 rei
.recovery_data_buf
=
923 CONFIG_SYS_LOAD_ADDR
+ (blocks
* pages
+
924 1) * sizeof(struct recovery_chunks
);
925 rei
.recovery_data_len
= 0;
926 if (!rei
.recovery_chunks_list
) {
927 printf("recovery chunks malloc failed\n");
930 printf("Flash device is %d blocks of %d pages of %d bytes\n", blocks
,
931 pages
, mtd
->writesize
);
932 while (block
< blocks
) {
933 if ((block
>= rei
.split_image_start
)
934 && (block
<= rei
.split_image_end
)) {
935 // printf("block %d is part of reimage\n", block);
940 (uint64_t) page
*mtd
->writesize
+
941 (uint64_t) block
*mtd
->erasesize
;
944 (mtd
, (uint64_t) block
* mtd
->erasesize
)) {
945 /* check for bad block */
946 printf("block %d is bad\n", block
);
952 /* read to buffer ... may not keep it */
953 bp
= rei
.recovery_data_buf
+ rei
.recovery_data_len
;
954 oob_ops
.mode
= MTD_OPS_PLACE_OOB
;
955 oob_ops
.len
= mtd
->writesize
;
957 oob_ops
.ooblen
= mtd
->oobsize
;
958 oob_ops
.oobretlen
= 0;
961 oob_ops
.oobbuf
= spare
;
962 i
= mtd_read_oob(mtd
, off
, &oob_ops
);
968 printf("%d/%d return %d sz %d\n", block
, page
, i
, sz
);
971 //printf("%d/%d ", block, page, i, sz);
973 // printf("%d/%d r %d sz %d", block, page, i, sz);
975 while ((n
< 2) && (j
< sz
)) {
977 n
= n
+ 32 - generic_hweight32(*up32
);
979 /* check if not blank ... otherwise read oob too */
982 // printf(" zeros %d", n);
986 /* check for zeros in oob */
987 for (j
= 0; j
< oob_ops
.oobretlen
>> 2; j
++) {
988 z
= z
+ 32 - generic_hweight32(spare
[j
]);
991 // printf(" spare zeros %d\n", z);
998 /* deal with this page */
1000 if ((i
== 0) && (n
!= 0)) {
1002 rei
.recovery_chunks_list
[chunk
].flashpage
=
1003 block
* pages
+ page
;
1004 rei
.recovery_chunks_list
[chunk
].size
= mtd
->writesize
;
1005 rei
.recovery_chunks_list
[chunk
].type
= 0x00;
1007 rei
.recovery_data_len
+= mtd
->writesize
;
1009 page
= (page
+ 1) % pages
;
1014 rei
.recovery_chunks_list
[chunk
].type
= 0x7fffffff;
1015 printf("chunks %d len 0x%x\n", chunk
, rei
.recovery_data_len
);
1016 // load old blocks (everything but reimage image) to ddr
1017 put_mtd_device(mtd
);
1021 // erase everything except the reimage payload (after loader)
1024 // store preserved files
1027 static int do_flashback(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
1028 char *const argv
[]);
1029 static int do_flashback(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
1032 struct mtd_info
*mtd
= NULL
;
1040 if (rei
.recovery_data_len
== 0) {
1041 printf("read recovery chunks first\n");
1044 mtd
= get_mtd_device_nm("nand0");
1045 blocks
= (mtd
->size
/ mtd
->erasesize
);
1046 pages
= (mtd
->erasesize
/ mtd
->writesize
);
1047 erase(mtd
, 0, blocks
);
1049 bp
= rei
.recovery_data_buf
;
1050 while (rei
.recovery_chunks_list
[chunk
].type
< 0x1000) {
1052 rei
.recovery_chunks_list
[chunk
].flashpage
*
1053 mtd
->writesize
, mtd
->writesize
, &sz
, bp
);
1054 bp
+= rei
.recovery_chunks_list
[chunk
].size
;
1056 printf("%d ", chunk
);
1058 put_mtd_device(mtd
);
1061 static int do_store_preserved(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
1062 char *const argv
[]);
1063 static int do_store_preserved(cmd_tbl_t
* cmdtp
, int flag
, int argc
,
1067 struct mtd_info
*mtd
= NULL
;
1068 mtd
= get_mtd_device_nm("nand0");
1069 if (IS_ERR_OR_NULL(mtd
)) {
1070 printf("failed to get mtd\n");
1073 sprintf(cmd
, "%s:%lld(loader),%lld@%lld(image)",
1075 (long long)(rei
.loader_blocks
* (long long)mtd
->erasesize
),
1076 (long long)(mtd
->size
-
1077 (rei
.loader_blocks
+ 8) * mtd
->erasesize
),
1078 (long long)(rei
.loader_blocks
* mtd
->erasesize
));
1079 run_command("mtdparts delall", 0);
1080 env_set("mtdparts", cmd
);
1081 run_command("mtdparts", 0);
1082 run_command("ubi part image", 0);
1083 if (rei
.preserved_data_max_len
) {
1084 sprintf(cmd
, "ubi create transition 0x%x dynamic 33",
1085 rei
.preserved_data_max_len
);
1086 run_command(cmd
, 0);
1087 sprintf(cmd
, "ubi write 0x%x transition 0x%x",
1088 rei
.preserved_data
, rei
.preserved_data_max_len
);
1089 run_command(cmd
, 0);
1091 if (rei
.recovery_data_len
) {
1092 sprintf(cmd
, "ubi create recovery 0x%x dynamic 34",
1093 rei
.recovery_data_len
+ (void *)rei
.recovery_data_buf
-
1094 (void *)rei
.recovery_chunks_list
);
1095 run_command(cmd
, 0);
1096 sprintf(cmd
, "ubi write 0x%x recovery 0x%x",
1097 rei
.recovery_chunks_list
,
1098 rei
.recovery_data_len
+ (void *)rei
.recovery_data_buf
-
1099 (void *)rei
.recovery_chunks_list
);
1100 run_command(cmd
, 0);
1104 void reimage_splice_env(struct reimager
*r
, char *more_env
, int more_env_size
)
1108 for (bp
= r
->loader_payload
;
1110 r
->loader_payload
+ r
->blocksizeK
* 1024 * r
->loader_blocks
;
1116 printf("env check at %x\r", bp
- r
->loader_payload
);
1117 if (tenv
[0] == BOOT_MAGIC_MAGIC
) {
1118 printf("\nGOT IT\n");
1119 ep
= (env_t
*) & tenv
[2];
1120 memcpy(&crc
, &ep
->crc
, sizeof(crc
));
1121 /* specifically use uboot's env crc function
1122 * even though we have included the standard
1124 new = the_env_crc32(0, ep
->data
, tenv
[1] - 4);
1130 for (i
= 0; i
< tenv
[1] - 4; i
++) {
1131 if ((ep
->data
[i
] == '\0')
1132 && (ep
->data
[i
+ 1] == '\0')) {
1133 memcpy(&ep
->data
[i
+ 1],
1134 more_env
, more_env_size
);
1138 new = the_env_crc32(0, ep
->data
, tenv
[1] - 4);
1139 memcpy(&ep
->crc
, &new, sizeof(new));
1145 static char usage
[] = "line 1...\n" "line 2...\n";
1147 U_BOOT_CMD_WITH_SUBCMDS(safeimage
, "safe reimage commands", usage
,
1148 U_BOOT_SUBCMD_MKENT(commit
, 5, 0, do_commit
),
1149 U_BOOT_SUBCMD_MKENT(flashback
, 5, 0, do_flashback
),
1150 U_BOOT_SUBCMD_MKENT(read_recovery
, 5, 0,
1152 U_BOOT_SUBCMD_MKENT(revertable
, 5, 0, do_revertable
),
1153 U_BOOT_SUBCMD_MKENT(nvram
, 1, 0, do_nvram_parse
),
1154 U_BOOT_SUBCMD_MKENT(store_preserved
, 1, 0,
1155 do_store_preserved
));
1157 U_BOOT_CMD_WITH_SUBCMDS(reimage
, "reimage commands", usage
,
1158 U_BOOT_SUBCMD_MKENT(auto, 1, 0, do_reimage_auto
),
1159 U_BOOT_SUBCMD_MKENT(finish
, 5, 0, do_finish
),
1160 U_BOOT_SUBCMD_MKENT(prepare
, 5, 0, do_prepare
),
1161 U_BOOT_SUBCMD_MKENT(nvram
, 1, 0, do_nvram_parse
));
1163 U_BOOT_CMD_WITH_SUBCMDS(preserve
, "preserve data commands", usage
,
1164 U_BOOT_SUBCMD_MKENT(allocate
, 5, 0,
1165 do_preserve_allocate
),
1166 U_BOOT_SUBCMD_MKENT(save
, 5, 0, do_preserve_save
));