Re: [PATCH v5] cmd: mtd: OTP access support

2024-04-14 Thread Dario Binacchi
Hi Arseniy,

On Tue, Mar 26, 2024 at 11:49 PM Arseniy Krasnov
 wrote:
>
> Add access to OTP region. It supports info, dump, write and lock
> operations. Usage example:
>
> 'mtd otpread nand0 u 0 1024' - dump 1024 bytes of user area starting
>  from offset 0 of device 'nand0'.
>
> 'mtd otpwrite nand0 10 11223344' - write binary data 0x11, 0x22, 0x33,
>  0x44 to offset 10 to user area of device 'nand0'.
>
> 'mtd otplock nand0 0 1024' - lock 1024 bytes of user area starting
>  from offset 0 of device 'nand0'.
>
> 'mtd otpinfo nand0 f' - show info about factory area of device 'nand0'.
>
> Signed-off-by: Arseniy Krasnov 
> ---
>  Changelog:
>  v1 -> v2:
>   * Remove warning that OTP can't be erased after write.
>  v2 -> v3:
>   * Commit message updated by adding usage.
>   * R-b added.
>  v3 -> v4:
>   * Fix build failure due to invalid format strings for 'printf()'.
>   * Rebase over latest version of cmd/mtd.c.
>  v4 -> v5:
>   * Implement commands from this patch as config option due to too big
> final size of the uboot image.
>   * R-b removed because of patch update.
>
>  cmd/Kconfig |   7 ++
>  cmd/mtd.c   | 234 
>  2 files changed, 241 insertions(+)
>
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 7292a150f5..832098e66e 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -1366,6 +1366,13 @@ config CMD_MTD
> help
>   MTD commands support.
>
> +config CMD_MTD_OTP
> +   bool "mtd otp"
> +   depends on CMD_MTD
> +   select HEXDUMP
> +   help
> + MTD commands for OTP access.
> +
>  config CMD_MUX
> bool "mux"
> depends on MULTIPLEXER
> diff --git a/cmd/mtd.c b/cmd/mtd.c
> index e63c011e79..c66105e373 100644
> --- a/cmd/mtd.c
> +++ b/cmd/mtd.c
> @@ -11,6 +11,9 @@
>  #include 
>  #include 
>  #include 
> +#if CONFIG_IS_ENABLED(CMD_MTD_OTP)
> +#include 
> +#endif
>  #include 
>  #include 
>  #include 
> @@ -202,6 +205,221 @@ static bool mtd_oob_write_is_empty(struct mtd_oob_ops 
> *op)
> return true;
>  }
>
> +#if CONFIG_IS_ENABLED(CMD_MTD_OTP)
> +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, %zu bytes\n",
> +  user ? "user" : "factory", from, len);
> +
> +   if (user)
> +   ret = mtd_read_user_prot_reg(mtd, from, len, , buf);
> +   else
> +   ret = mtd_read_fact_prot_reg(mtd, from, len, , 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 

[PATCH v5] cmd: mtd: OTP access support

2024-03-26 Thread Arseniy Krasnov
Add access to OTP region. It supports info, dump, write and lock
operations. Usage example:

'mtd otpread nand0 u 0 1024' - dump 1024 bytes of user area starting
 from offset 0 of device 'nand0'.

'mtd otpwrite nand0 10 11223344' - write binary data 0x11, 0x22, 0x33,
 0x44 to offset 10 to user area of device 'nand0'.

'mtd otplock nand0 0 1024' - lock 1024 bytes of user area starting
 from offset 0 of device 'nand0'.

'mtd otpinfo nand0 f' - show info about factory area of device 'nand0'.

Signed-off-by: Arseniy Krasnov 
---
 Changelog:
 v1 -> v2:
  * Remove warning that OTP can't be erased after write.
 v2 -> v3:
  * Commit message updated by adding usage.
  * R-b added.
 v3 -> v4:
  * Fix build failure due to invalid format strings for 'printf()'.
  * Rebase over latest version of cmd/mtd.c.
 v4 -> v5:
  * Implement commands from this patch as config option due to too big
final size of the uboot image.
  * R-b removed because of patch update.

 cmd/Kconfig |   7 ++
 cmd/mtd.c   | 234 
 2 files changed, 241 insertions(+)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 7292a150f5..832098e66e 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1366,6 +1366,13 @@ config CMD_MTD
help
  MTD commands support.
 
+config CMD_MTD_OTP
+   bool "mtd otp"
+   depends on CMD_MTD
+   select HEXDUMP
+   help
+ MTD commands for OTP access.
+
 config CMD_MUX
bool "mux"
depends on MULTIPLEXER
diff --git a/cmd/mtd.c b/cmd/mtd.c
index e63c011e79..c66105e373 100644
--- a/cmd/mtd.c
+++ b/cmd/mtd.c
@@ -11,6 +11,9 @@
 #include 
 #include 
 #include 
+#if CONFIG_IS_ENABLED(CMD_MTD_OTP)
+#include 
+#endif
 #include 
 #include 
 #include 
@@ -202,6 +205,221 @@ static bool mtd_oob_write_is_empty(struct mtd_oob_ops *op)
return true;
 }
 
+#if CONFIG_IS_ENABLED(CMD_MTD_OTP)
+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, %zu bytes\n",
+  user ? "user" : "factory", from, len);
+
+   if (user)
+   ret = mtd_read_user_prot_reg(mtd, from, len, , buf);
+   else
+   ret = mtd_read_fact_prot_reg(mtd, from, len, , 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);
+
+