From be683756f620349966e0ebb4a5e02e5ff03c8a8e Mon Sep 17 00:00:00 2001 From: Ruslan Trofymenko Date: Fri, 14 Jun 2019 17:01:26 +0300 Subject: cmd: part: Add 'number' sub-command This sub-command serves for getting the partition index from partition name. Also it can be used to test the existence of specified partition. Use case: For example, in most CI environments this U-Boot command for automatic testing of Linux rootfs is used: => setenv bootpart 1:f where 0xf is "userdata" partition. But the number of "userdata" partition can be changed any time, when partition table is changed. So it would be nice to get rid of that 0xf magic number and use partition name instead, like this: => part number mmc 1 userdata part_num => setenv bootpart 1:${part_num} Signed-off-by: Ruslan Trofymenko Signed-off-by: Igor Opaniuk Reviewed-by: Alistair Strachan Reviewed-by: Sam Protsenko Reviewed-by: Simon Glass Reviewed-by: Sam Protsenko --- cmd/part.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/part.c b/cmd/part.c index bfb6488b0f..653e13ced1 100644 --- a/cmd/part.c +++ b/cmd/part.c @@ -24,6 +24,7 @@ enum cmd_part_info { CMD_PART_INFO_START = 0, CMD_PART_INFO_SIZE, + CMD_PART_INFO_NUMBER }; static int do_part_uuid(int argc, char * const argv[]) @@ -149,6 +150,9 @@ static int do_part_info(int argc, char * const argv[], enum cmd_part_info param) case CMD_PART_INFO_SIZE: snprintf(buf, sizeof(buf), LBAF, info.size); break; + case CMD_PART_INFO_NUMBER: + snprintf(buf, sizeof(buf), "%d", part); + break; default: printf("** Unknown cmd_part_info value: %d\n", param); return 1; @@ -172,6 +176,11 @@ static int do_part_size(int argc, char * const argv[]) return do_part_info(argc, argv, CMD_PART_INFO_SIZE); } +static int do_part_number(int argc, char * const argv[]) +{ + return do_part_info(argc, argv, CMD_PART_INFO_NUMBER); +} + static int do_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { if (argc < 2) @@ -185,6 +194,8 @@ static int do_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return do_part_start(argc - 2, argv + 2); else if (!strcmp(argv[1], "size")) return do_part_size(argc - 2, argv + 2); + else if (!strcmp(argv[1], "number")) + return do_part_number(argc - 2, argv + 2); return CMD_RET_USAGE; } @@ -206,5 +217,8 @@ U_BOOT_CMD( " part can be either partition number or partition name\n" "part size \n" " - set environment variable to the size of the partition (in blocks)\n" - " part can be either partition number or partition name" + " part can be either partition number or partition name\n" + "part number \n" + " - set environment variable to the partition number using the partition name\n" + " part must be specified as partition name" ); -- cgit v1.2.3 From cef4de88359ddc37954046a758c0152dda53069b Mon Sep 17 00:00:00 2001 From: Eugeniu Rosca Date: Fri, 19 Jul 2019 23:26:11 +0200 Subject: treewide: Fix stale references of Android docs Commit 9bdf0e8fef86 ("doc: relocate/rename Android README and add BCB overview") left some obsolete references of Android documents/paths. This has been pointed out by Sam (thanks!) in: https://patchwork.ozlabs.org/patch/1104245/#2208134 Fixes: 9bdf0e8fef86 ("doc: relocate/rename Android README and add BCB overview") Reported-by: Sam Protsenko Suggested-by: Sam Protsenko Signed-off-by: Eugeniu Rosca Reviewed-by: Igor Opaniuk Reviewed-by: Sam Protsenko --- cmd/Kconfig | 2 +- test/py/tests/test_avb.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'cmd') diff --git a/cmd/Kconfig b/cmd/Kconfig index 175c6ad9e3..e1e050f4ad 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -735,7 +735,7 @@ config CMD_FASTBOOT Android devices. Fastboot requires either the network stack enabled or support for acting as a USB device. - See doc/README.android-fastboot for more information. + See doc/android/fastboot.txt for more information. config CMD_FDC bool "fdcboot - Boot from floppy device" diff --git a/test/py/tests/test_avb.py b/test/py/tests/test_avb.py index 2bb75ed6e2..8132423435 100644 --- a/test/py/tests/test_avb.py +++ b/test/py/tests/test_avb.py @@ -8,7 +8,7 @@ This tests Android Verified Boot 2.0 support in U-boot: For additional details about how to build proper vbmeta partition -check doc/README.avb2 +check doc/android/avb2.txt For configuration verification: - Corrupt boot partition and check for failure -- cgit v1.2.3 From e47b73b821f7f6078c0d11b453545507e25727cc Mon Sep 17 00:00:00 2001 From: Eugeniu Rosca Date: Fri, 19 Jul 2019 23:26:12 +0200 Subject: cmd: bcb: Fix duplicated handling in two case-branches Fix warning V1037 reported by PVS-Studio Static Analyzer: Two or more case-branches perform the same actions. Check lines: 49, 53 Fixes: db7b7a05b267 ("cmd: Add 'bcb' command to read/modify/write BCB fields") Signed-off-by: Eugeniu Rosca Reviewed-by: Igor Opaniuk Reviewed-by: Sam Protsenko --- cmd/bcb.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'cmd') diff --git a/cmd/bcb.c b/cmd/bcb.c index 2bd5a744de..3b1c7434e2 100644 --- a/cmd/bcb.c +++ b/cmd/bcb.c @@ -46,9 +46,6 @@ static int bcb_is_misused(int argc, char *const argv[]) switch (cmd) { case BCB_CMD_LOAD: - if (argc != 3) - goto err; - break; case BCB_CMD_FIELD_SET: if (argc != 3) goto err; -- cgit v1.2.3 From 739168cfdc18690273e24a34f0360a61e6658424 Mon Sep 17 00:00:00 2001 From: Eugeniu Rosca Date: Fri, 19 Jul 2019 23:26:13 +0200 Subject: cmd: bcb: Use strcmp() instead of strncmp() for string literals Quote from https://patchwork.ozlabs.org/patch/1104244/#2210814: ----------8<----------- strncmp() is chosen for the sake of paranoid/defensive programming. Indeed, strncmp() is not really needed when comparing a variable with a string literal. We expect strcmp() to behave safely even if the string variable is not NUL-terminated. In the same scenario, Linux v5.2-rc7 uses both strcmp() and strncmp(), but the frequency of strcmp() is higher: $ git --version git version 2.22.0 $ (Linux 5.2-rc7) git grep -En 'strncmp\([^"]*"[[:alnum:]]+"' | wc -l 1066 $ (Linux 5.2-rc7) git grep -En 'strcmp\([^"]*"[[:alnum:]]+"' | wc -l 1968 A quick "strcmp vs strncmp" object size test shows that strcmp() generates smaller memory footprint (gcc-8, x86_64): $ (U-Boot) size cmd/bcb-strncmp.o cmd/bcb-strcmp.o text data bss dec hex filename 3373 400 2048 5821 16bd cmd/bcb-strncmp.o 3314 400 2048 5762 1682 cmd/bcb-strcmp.o So, overall, I agree to use strcmp() whenever variables are compared with string literals. ----------8<----------- Fixes: db7b7a05b267 ("cmd: Add 'bcb' command to read/modify/write BCB fields") Reported-by: Simon Glass Signed-off-by: Eugeniu Rosca Reviewed-by: Sam Protsenko Reviewed-by: Igor Opaniuk --- cmd/bcb.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'cmd') diff --git a/cmd/bcb.c b/cmd/bcb.c index 3b1c7434e2..fa9fdeeb0d 100644 --- a/cmd/bcb.c +++ b/cmd/bcb.c @@ -24,17 +24,17 @@ static struct bootloader_message bcb = { { 0 } }; static int bcb_cmd_get(char *cmd) { - if (!strncmp(cmd, "load", sizeof("load"))) + if (!strcmp(cmd, "load")) return BCB_CMD_LOAD; - if (!strncmp(cmd, "set", sizeof("set"))) + if (!strcmp(cmd, "set")) return BCB_CMD_FIELD_SET; - if (!strncmp(cmd, "clear", sizeof("clear"))) + if (!strcmp(cmd, "clear")) return BCB_CMD_FIELD_CLEAR; - if (!strncmp(cmd, "test", sizeof("test"))) + if (!strcmp(cmd, "test")) return BCB_CMD_FIELD_TEST; - if (!strncmp(cmd, "store", sizeof("store"))) + if (!strcmp(cmd, "store")) return BCB_CMD_STORE; - if (!strncmp(cmd, "dump", sizeof("dump"))) + if (!strcmp(cmd, "dump")) return BCB_CMD_FIELD_DUMP; else return -1; @@ -85,19 +85,19 @@ err: static int bcb_field_get(char *name, char **field, int *size) { - if (!strncmp(name, "command", sizeof("command"))) { + if (!strcmp(name, "command")) { *field = bcb.command; *size = sizeof(bcb.command); - } else if (!strncmp(name, "status", sizeof("status"))) { + } else if (!strcmp(name, "status")) { *field = bcb.status; *size = sizeof(bcb.status); - } else if (!strncmp(name, "recovery", sizeof("recovery"))) { + } else if (!strcmp(name, "recovery")) { *field = bcb.recovery; *size = sizeof(bcb.recovery); - } else if (!strncmp(name, "stage", sizeof("stage"))) { + } else if (!strcmp(name, "stage")) { *field = bcb.stage; *size = sizeof(bcb.stage); - } else if (!strncmp(name, "reserved", sizeof("reserved"))) { + } else if (!strcmp(name, "reserved")) { *field = bcb.reserved; *size = sizeof(bcb.reserved); } else { -- cgit v1.2.3 From 37f1811a0b31005284e8514955e7bf7e174cc506 Mon Sep 17 00:00:00 2001 From: Eugeniu Rosca Date: Fri, 19 Jul 2019 23:26:14 +0200 Subject: cmd: bcb: Apply non-functional refinements These have been reported by Simon in [1] and fixed in [2]. However, since [1] has already been pushed to u-boot/master, the improvements incorporated in [2] are now extracted and resubmitted. The changes are in the area of coding style and best practices: * s/field/fieldp/, s/size/sizep/, to convey that the variables return an output to the caller * s/err_1/err_read_fail/, s/err_2/err_too_small/, to be more descriptive * Made sure 'static int do_bcb_load' appears on the same line * Placed a `/*` on top of multi-line comment [1] https://patchwork.ozlabs.org/patch/1104244/#2200259 [2] https://patchwork.ozlabs.org/cover/1128661/ ("[v4,0/4] Add 'bcb' command to read/modify/write Android BCB") Fixes: db7b7a05b267 ("cmd: Add 'bcb' command to read/modify/write BCB fields") Reported-by: Simon Glass Signed-off-by: Eugeniu Rosca Reviewed-by: Sam Protsenko --- cmd/bcb.c | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) (limited to 'cmd') diff --git a/cmd/bcb.c b/cmd/bcb.c index fa9fdeeb0d..9626f2c69e 100644 --- a/cmd/bcb.c +++ b/cmd/bcb.c @@ -83,23 +83,23 @@ err: return -1; } -static int bcb_field_get(char *name, char **field, int *size) +static int bcb_field_get(char *name, char **fieldp, int *sizep) { if (!strcmp(name, "command")) { - *field = bcb.command; - *size = sizeof(bcb.command); + *fieldp = bcb.command; + *sizep = sizeof(bcb.command); } else if (!strcmp(name, "status")) { - *field = bcb.status; - *size = sizeof(bcb.status); + *fieldp = bcb.status; + *sizep = sizeof(bcb.status); } else if (!strcmp(name, "recovery")) { - *field = bcb.recovery; - *size = sizeof(bcb.recovery); + *fieldp = bcb.recovery; + *sizep = sizeof(bcb.recovery); } else if (!strcmp(name, "stage")) { - *field = bcb.stage; - *size = sizeof(bcb.stage); + *fieldp = bcb.stage; + *sizep = sizeof(bcb.stage); } else if (!strcmp(name, "reserved")) { - *field = bcb.reserved; - *size = sizeof(bcb.reserved); + *fieldp = bcb.reserved; + *sizep = sizeof(bcb.reserved); } else { printf("Error: Unknown bcb field '%s'\n", name); return -1; @@ -108,8 +108,8 @@ static int bcb_field_get(char *name, char **field, int *size) return 0; } -static int -do_bcb_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +static int do_bcb_load(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { struct blk_desc *desc; disk_partition_t info; @@ -119,28 +119,28 @@ do_bcb_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ret = blk_get_device_by_str("mmc", argv[1], &desc); if (ret < 0) - goto err_1; + goto err_read_fail; part = simple_strtoul(argv[2], &endp, 0); if (*endp == '\0') { ret = part_get_info(desc, part, &info); if (ret) - goto err_1; + goto err_read_fail; } else { part = part_get_info_by_name(desc, argv[2], &info); if (part < 0) { ret = part; - goto err_1; + goto err_read_fail; } } cnt = DIV_ROUND_UP(sizeof(struct bootloader_message), info.blksz); if (cnt > info.size) - goto err_2; + goto err_too_small; if (blk_dread(desc, info.start, cnt, &bcb) != cnt) { ret = -EIO; - goto err_1; + goto err_read_fail; } bcb_dev = desc->devnum; @@ -148,10 +148,10 @@ do_bcb_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) debug("%s: Loaded from mmc %d:%d\n", __func__, bcb_dev, bcb_part); return CMD_RET_SUCCESS; -err_1: +err_read_fail: printf("Error: mmc %s:%s read failed (%d)\n", argv[1], argv[2], ret); goto err; -err_2: +err_too_small: printf("Error: mmc %s:%s too small!", argv[1], argv[2]); goto err; err: @@ -304,7 +304,8 @@ static int do_bcb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) return CMD_RET_USAGE; if (bcb_is_misused(argc, argv)) { - /* We try to improve the user experience by reporting the + /* + * We try to improve the user experience by reporting the * root-cause of misusage, so don't return CMD_RET_USAGE, * since the latter prints out the full-blown help text */ -- cgit v1.2.3 From 17030c7c4c99c09f439641628734dfc5840da3ff Mon Sep 17 00:00:00 2001 From: Ruslan Trofymenko Date: Fri, 5 Jul 2019 15:37:33 +0300 Subject: cmd: Add 'ab_select' command For A/B system update support the Android boot process requires to send 'androidboot.slot_suffix' parameter as a command line argument. This patch implementes 'ab_select' command which allows us to obtain current slot by processing the A/B metadata. The patch was extracted from commit [1] with one modification: the separator for specifying the name of metadata partition was changed from ';' to '#', because ';' is used for commands separation. [1] https://android-review.googlesource.com/c/platform/external/u-boot/+/729880/2 Signed-off-by: Ruslan Trofymenko Signed-off-by: Igor Opaniuk Reviewed-by: Alistair Strachan Reviewed-by: Sam Protsenko Reviewed-by: Simon Glass --- cmd/Kconfig | 15 +++++++++++++++ cmd/Makefile | 1 + cmd/ab_select.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 cmd/ab_select.c (limited to 'cmd') diff --git a/cmd/Kconfig b/cmd/Kconfig index e1e050f4ad..9e66cc110d 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1198,6 +1198,21 @@ config CMD_SETEXPR endmenu +menu "Android support commands" + +config CMD_AB_SELECT + bool "ab_select" + default n + depends on ANDROID_AB + help + On Android devices with more than one boot slot (multiple copies of + the kernel and system images) this provides a command to select which + slot should be used to boot from and register the boot attempt. This + is used by the new A/B update model where one slot is updated in the + background while running from the other slot. + +endmenu + if NET menuconfig CMD_NET diff --git a/cmd/Makefile b/cmd/Makefile index 0aa3741453..43a6b0ee21 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -12,6 +12,7 @@ obj-y += version.o # command obj-$(CONFIG_CMD_AES) += aes.o +obj-$(CONFIG_CMD_AB_SELECT) += ab_select.o obj-$(CONFIG_CMD_ADC) += adc.o obj-$(CONFIG_CMD_ARMFLASH) += armflash.o obj-y += blk_common.o diff --git a/cmd/ab_select.c b/cmd/ab_select.c new file mode 100644 index 0000000000..7c8f2ee8eb --- /dev/null +++ b/cmd/ab_select.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017 The Android Open Source Project + */ + +#include +#include + +static int do_ab_select(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + int ret; + struct blk_desc *dev_desc; + disk_partition_t part_info; + char slot[2]; + + if (argc != 4) + return CMD_RET_USAGE; + + /* Lookup the "misc" partition from argv[2] and argv[3] */ + if (part_get_info_by_dev_and_name_or_num(argv[2], argv[3], + &dev_desc, &part_info) < 0) { + return CMD_RET_FAILURE; + } + + ret = ab_select_slot(dev_desc, &part_info); + if (ret < 0) { + printf("Android boot failed, error %d.\n", ret); + return CMD_RET_FAILURE; + } + + /* Android standard slot names are 'a', 'b', ... */ + slot[0] = BOOT_SLOT_NAME(ret); + slot[1] = '\0'; + env_set(argv[1], slot); + printf("ANDROID: Booting slot: %s\n", slot); + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD(ab_select, 4, 0, do_ab_select, + "Select the slot used to boot from and register the boot attempt.", + " \n" + " - Load the slot metadata from the partition 'part' on\n" + " device type 'interface' instance 'dev' and store the active\n" + " slot in the 'slot_var_name' variable. This also updates the\n" + " Android slot metadata with a boot attempt, which can cause\n" + " successive calls to this function to return a different result\n" + " if the returned slot runs out of boot attempts.\n" + " - If 'part_name' is passed, preceded with a # instead of :, the\n" + " partition name whose label is 'part_name' will be looked up in\n" + " the partition table. This is commonly the \"misc\" partition.\n" +); -- cgit v1.2.3