Sorry, pls ping

Thanks, Arseniy

On 08.01.2024 21:33, Arseniy Krasnov wrote:
> Sorry, pls ping
> 
> Thanks, Arseniy
> 
> On 20.12.2023 22:36, Arseniy Krasnov wrote:
>> Add access to OTP region. It supports info, dump, write and lock
>> operations.
>>
>> Signed-off-by: Arseniy Krasnov <avkras...@salutedevices.com>
>> ---
>>  Changelog:
>>  v1 -> v2:
>>   * Remove warning that OTP can't be erased after write.
>>
>>  cmd/Kconfig |   1 +
>>  cmd/mtd.c   | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 225 insertions(+)
>>
>> diff --git a/cmd/Kconfig b/cmd/Kconfig
>> index 90e4ef93e0..c47523a03b 100644
>> --- a/cmd/Kconfig
>> +++ b/cmd/Kconfig
>> @@ -1354,6 +1354,7 @@ config CMD_MTD
>>      bool "mtd"
>>      depends on MTD
>>      select MTD_PARTITIONS
>> +    select HEXDUMP
>>      help
>>        MTD commands support.
>>  
>> diff --git a/cmd/mtd.c b/cmd/mtd.c
>> index eb6e2d6892..1ab69b108b 100644
>> --- a/cmd/mtd.c
>> +++ b/cmd/mtd.c
>> @@ -11,6 +11,7 @@
>>  #include <command.h>
>>  #include <common.h>
>>  #include <console.h>
>> +#include <hexdump.h>
>>  #include <malloc.h>
>>  #include <mapmem.h>
>>  #include <mtd.h>
>> @@ -202,6 +203,219 @@ static bool mtd_oob_write_is_empty(struct mtd_oob_ops 
>> *op)
>>      return true;
>>  }
>>  
>> +static int do_mtd_otp_read(struct cmd_tbl *cmdtp, int flag, int argc,
>> +                       char *const argv[])
>> +{
>> +    struct mtd_info *mtd;
>> +    size_t retlen;
>> +    off_t from;
>> +    size_t len;
>> +    bool user;
>> +    int ret;
>> +    u8 *buf;
>> +
>> +    if (argc != 5)
>> +            return CMD_RET_USAGE;
>> +
>> +    if (!strcmp(argv[2], "u"))
>> +            user = true;
>> +    else if (!strcmp(argv[2], "f"))
>> +            user = false;
>> +    else
>> +            return CMD_RET_USAGE;
>> +
>> +    mtd = get_mtd_by_name(argv[1]);
>> +    if (IS_ERR_OR_NULL(mtd))
>> +            return CMD_RET_FAILURE;
>> +
>> +    from = simple_strtoul(argv[3], NULL, 0);
>> +    len = simple_strtoul(argv[4], NULL, 0);
>> +
>> +    ret = CMD_RET_FAILURE;
>> +
>> +    buf = malloc(len);
>> +    if (!buf)
>> +            goto put_mtd;
>> +
>> +    printf("Reading %s OTP from 0x%lx, %lu bytes\n",
>> +           user ? "user" : "factory", from, len);
>> +
>> +    if (user)
>> +            ret = mtd_read_user_prot_reg(mtd, from, len, &retlen, buf);
>> +    else
>> +            ret = mtd_read_fact_prot_reg(mtd, from, len, &retlen, buf);
>> +    if (ret) {
>> +            free(buf);
>> +            pr_err("OTP read failed: %d\n", ret);
>> +            ret = CMD_RET_FAILURE;
>> +            goto put_mtd;
>> +    }
>> +
>> +    if (retlen != len)
>> +            pr_err("OTP read returns %zu, but %zu expected\n",
>> +                   retlen, len);
>> +
>> +    print_hex_dump("", 0, 16, 1, buf, retlen, true);
>> +
>> +    free(buf);
>> +
>> +    ret = CMD_RET_SUCCESS;
>> +
>> +put_mtd:
>> +    put_mtd_device(mtd);
>> +
>> +    return ret;
>> +}
>> +
>> +static int do_mtd_otp_lock(struct cmd_tbl *cmdtp, int flag, int argc,
>> +                       char *const argv[])
>> +{
>> +    struct mtd_info *mtd;
>> +    off_t from;
>> +    size_t len;
>> +    int ret;
>> +
>> +    if (argc != 4)
>> +            return CMD_RET_USAGE;
>> +
>> +    mtd = get_mtd_by_name(argv[1]);
>> +    if (IS_ERR_OR_NULL(mtd))
>> +            return CMD_RET_FAILURE;
>> +
>> +    from = simple_strtoul(argv[2], NULL, 0);
>> +    len = simple_strtoul(argv[3], NULL, 0);
>> +
>> +    ret = mtd_lock_user_prot_reg(mtd, from, len);
>> +    if (ret) {
>> +            pr_err("OTP lock failed: %d\n", ret);
>> +            ret = CMD_RET_FAILURE;
>> +            goto put_mtd;
>> +    }
>> +
>> +    ret = CMD_RET_SUCCESS;
>> +
>> +put_mtd:
>> +    put_mtd_device(mtd);
>> +
>> +    return ret;
>> +}
>> +
>> +static int do_mtd_otp_write(struct cmd_tbl *cmdtp, int flag, int argc,
>> +                        char *const argv[])
>> +{
>> +    struct mtd_info *mtd;
>> +    size_t retlen;
>> +    size_t binlen;
>> +    u8 *binbuf;
>> +    off_t from;
>> +    int ret;
>> +
>> +    if (argc != 4)
>> +            return CMD_RET_USAGE;
>> +
>> +    mtd = get_mtd_by_name(argv[1]);
>> +    if (IS_ERR_OR_NULL(mtd))
>> +            return CMD_RET_FAILURE;
>> +
>> +    from = simple_strtoul(argv[2], NULL, 0);
>> +    binlen = strlen(argv[3]) / 2;
>> +
>> +    ret = CMD_RET_FAILURE;
>> +    binbuf = malloc(binlen);
>> +    if (!binbuf)
>> +            goto put_mtd;
>> +
>> +    hex2bin(binbuf, argv[3], binlen);
>> +
>> +    printf("Will write:\n");
>> +
>> +    print_hex_dump("", 0, 16, 1, binbuf, binlen, true);
>> +
>> +    printf("to 0x%zx\n", from);
>> +
>> +    printf("Continue (y/n)?\n");
>> +
>> +    if (confirm_yesno() != 1) {
>> +            pr_err("OTP write canceled\n");
>> +            ret = CMD_RET_SUCCESS;
>> +            goto put_mtd;
>> +    }
>> +
>> +    ret = mtd_write_user_prot_reg(mtd, from, binlen, &retlen, binbuf);
>> +    if (ret) {
>> +            pr_err("OTP write failed: %d\n", ret);
>> +            ret = CMD_RET_FAILURE;
>> +            goto put_mtd;
>> +    }
>> +
>> +    if (retlen != binlen)
>> +            pr_err("OTP write returns %zu, but %zu expected\n",
>> +                   retlen, binlen);
>> +
>> +    ret = CMD_RET_SUCCESS;
>> +
>> +put_mtd:
>> +    free(binbuf);
>> +    put_mtd_device(mtd);
>> +
>> +    return ret;
>> +}
>> +
>> +static int do_mtd_otp_info(struct cmd_tbl *cmdtp, int flag, int argc,
>> +                       char *const argv[])
>> +{
>> +    struct otp_info otp_info;
>> +    struct mtd_info *mtd;
>> +    size_t retlen;
>> +    bool user;
>> +    int ret;
>> +
>> +    if (argc != 3)
>> +            return CMD_RET_USAGE;
>> +
>> +    if (!strcmp(argv[2], "u"))
>> +            user = true;
>> +    else if (!strcmp(argv[2], "f"))
>> +            user = false;
>> +    else
>> +            return CMD_RET_USAGE;
>> +
>> +    mtd = get_mtd_by_name(argv[1]);
>> +    if (IS_ERR_OR_NULL(mtd))
>> +            return CMD_RET_FAILURE;
>> +
>> +    if (user)
>> +            ret = mtd_get_user_prot_info(mtd, sizeof(otp_info), &retlen,
>> +                                         &otp_info);
>> +    else
>> +            ret = mtd_get_fact_prot_info(mtd, sizeof(otp_info), &retlen,
>> +                                         &otp_info);
>> +    if (ret) {
>> +            pr_err("OTP info failed: %d\n", ret);
>> +            ret = CMD_RET_FAILURE;
>> +            goto put_mtd;
>> +    }
>> +
>> +    if (retlen != sizeof(otp_info)) {
>> +            pr_err("OTP info returns %zu, but %zu expected\n",
>> +                   retlen, sizeof(otp_info));
>> +            ret = CMD_RET_FAILURE;
>> +            goto put_mtd;
>> +    }
>> +
>> +    printf("%s OTP region info:\n", user ? "User" : "Factory");
>> +    printf("\tstart: %u\n", otp_info.start);
>> +    printf("\tlength: %u\n", otp_info.length);
>> +    printf("\tlocked: %u\n", otp_info.locked);
>> +
>> +    ret = CMD_RET_SUCCESS;
>> +
>> +put_mtd:
>> +    put_mtd_device(mtd);
>> +
>> +    return ret;
>> +}
>> +
>>  static int do_mtd_list(struct cmd_tbl *cmdtp, int flag, int argc,
>>                     char *const argv[])
>>  {
>> @@ -552,6 +766,10 @@ static char mtd_help_text[] =
>>      "\n"
>>      "Specific functions:\n"
>>      "mtd bad                               <name>\n"
>> +    "mtd otpread                           <name> [u|f] <off> <size>\n"
>> +    "mtd otpwrite                          <name> <off> <hex string>\n"
>> +    "mtd otplock                           <name> <off> <size>\n"
>> +    "mtd otpinfo                           <name> [u|f]\n"
>>      "\n"
>>      "With:\n"
>>      "\t<name>: NAND partition/chip name (or corresponding DM device name or 
>> OF path)\n"
>> @@ -562,11 +780,17 @@ static char mtd_help_text[] =
>>      "\t<size>: length of the operation in bytes (default: the entire 
>> device)\n"
>>      "\t\t* must be a multiple of a block for erase\n"
>>      "\t\t* must be a multiple of a page otherwise (special case: default is 
>> a page with dump)\n"
>> +    "\t<hex string>: hex string without '0x' and spaces. Example: 
>> ABCD1234\n"
>> +    "\t[u|f]: user or factory OTP region\n"
>>      "\n"
>>      "The .dontskipff option forces writing empty pages, don't use it if 
>> unsure.\n";
>>  #endif
>>  
>>  U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils", mtd_help_text,
>> +            U_BOOT_SUBCMD_MKENT(otpread, 5, 1, do_mtd_otp_read),
>> +            U_BOOT_SUBCMD_MKENT(otpwrite, 4, 1, do_mtd_otp_write),
>> +            U_BOOT_SUBCMD_MKENT(otplock, 4, 1, do_mtd_otp_lock),
>> +            U_BOOT_SUBCMD_MKENT(otpinfo, 3, 1, do_mtd_otp_info),
>>              U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mtd_list),
>>              U_BOOT_SUBCMD_MKENT_COMPLETE(read, 5, 0, do_mtd_io,
>>                                           mtd_name_complete),

Reply via email to