From 4a4830cf915e76f07cff5ce346c3ccbc987c1557 Mon Sep 17 00:00:00 2001 From: John Chau Date: Thu, 2 Jul 2020 12:01:21 +0800 Subject: cmd: add clone command This patch adds a feature for block device cloning similar to dd command, this should be useful for boot-strapping a device where usb gadget or networking is not available. For instance one can clone a factory image into a blank emmc from an external sd card. Signed-off-by: John Chau --- cmd/Kconfig | 8 ++++ cmd/Makefile | 1 + cmd/clone.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 cmd/clone.c (limited to 'cmd') diff --git a/cmd/Kconfig b/cmd/Kconfig index d7136b0e790..e11176451b1 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1148,6 +1148,14 @@ config CMD_MMC_SWRITE endif +config CMD_CLONE + bool "clone" + depends on BLK + help + Enable storage cloning over block devices, useful for + initial flashing by external block device without network + or usb support. + config CMD_MTD bool "mtd" depends on MTD diff --git a/cmd/Makefile b/cmd/Makefile index 6e0086ba07f..70750375d12 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -98,6 +98,7 @@ obj-$(CONFIG_CMD_MMC) += mmc.o obj-$(CONFIG_MP) += mp.o obj-$(CONFIG_CMD_MTD) += mtd.o obj-$(CONFIG_CMD_MTDPARTS) += mtdparts.o +obj-$(CONFIG_CMD_CLONE) += clone.o ifneq ($(CONFIG_CMD_NAND)$(CONFIG_CMD_SF),) obj-y += legacy-mtd-utils.o endif diff --git a/cmd/clone.c b/cmd/clone.c new file mode 100644 index 00000000000..97747f8f080 --- /dev/null +++ b/cmd/clone.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 John Chau + * + */ + +#include +#include +#include +#include +#include +#include + +#define BUFSIZE (1 * 1024 * 1024) +static int do_clone(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) +{ + int srcdev, destdev; + struct blk_desc *srcdesc, *destdesc; + int srcbz, destbz, ret; + char *unit, *buf; + unsigned long wrcnt, rdcnt, requested, srcblk, destblk; + unsigned long timer; + const unsigned long buffersize = 1024 * 1024; + + if (argc < 6) + return CMD_RET_USAGE; + + srcdev = blk_get_device_by_str(argv[1], argv[2], &srcdesc); + destdev = blk_get_device_by_str(argv[3], argv[4], &destdesc); + if (srcdev < 0) { + printf("Unable to open source device\n"); + return 1; + } else if (destdev < 0) { + printf("Unable to open destination device\n"); + return 1; + } + requested = simple_strtoul(argv[5], &unit, 10); + srcbz = srcdesc->blksz; + destbz = destdesc->blksz; + + if ((srcbz * (buffersize / srcbz) != buffersize) && + (destbz * (buffersize / destbz) != buffersize)) { + printf("failed: cannot match device block sizes\n"); + return 1; + } + if (requested == 0) { + unsigned long a = srcdesc->lba * srcdesc->blksz; + unsigned long b = destdesc->lba * destdesc->blksz; + + if (a > b) + requested = a; + else + requested = b; + } else { + switch (unit[0]) { + case 'g': + case 'G': + requested *= 1024; + case 'm': + case 'M': + requested *= 1024; + case 'k': + case 'K': + requested *= 1024; + break; + } + } + printf("Copying %ld bytes from %s:%s to %s:%s\n", + requested, argv[1], argv[2], argv[3], argv[4]); + wrcnt = 0; + rdcnt = 0; + buf = (char *)malloc(BUFSIZE); + srcblk = 0; + destblk = 0; + timer = get_timer(0); + while (wrcnt < requested) { + unsigned long toread = BUFSIZE / srcbz; + unsigned long towrite = BUFSIZE / destbz; + unsigned long offset = 0; + +read: + ret = blk_dread(srcdesc, srcblk, toread, buf + offset); + if (ret < 0) { + printf("Src read error @blk %ld\n", srcblk); + goto exit; + } + rdcnt += ret * srcbz; + srcblk += ret; + if (ret < toread) { + toread -= ret; + offset += ret * srcbz; + goto read; + } + offset = 0; +write: + ret = blk_dwrite(destdesc, destblk, towrite, buf + offset); + if (ret < 0) { + printf("Dest write error @blk %ld\n", srcblk); + goto exit; + } + wrcnt += ret * destbz; + destblk += ret; + if (ret < towrite) { + towrite -= ret; + offset += ret * destbz; + goto write; + } + } + +exit: + timer = get_timer(timer); + timer = 1000 * timer / CONFIG_SYS_HZ; + printf("%ld read\n", rdcnt); + printf("%ld written\n", wrcnt); + printf("%ldms, %ldkB/s\n", timer, wrcnt / timer); + free(buf); + + return 0; +} + +U_BOOT_CMD( + clone, 6, 1, do_clone, + "simple storage cloning", + " \n" + "clone storage from 'src dev' on 'src interface' to 'dest dev' on 'dest interface' with maximum 'size' bytes (or 0 for clone to end)" +); -- cgit v1.2.3 From 9996cea75f5a77db5a6055342130d27a36830ef8 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 20 Jul 2020 11:10:45 +0300 Subject: lmb/bdinfo: dump lmb info via bdinfo Dump lmb status from the bdinfo command. This is useful for seeing the reserved memory regions from the u-boot cmdline. Signed-off-by: Tero Kristo --- cmd/bdinfo.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'cmd') diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index 8b2c105e777..2a6dd6c67a5 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +97,12 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) #if CONFIG_IS_ENABLED(MULTI_DTB_FIT) bdinfo_print_num("multi_dtb_fit", (ulong)gd->multi_dtb_fit); #endif + if (gd->fdt_blob) { + struct lmb lmb; + + lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob); + lmb_dump_all_force(&lmb); + } arch_print_bdinfo(); -- cgit v1.2.3 From f2d58f3bdad30ac088f76cce38a2e64a6c640f19 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Tue, 28 Jul 2020 17:57:48 +0300 Subject: cmd: bootz: fix device-tree overlap test The address of the kernel image is stored in images->ep. zi_start is the offset of execution entry in the image, which is usually 0 for ARM zImage. Fixes boot error when ftd is stored near RAM address 0x0: ERROR: FDT image overlaps OS image (OS=0x0..0x5fd608) Fixes: fbde7589ce30 ("common: bootm: add checks to verify if ramdisk / fdtimage overlaps OS image") Cc: Tero Kristo Signed-off-by: Baruch Siach --- cmd/bootz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/bootz.c b/cmd/bootz.c index 1c8b0cf89f9..7556cd2752a 100644 --- a/cmd/bootz.c +++ b/cmd/bootz.c @@ -54,7 +54,7 @@ static int bootz_start(struct cmd_tbl *cmdtp, int flag, int argc, * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not * have a header that provide this informaiton. */ - if (bootm_find_images(flag, argc, argv, zi_start, zi_end - zi_start)) + if (bootm_find_images(flag, argc, argv, images->ep, zi_end - zi_start)) return 1; return 0; -- cgit v1.2.3 From 5ce2776ae63326807bc504fcfed24997c2a03bb2 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 28 Jul 2020 17:56:33 +0200 Subject: cmd: bdinfo: cleanup phys_addr_t output We currently print the memory size with at least 8 hexadecimal digits. This creates a ragged output on 64 bit boards, e.g. on a Kendryte K210: DRAM bank = 0x0000000000000002 -> start = 0x0000000080600000 -> size = 0x0000000000200000 memstart = 0x0000000000000000 memsize = 0x00000000 flashstart = 0x0000000000000000 flashsize = 0x0000000000000000 flashoffset = 0x0000000000000000 All other numbers are printed with the number of digits needed for the type ulong. So use this value as minimum number of digits (precision) for printing physical addresses. Signed-off-by: Heinrich Schuchardt Reviewed-by: Heiko Schocher Reviewed-by: Stefan Roese Reviewed-by: Simon Glass --- cmd/bdinfo.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'cmd') diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index 2a6dd6c67a5..9485c404740 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -34,9 +34,10 @@ static void print_eth(int idx) printf("%-12s= %s\n", name, val); } -static void print_lnum(const char *name, unsigned long long value) +static void print_phys_addr(const char *name, phys_addr_t value) { - printf("%-12s= 0x%.8llX\n", name, value); + printf("%-12s= 0x%.*llx\n", name, 2 * (int)sizeof(ulong), + (unsigned long long)value); } void bdinfo_print_mhz(const char *name, unsigned long hz) @@ -75,7 +76,7 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) bdinfo_print_num("boot_params", (ulong)bd->bi_boot_params); print_bi_dram(bd); bdinfo_print_num("memstart", (ulong)bd->bi_memstart); - print_lnum("memsize", (u64)bd->bi_memsize); + print_phys_addr("memsize", bd->bi_memsize); bdinfo_print_num("flashstart", (ulong)bd->bi_flashstart); bdinfo_print_num("flashsize", (ulong)bd->bi_flashsize); bdinfo_print_num("flashoffset", (ulong)bd->bi_flashoffset); -- cgit v1.2.3