Hi Alexey,

On lun., mars 04, 2024 at 14:03, Alexey Romanov <[email protected]> 
wrote:

> 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 
>> <[email protected]> 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 <[email protected]>
>> > ---
>> >  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?

I would have liked to have a generic "erase bootenv" command yes, but
your solution seems fine so no need to do something different.

Thank you for your patience with this !

>
>> (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