mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-30 08:07:59 +00:00
cmd: bcb: support various block device interfaces for BCB command
Currently BCB command-line, C APIs and implementation only support MMC interface. Extend it to allow various block device interfaces. Signed-off-by: Dmitrii Merkurev <dimorinny@google.com> Cc: Eugeniu Rosca <erosca@de.adit-jv.com> Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org> Cc: Simon Glass <sjg@chromium.org> Cc: Mattijs Korpershoek <mkorpershoek@baylibre.com> Cc: Sean Anderson <sean.anderson@seco.com> Cc: Cody Schuffelen <schuffelen@google.com> Tested-by: Mattijs Korpershoek <mkorpershoek@baylibre.com> # on vim3 Reviewed-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
This commit is contained in:
parent
66a3618b9a
commit
a654369b49
5 changed files with 65 additions and 47 deletions
|
@ -960,7 +960,6 @@ config CMD_ADC
|
||||||
|
|
||||||
config CMD_BCB
|
config CMD_BCB
|
||||||
bool "bcb"
|
bool "bcb"
|
||||||
depends on MMC
|
|
||||||
depends on PARTITIONS
|
depends on PARTITIONS
|
||||||
help
|
help
|
||||||
Read/modify/write the fields of Bootloader Control Block, usually
|
Read/modify/write the fields of Bootloader Control Block, usually
|
||||||
|
|
70
cmd/bcb.c
70
cmd/bcb.c
|
@ -25,6 +25,7 @@ enum bcb_cmd {
|
||||||
BCB_CMD_STORE,
|
BCB_CMD_STORE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum uclass_id bcb_uclass_id = UCLASS_INVALID;
|
||||||
static int bcb_dev = -1;
|
static int bcb_dev = -1;
|
||||||
static int bcb_part = -1;
|
static int bcb_part = -1;
|
||||||
static struct bootloader_message bcb __aligned(ARCH_DMA_MINALIGN) = { { 0 } };
|
static struct bootloader_message bcb __aligned(ARCH_DMA_MINALIGN) = { { 0 } };
|
||||||
|
@ -53,6 +54,9 @@ static int bcb_is_misused(int argc, char *const argv[])
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case BCB_CMD_LOAD:
|
case BCB_CMD_LOAD:
|
||||||
|
if (argc != 3 && argc != 4)
|
||||||
|
goto err;
|
||||||
|
break;
|
||||||
case BCB_CMD_FIELD_SET:
|
case BCB_CMD_FIELD_SET:
|
||||||
if (argc != 3)
|
if (argc != 3)
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -115,7 +119,7 @@ static int bcb_field_get(char *name, char **fieldp, int *sizep)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __bcb_load(int devnum, const char *partp)
|
static int __bcb_load(const char *iface, int devnum, const char *partp)
|
||||||
{
|
{
|
||||||
struct blk_desc *desc;
|
struct blk_desc *desc;
|
||||||
struct disk_partition info;
|
struct disk_partition info;
|
||||||
|
@ -123,14 +127,14 @@ static int __bcb_load(int devnum, const char *partp)
|
||||||
char *endp;
|
char *endp;
|
||||||
int part, ret;
|
int part, ret;
|
||||||
|
|
||||||
desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, devnum);
|
desc = blk_get_dev(iface, devnum);
|
||||||
if (!desc) {
|
if (!desc) {
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err_read_fail;
|
goto err_read_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* always select the USER mmc hwpart in case another
|
* always select the first hwpart in case another
|
||||||
* blk operation selected a different hwpart
|
* blk operation selected a different hwpart
|
||||||
*/
|
*/
|
||||||
ret = blk_dselect_hwpart(desc, 0);
|
ret = blk_dselect_hwpart(desc, 0);
|
||||||
|
@ -161,18 +165,20 @@ static int __bcb_load(int devnum, const char *partp)
|
||||||
goto err_read_fail;
|
goto err_read_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bcb_uclass_id = desc->uclass_id;
|
||||||
bcb_dev = desc->devnum;
|
bcb_dev = desc->devnum;
|
||||||
bcb_part = part;
|
bcb_part = part;
|
||||||
debug("%s: Loaded from mmc %d:%d\n", __func__, bcb_dev, bcb_part);
|
debug("%s: Loaded from %s %d:%d\n", __func__, iface, bcb_dev, bcb_part);
|
||||||
|
|
||||||
return CMD_RET_SUCCESS;
|
return CMD_RET_SUCCESS;
|
||||||
err_read_fail:
|
err_read_fail:
|
||||||
printf("Error: mmc %d:%s read failed (%d)\n", devnum, partp, ret);
|
printf("Error: %s %d:%s read failed (%d)\n", iface, devnum, partp, ret);
|
||||||
goto err;
|
goto err;
|
||||||
err_too_small:
|
err_too_small:
|
||||||
printf("Error: mmc %d:%s too small!", devnum, partp);
|
printf("Error: %s %d:%s too small!", iface, devnum, partp);
|
||||||
goto err;
|
goto err;
|
||||||
err:
|
err:
|
||||||
|
bcb_uclass_id = UCLASS_INVALID;
|
||||||
bcb_dev = -1;
|
bcb_dev = -1;
|
||||||
bcb_part = -1;
|
bcb_part = -1;
|
||||||
|
|
||||||
|
@ -182,15 +188,23 @@ err:
|
||||||
static int do_bcb_load(struct cmd_tbl *cmdtp, int flag, int argc,
|
static int do_bcb_load(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
char * const argv[])
|
char * const argv[])
|
||||||
{
|
{
|
||||||
|
int devnum;
|
||||||
char *endp;
|
char *endp;
|
||||||
int devnum = simple_strtoul(argv[1], &endp, 0);
|
char *iface = "mmc";
|
||||||
|
|
||||||
|
if (argc == 4) {
|
||||||
|
iface = argv[1];
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
devnum = simple_strtoul(argv[1], &endp, 0);
|
||||||
if (*endp != '\0') {
|
if (*endp != '\0') {
|
||||||
printf("Error: Device id '%s' not a number\n", argv[1]);
|
printf("Error: Device id '%s' not a number\n", argv[1]);
|
||||||
return CMD_RET_FAILURE;
|
return CMD_RET_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return __bcb_load(devnum, argv[2]);
|
return __bcb_load(iface, devnum, argv[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __bcb_set(char *fieldp, const char *valp)
|
static int __bcb_set(char *fieldp, const char *valp)
|
||||||
|
@ -298,7 +312,7 @@ static int __bcb_store(void)
|
||||||
u64 cnt;
|
u64 cnt;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, bcb_dev);
|
desc = blk_get_devnum_by_uclass_id(bcb_uclass_id, bcb_dev);
|
||||||
if (!desc) {
|
if (!desc) {
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -317,7 +331,7 @@ static int __bcb_store(void)
|
||||||
|
|
||||||
return CMD_RET_SUCCESS;
|
return CMD_RET_SUCCESS;
|
||||||
err:
|
err:
|
||||||
printf("Error: mmc %d:%d write failed (%d)\n", bcb_dev, bcb_part, ret);
|
printf("Error: %d %d:%d write failed (%d)\n", bcb_uclass_id, bcb_dev, bcb_part, ret);
|
||||||
|
|
||||||
return CMD_RET_FAILURE;
|
return CMD_RET_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -328,11 +342,11 @@ static int do_bcb_store(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
return __bcb_store();
|
return __bcb_store();
|
||||||
}
|
}
|
||||||
|
|
||||||
int bcb_write_reboot_reason(int devnum, char *partp, const char *reasonp)
|
int bcb_write_reboot_reason(const char *iface, int devnum, char *partp, const char *reasonp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = __bcb_load(devnum, partp);
|
ret = __bcb_load(iface, devnum, partp);
|
||||||
if (ret != CMD_RET_SUCCESS)
|
if (ret != CMD_RET_SUCCESS)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -385,21 +399,23 @@ static int do_bcb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||||
U_BOOT_CMD(
|
U_BOOT_CMD(
|
||||||
bcb, CONFIG_SYS_MAXARGS, 1, do_bcb,
|
bcb, CONFIG_SYS_MAXARGS, 1, do_bcb,
|
||||||
"Load/set/clear/test/dump/store Android BCB fields",
|
"Load/set/clear/test/dump/store Android BCB fields",
|
||||||
"load <dev> <part> - load BCB from mmc <dev>:<part>\n"
|
"load <interface> <dev> <part> - load BCB from <interface> <dev>:<part>\n"
|
||||||
"bcb set <field> <val> - set BCB <field> to <val>\n"
|
"load <dev> <part> - load BCB from mmc <dev>:<part>\n"
|
||||||
"bcb clear [<field>] - clear BCB <field> or all fields\n"
|
"bcb set <field> <val> - set BCB <field> to <val>\n"
|
||||||
"bcb test <field> <op> <val> - test BCB <field> against <val>\n"
|
"bcb clear [<field>] - clear BCB <field> or all fields\n"
|
||||||
"bcb dump <field> - dump BCB <field>\n"
|
"bcb test <field> <op> <val> - test BCB <field> against <val>\n"
|
||||||
"bcb store - store BCB back to mmc\n"
|
"bcb dump <field> - dump BCB <field>\n"
|
||||||
|
"bcb store - store BCB back to <interface>\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Legend:\n"
|
"Legend:\n"
|
||||||
"<dev> - MMC device index containing the BCB partition\n"
|
"<interface> - storage device interface (virtio, mmc, etc)\n"
|
||||||
"<part> - MMC partition index or name containing the BCB\n"
|
"<dev> - storage device index containing the BCB partition\n"
|
||||||
"<field> - one of {command,status,recovery,stage,reserved}\n"
|
"<part> - partition index or name containing the BCB\n"
|
||||||
"<op> - the binary operator used in 'bcb test':\n"
|
"<field> - one of {command,status,recovery,stage,reserved}\n"
|
||||||
" '=' returns true if <val> matches the string stored in <field>\n"
|
"<op> - the binary operator used in 'bcb test':\n"
|
||||||
" '~' returns true if <val> matches a subset of <field>'s string\n"
|
" '=' returns true if <val> matches the string stored in <field>\n"
|
||||||
"<val> - string/text provided as input to bcb {set,test}\n"
|
" '~' returns true if <val> matches a subset of <field>'s string\n"
|
||||||
" NOTE: any ':' character in <val> will be replaced by line feed\n"
|
"<val> - string/text provided as input to bcb {set,test}\n"
|
||||||
" during 'bcb set' and used as separator by upper layers\n"
|
" NOTE: any ':' character in <val> will be replaced by line feed\n"
|
||||||
|
" during 'bcb set' and used as separator by upper layers\n"
|
||||||
);
|
);
|
||||||
|
|
|
@ -41,23 +41,25 @@ requirements enumerated above. Below is the command's help message::
|
||||||
bcb - Load/set/clear/test/dump/store Android BCB fields
|
bcb - Load/set/clear/test/dump/store Android BCB fields
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
bcb load <dev> <part> - load BCB from mmc <dev>:<part>
|
bcb load <interface> <dev> <part> - load BCB from <interface> <dev>:<part>
|
||||||
bcb set <field> <val> - set BCB <field> to <val>
|
load <dev> <part> - load BCB from mmc <dev>:<part>
|
||||||
bcb clear [<field>] - clear BCB <field> or all fields
|
bcb set <field> <val> - set BCB <field> to <val>
|
||||||
bcb test <field> <op> <val> - test BCB <field> against <val>
|
bcb clear [<field>] - clear BCB <field> or all fields
|
||||||
bcb dump <field> - dump BCB <field>
|
bcb test <field> <op> <val> - test BCB <field> against <val>
|
||||||
bcb store - store BCB back to mmc
|
bcb dump <field> - dump BCB <field>
|
||||||
|
bcb store - store BCB back to <interface>
|
||||||
|
|
||||||
Legend:
|
Legend:
|
||||||
<dev> - MMC device index containing the BCB partition
|
<interface> - storage device interface (virtio, mmc, etc)
|
||||||
<part> - MMC partition index or name containing the BCB
|
<dev> - storage device index containing the BCB partition
|
||||||
<field> - one of {command,status,recovery,stage,reserved}
|
<part> - partition index or name containing the BCB
|
||||||
<op> - the binary operator used in 'bcb test':
|
<field> - one of {command,status,recovery,stage,reserved}
|
||||||
'=' returns true if <val> matches the string stored in <field>
|
<op> - the binary operator used in 'bcb test':
|
||||||
'~' returns true if <val> matches a subset of <field>'s string
|
'=' returns true if <val> matches the string stored in <field>
|
||||||
<val> - string/text provided as input to bcb {set,test}
|
'~' returns true if <val> matches a subset of <field>'s string
|
||||||
NOTE: any ':' character in <val> will be replaced by line feed
|
<val> - string/text provided as input to bcb {set,test}
|
||||||
during 'bcb set' and used as separator by upper layers
|
NOTE: any ':' character in <val> will be replaced by line feed
|
||||||
|
during 'bcb set' and used as separator by upper layers
|
||||||
|
|
||||||
|
|
||||||
'bcb'. Example of getting reboot reason
|
'bcb'. Example of getting reboot reason
|
||||||
|
@ -91,7 +93,7 @@ The following Kconfig options must be enabled::
|
||||||
|
|
||||||
CONFIG_PARTITIONS=y
|
CONFIG_PARTITIONS=y
|
||||||
CONFIG_MMC=y
|
CONFIG_MMC=y
|
||||||
CONFIG_BCB=y
|
CONFIG_CMD_BCB=y
|
||||||
|
|
||||||
.. [1] https://android.googlesource.com/platform/bootable/recovery
|
.. [1] https://android.googlesource.com/platform/bootable/recovery
|
||||||
.. [2] https://source.android.com/devices/bootloader
|
.. [2] https://source.android.com/devices/bootloader
|
||||||
|
|
|
@ -105,7 +105,7 @@ int __weak fastboot_set_reboot_flag(enum fastboot_reboot_reason reason)
|
||||||
if (reason >= FASTBOOT_REBOOT_REASONS_COUNT)
|
if (reason >= FASTBOOT_REBOOT_REASONS_COUNT)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return bcb_write_reboot_reason(mmc_dev, "misc", boot_cmds[reason]);
|
return bcb_write_reboot_reason("mmc", mmc_dev, "misc", boot_cmds[reason]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -9,10 +9,11 @@
|
||||||
#define __BCB_H__
|
#define __BCB_H__
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_CMD_BCB)
|
#if IS_ENABLED(CONFIG_CMD_BCB)
|
||||||
int bcb_write_reboot_reason(int devnum, char *partp, const char *reasonp);
|
int bcb_write_reboot_reason(const char *iface, int devnum, char *partp, const char *reasonp);
|
||||||
#else
|
#else
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
static inline int bcb_write_reboot_reason(int devnum, char *partp, const char *reasonp)
|
static inline int bcb_write_reboot_reason(const char *iface, int devnum,
|
||||||
|
char *partp, const char *reasonp)
|
||||||
{
|
{
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue