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

Reply via email to