summaryrefslogtreecommitdiff
path: root/drivers/fastboot
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/fastboot')
-rw-r--r--drivers/fastboot/Kconfig12
-rw-r--r--drivers/fastboot/Makefile1
-rw-r--r--drivers/fastboot/fb_bcb_impl.c43
-rw-r--r--drivers/fastboot/fb_command.c40
-rw-r--r--drivers/fastboot/fb_common.c2
-rw-r--r--drivers/fastboot/fb_getvar.c4
-rw-r--r--drivers/fastboot/fb_mmc.c75
7 files changed, 164 insertions, 13 deletions
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
index d4436dfc917..4352ba67a71 100644
--- a/drivers/fastboot/Kconfig
+++ b/drivers/fastboot/Kconfig
@@ -165,6 +165,18 @@ config FASTBOOT_CMD_OEM_FORMAT
relies on the env variable partitions to contain the list of
partitions as required by the gpt command.
+config FASTBOOT_USE_BCB_SET_REBOOT_FLAG
+ bool "Use BCB by fastboot to set boot reason"
+ depends on CMD_BCB && !ARCH_MESON && !ARCH_ROCKCHIP && !TARGET_KC1 && \
+ !TARGET_SNIPER && !TARGET_AM57XX_EVM && !TARGET_DRA7XX_EVM
+ default y
+ help
+ Fastboot could implement setting of reboot reason in a generic fashion
+ via BCB commands. BCB commands are able to write reboot reason into
+ command field of boot control block. In general case it is sufficient
+ implementation if your platform supports BCB commands and doesn't
+ require any specific reboot reason handling.
+
endif # FASTBOOT
endmenu
diff --git a/drivers/fastboot/Makefile b/drivers/fastboot/Makefile
index 048af5aa823..2b2c390fe4d 100644
--- a/drivers/fastboot/Makefile
+++ b/drivers/fastboot/Makefile
@@ -5,3 +5,4 @@ obj-y += fb_getvar.o
obj-y += fb_command.o
obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fb_mmc.o
obj-$(CONFIG_FASTBOOT_FLASH_NAND) += fb_nand.o
+obj-$(CONFIG_FASTBOOT_USE_BCB_SET_REBOOT_FLAG) += fb_bcb_impl.o
diff --git a/drivers/fastboot/fb_bcb_impl.c b/drivers/fastboot/fb_bcb_impl.c
new file mode 100644
index 00000000000..89ec3601b6f
--- /dev/null
+++ b/drivers/fastboot/fb_bcb_impl.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 GlobalLogic.
+ * Roman Kovalivskyi <roman.kovalivskyi@globallogic.com>
+ */
+
+#include <common.h>
+#include <fastboot.h>
+
+/**
+ * fastboot_set_reboot_flag() - Set flag to indicate reboot-bootloader
+ *
+ * Set flag which indicates that we should reboot into the bootloader
+ * following the reboot that fastboot executes after this function.
+ *
+ * This function should be overridden in your board file with one
+ * which sets whatever flag your board specific Android bootloader flow
+ * requires in order to re-enter the bootloader.
+ */
+int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason)
+{
+ char cmd[64];
+
+ if (reason >= FASTBOOT_REBOOT_REASONS_COUNT)
+ return -EINVAL;
+
+ snprintf(cmd, sizeof(cmd), "bcb load %d misc",
+ CONFIG_FASTBOOT_FLASH_MMC_DEV);
+
+ if (run_command(cmd, 0))
+ return -ENODEV;
+
+ snprintf(cmd, sizeof(cmd), "bcb set command %s",
+ fastboot_boot_cmds[reason]);
+
+ if (run_command(cmd, 0))
+ return -ENOEXEC;
+
+ if (run_command("bcb store", 0))
+ return -EIO;
+
+ return 0;
+}
diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c
index 49f6a61c374..d3c578672dc 100644
--- a/drivers/fastboot/fb_command.c
+++ b/drivers/fastboot/fb_command.c
@@ -37,6 +37,8 @@ static void flash(char *, char *);
static void erase(char *, char *);
#endif
static void reboot_bootloader(char *, char *);
+static void reboot_fastbootd(char *, char *);
+static void reboot_recovery(char *, char *);
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
static void oem_format(char *, char *);
#endif
@@ -79,6 +81,14 @@ static const struct {
.command = "reboot-bootloader",
.dispatch = reboot_bootloader
},
+ [FASTBOOT_COMMAND_REBOOT_FASTBOOTD] = {
+ .command = "reboot-fastboot",
+ .dispatch = reboot_fastbootd
+ },
+ [FASTBOOT_COMMAND_REBOOT_RECOVERY] = {
+ .command = "reboot-recovery",
+ .dispatch = reboot_recovery
+ },
[FASTBOOT_COMMAND_SET_ACTIVE] = {
.command = "set_active",
.dispatch = okay
@@ -307,12 +317,40 @@ static void erase(char *cmd_parameter, char *response)
*/
static void reboot_bootloader(char *cmd_parameter, char *response)
{
- if (fastboot_set_reboot_flag())
+ if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_BOOTLOADER))
fastboot_fail("Cannot set reboot flag", response);
else
fastboot_okay(NULL, response);
}
+/**
+ * reboot_fastbootd() - Sets reboot fastboot flag.
+ *
+ * @cmd_parameter: Pointer to command parameter
+ * @response: Pointer to fastboot response buffer
+ */
+static void reboot_fastbootd(char *cmd_parameter, char *response)
+{
+ if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_FASTBOOTD))
+ fastboot_fail("Cannot set fastboot flag", response);
+ else
+ fastboot_okay(NULL, response);
+}
+
+/**
+ * reboot_recovery() - Sets reboot recovery flag.
+ *
+ * @cmd_parameter: Pointer to command parameter
+ * @response: Pointer to fastboot response buffer
+ */
+static void reboot_recovery(char *cmd_parameter, char *response)
+{
+ if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_RECOVERY))
+ fastboot_fail("Cannot set recovery flag", response);
+ else
+ fastboot_okay(NULL, response);
+}
+
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
/**
* oem_format() - Execute the OEM format command
diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c
index c3735a44af7..736ce1cd024 100644
--- a/drivers/fastboot/fb_common.c
+++ b/drivers/fastboot/fb_common.c
@@ -88,7 +88,7 @@ void fastboot_okay(const char *reason, char *response)
* which sets whatever flag your board specific Android bootloader flow
* requires in order to re-enter the bootloader.
*/
-int __weak fastboot_set_reboot_flag(void)
+int __weak fastboot_set_reboot_flag(enum fastboot_reboot_reason reason)
{
return -ENOSYS;
}
diff --git a/drivers/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c
index 52da34b1e37..d43f2cfee66 100644
--- a/drivers/fastboot/fb_getvar.c
+++ b/drivers/fastboot/fb_getvar.c
@@ -95,7 +95,7 @@ static const struct {
*
* @param[in] part_name Info for which partition name to look for
* @param[in,out] response Pointer to fastboot response buffer
- * @param[out] size If not NULL, will contain partition size (in blocks)
+ * @param[out] size If not NULL, will contain partition size
* @return Partition number or negative value on error
*/
static int getvar_get_part_info(const char *part_name, char *response,
@@ -109,7 +109,7 @@ static int getvar_get_part_info(const char *part_name, char *response,
r = fastboot_mmc_get_part_info(part_name, &dev_desc, &part_info,
response);
if (r >= 0 && size)
- *size = part_info.size;
+ *size = part_info.size * part_info.blksz;
# elif CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)
struct part_info *part_info;
diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c
index b2f8932e1c7..ae8e8e512f2 100644
--- a/drivers/fastboot/fb_mmc.c
+++ b/drivers/fastboot/fb_mmc.c
@@ -50,6 +50,48 @@ static int part_get_info_by_name_or_alias(struct blk_desc *dev_desc,
return ret;
}
+static int raw_part_get_info_by_name(struct blk_desc *dev_desc,
+ const char *name, struct disk_partition *info, int *mmcpart)
+{
+ /* strlen("fastboot_raw_partition_") + PART_NAME_LEN + 1 */
+ char env_desc_name[23 + PART_NAME_LEN + 1];
+ char *raw_part_desc;
+ const char *argv[2];
+ const char **parg = argv;
+
+ /* check for raw partition descriptor */
+ strcpy(env_desc_name, "fastboot_raw_partition_");
+ strncat(env_desc_name, name, PART_NAME_LEN);
+ raw_part_desc = strdup(env_get(env_desc_name));
+ if (raw_part_desc == NULL)
+ return -ENODEV;
+
+ /*
+ * parse partition descriptor
+ *
+ * <lba_start> <lba_size> [mmcpart <num>]
+ */
+ for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) {
+ *parg = strsep(&raw_part_desc, " ");
+ if (*parg == NULL) {
+ pr_err("Invalid number of arguments.\n");
+ return -ENODEV;
+ }
+ }
+
+ info->start = simple_strtoul(argv[0], NULL, 0);
+ info->size = simple_strtoul(argv[1], NULL, 0);
+ info->blksz = dev_desc->blksz;
+ strncpy((char *)info->name, name, PART_NAME_LEN);
+
+ if (raw_part_desc) {
+ if (strcmp(strsep(&raw_part_desc, " "), "mmcpart") == 0)
+ *mmcpart = simple_strtoul(raw_part_desc, NULL, 0);
+ }
+
+ return 0;
+}
+
/**
* fb_mmc_blk_write() - Write/erase MMC in chunks of FASTBOOT_MAX_BLK_WRITE
*
@@ -376,7 +418,8 @@ int fastboot_mmc_get_part_info(const char *part_name,
struct blk_desc **dev_desc,
struct disk_partition *part_info, char *response)
{
- int r;
+ int r = 0;
+ int mmcpart;
*dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (!*dev_desc) {
@@ -388,10 +431,12 @@ int fastboot_mmc_get_part_info(const char *part_name,
return -ENOENT;
}
- r = part_get_info_by_name_or_alias(*dev_desc, part_name, part_info);
- if (r < 0) {
- fastboot_fail("partition not found", response);
- return r;
+ if (raw_part_get_info_by_name(*dev_desc, part_name, part_info, &mmcpart) < 0) {
+ r = part_get_info_by_name_or_alias(*dev_desc, part_name, part_info);
+ if (r < 0) {
+ fastboot_fail("partition not found", response);
+ return r;
+ }
}
return r;
@@ -410,6 +455,7 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
{
struct blk_desc *dev_desc;
struct disk_partition info;
+ int mmcpart = 0;
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
@@ -482,7 +528,13 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
}
#endif
- if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0) {
+ if (raw_part_get_info_by_name(dev_desc, cmd, &info, &mmcpart) == 0) {
+ if (blk_dselect_hwpart(dev_desc, mmcpart)) {
+ pr_err("Failed to select hwpart\n");
+ fastboot_fail("Failed to select hwpart", response);
+ return;
+ }
+ } else if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0) {
pr_err("cannot find partition: '%s'\n", cmd);
fastboot_fail("cannot find partition", response);
return;
@@ -524,11 +576,11 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
*/
void fastboot_mmc_erase(const char *cmd, char *response)
{
- int ret;
struct blk_desc *dev_desc;
struct disk_partition info;
lbaint_t blks, blks_start, blks_size, grp_size;
struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
+ int mmcpart = 0;
if (mmc == NULL) {
pr_err("invalid mmc device\n");
@@ -562,8 +614,13 @@ void fastboot_mmc_erase(const char *cmd, char *response)
}
#endif
- ret = part_get_info_by_name_or_alias(dev_desc, cmd, &info);
- if (ret < 0) {
+ if (raw_part_get_info_by_name(dev_desc, cmd, &info, &mmcpart) == 0) {
+ if (blk_dselect_hwpart(dev_desc, mmcpart)) {
+ pr_err("Failed to select hwpart\n");
+ fastboot_fail("Failed to select hwpart", response);
+ return;
+ }
+ } else if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0) {
pr_err("cannot find partition: '%s'\n", cmd);
fastboot_fail("cannot find partition", response);
return;