[RFC PATCH v2 2/2] board: ad401: example of fastboot oem board realization

Alexey Romanov avromanov at salutedevices.com
Thu Feb 1 10:20:27 CET 2024


An example of how we use fastboot oeam board subcommand
for Sean Anderson.

1 - OEM_BOARD_WRITE_BOOTLOADER_CMD:

We use it for custom Amlogic bootloader + tpl
flashing protocol.

2 - OEM_BOARD_ERASE_CMD:

Custom logic for erasing the env-emulated partition,
which isn't in the mtd markup map.

Example of the script which completely flashes the device:

  $ fastboot erase bootloader
  $ fastboot stage u-boot.bin
  $ fastboot oem board:write_bootloader
  $ fastboot reboot-bootloader
  $ fastboot oem board:erase_env
  $ fastboot erase misc
  $ fastboot erase super
  $ fastboot flash super rootfs
  $ fastboot reboot

Signed-off-by: Alexey Romanov <avromanov at salutedevices.com>
---
 board/amlogic/ad401/fastboot.c | 222 +++++++++++++++++++++++++++++++++
 1 file changed, 222 insertions(+)
 create mode 100644 board/amlogic/ad401/fastboot.c

diff --git a/board/amlogic/ad401/fastboot.c b/board/amlogic/ad401/fastboot.c
new file mode 100644
index 0000000000..01da8efa5b
--- /dev/null
+++ b/board/amlogic/ad401/fastboot.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2023 SaluteDevices, Inc.
+ */
+
+#include <common.h>
+#include <env.h>
+#include <fastboot.h>
+#include <nand.h>
+#include <asm/arch/nand.h>
+#include <jffs2/load_kernel.h>
+#include <linux/sizes.h>
+#include <linux/types.h>
+#include <linux/mtd/mtd.h>
+
+enum {
+	OEM_BOARD_ERASE_CMD,
+	OEM_BOARD_WRITE_BOOTLOADER_CMD,
+};
+
+struct defenv {
+	char *name;
+	char value[256];
+};
+
+static void save_defenv(struct defenv *e, size_t cnt)
+{
+	int i;
+
+	for (i = 0; i < cnt; i++) {
+		const char *env_val = env_get(e[i].name);
+
+		if (env_val)
+			strlcpy(e[i].value, env_val, sizeof(e[i].value));
+		else
+			e[i].value[0] = '\0';
+	}
+}
+
+static void set_defenv(struct defenv *e, size_t cnt)
+{
+	int i;
+
+	for (i = 0; i < cnt; i++)
+		env_set(e[i].name, e[i].value);
+}
+
+static int fastboot_erase_env(void)
+{
+	char *const defenv_names[] = { "lock", "mtdparts", "mtdids" };
+	struct defenv env[ARRAY_SIZE(defenv_names)];
+	int err, i;
+
+	for (i = 0; i < ARRAY_SIZE(env); i++)
+		env[i].name = defenv_names[i];
+
+	printf("ENV is being erased...\n");
+
+	/*
+	 * Reset environment to the default, excluding 'lock' variable,
+	 * because it reflects the fastboot's state after execution of
+	 * 'flashing unlock' command, hence it must survive the env-erasing.
+	 * Otherwise, further erase commands will fail on check_lock().
+	 *
+	 * Also, we have to save 'mtdparts' and 'mtdids' variables
+	 * because they are necessary to obtain partition map.
+	 */
+
+	save_defenv(env, ARRAY_SIZE(env));
+	env_set_default(NULL, 0);
+	set_defenv(env, ARRAY_SIZE(env));
+
+	err = env_save();
+	if (err) {
+		pr_err("Can't overwrite ENV-partition\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int fastboot_nand_write_tpl(struct mtd_info *mtd, void *buffer,
+				   u32 offset, size_t size, int flags)
+{
+	int boot_cpy_num = meson_bootloader_copy_num(BOOT_TPL);
+	u64 size_per_copy = meson_bootloader_copy_size(mtd, BOOT_TPL);
+	int i;
+
+	for (i = 0; i < boot_cpy_num; i++) {
+		size_t retlen, len = size;
+		int ret;
+
+		ret = nand_write_skip_bad(mtd, offset + (i * size_per_copy),
+					  &len, &retlen, offset + size_per_copy,
+					  buffer, flags);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int fastboot_nand_write_bl2(struct mtd_info *mtd, void *buffer,
+				   u32 offset, size_t size, int flags)
+{
+	int boot_cpy_num = meson_bootloader_copy_num(BOOT_BL2);
+	u64 size_per_copy = meson_bootloader_copy_size(mtd, BOOT_BL2);
+	int i;
+
+	for (i = 0; i < boot_cpy_num; i++) {
+		int ret;
+
+		ret = meson_bootloader_write_bl2(mtd, buffer,
+						 offset + (i * size_per_copy),
+					         size, flags);
+		if (ret)
+			return ret;
+	}
+
+	return meson_bootloader_write_info_pages();
+}
+
+static int fastboot_nand_write_bootloader(void *buffer, u32 size)
+{
+	struct part_info *part;
+	struct mtd_info *mtd = NULL;
+	struct mtd_device *dev;
+	u8 pnum;
+	int ret;
+
+	if (size < BL2_SIZE)
+		return 0;
+
+	if (!buffer)
+		return -EINVAL;
+
+	ret = mtdparts_init();
+	if (ret) {
+		pr_err("Cannot initialize MTD partitions\n");
+		return ret;
+	}
+
+	ret = find_dev_and_part("bootloader", &dev, &pnum, &part);
+	if (ret) {
+		pr_err("cannot find 'bootloader' partition\n");
+		return ret;
+	}
+
+	mtd = get_nand_dev_by_index(dev->id->num);
+	if (!mtd)
+		return -EINVAL;
+
+	ret = fastboot_nand_write_bl2(mtd, buffer, part->offset,
+				      BL2_SIZE, WITH_WR_VERIFY);
+	if (ret) {
+		pr_err("fastboot: failed to write BL2\n");
+		return ret;
+	}
+
+	ret = find_dev_and_part("tpl", &dev, &pnum, &part);
+	if (ret) {
+		pr_err("cannot find 'bootloader' partition\n");
+		return ret;
+	}
+
+	mtd = get_nand_dev_by_index(dev->id->num);
+	if (!mtd)
+		return -EINVAL;
+
+	ret = fastboot_nand_write_tpl(mtd, buffer + BL2_SIZE, part->offset,
+				      size - BL2_SIZE, WITH_WR_VERIFY);
+	if (ret) {
+		pr_err("fastboot: failed to write TPL\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+int get_oem_board_command(const char *cmd)
+{
+	const char *oem_commands[] = {
+		[OEM_BOARD_ERASE_CMD] = "erase_env",
+		[OEM_BOARD_WRITE_BOOTLOADER_CMD] = "write_bootloader",
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(oem_commands); i++)
+		if (!strcmp(cmd, oem_commands[i]))
+			return i;
+
+	return -EINVAL;
+}
+
+void fastboot_oem_board(const char *cmd_parameter, void *data, u32 size,
+			char *response)
+{
+	char buf[128] = { 0 };
+	int ret, cmd;
+
+	cmd = get_oem_board_command(cmd_parameter);
+
+	switch (cmd) {
+		case OEM_BOARD_ERASE_CMD:
+			ret = fastboot_erase_env();
+			break;
+		case OEM_BOARD_WRITE_BOOTLOADER_CMD:
+			ret = fastboot_nand_write_bootloader(data, size);
+			break;
+		default:
+			snprintf(buf, sizeof(buf),
+				 "Command 'oem board %s' not supported",
+				 cmd_parameter);
+			fastboot_fail(buf, response);
+			return;
+	}
+
+	if (ret < 0)
+		fastboot_fail("Failed to erase env partition", response);
+	else
+		fastboot_okay(NULL, response);
+}
-- 
2.30.1



More information about the U-Boot mailing list