Hello Mattijs, On Thu, Feb 15, 2024 at 10:24:11AM +0100, Mattijs Korpershoek wrote: > On jeu., f'evr. 01, 2024 at 12:20, Alexey Romanov > <avroma...@salutedevices.com> wrote: > > > 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 <avroma...@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; > > + } > > Hmm so the fastboot locked state is saved in the U-Boot environment. > There is probably a good reason for this (no secure storage for > example). But this does not feel board specific. > > Wouldn't it be better if we could just run "fastboot erase bootenv" and > that the generic fastboot code does the right thing?
Are you proposing to modify the code of fastboot in such a way that if user send 'erase bootenv' string, then we call generic function to cleanup environment, instead of try to search (and erase) in partition schema 'bootenv' partition? > (which is env default, and ignoring some magic/specific variables) > > > + > > + 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 -- Thank you, Alexey