[PATCH] mtd-utils: Add flash_otp_erase

Michael Walle michael at walle.cc
Mon May 10 13:13:19 PDT 2021


On some SPI NOR flashes you can actually erase the OTP region until its
fully locked. Add a small utility for that.

Signed-off-by: Michael Walle <michael at walle.cc>
---
The ioctl was merged in linux commit e3c1f1c92d6e ("mtd: add OTP
(one-time-programmable) erase ioctl").

 .gitignore                   |  1 +
 include/mtd/mtd-abi.h        |  2 ++
 misc-utils/Makemodule.am     |  4 ++-
 misc-utils/flash_otp_erase.c | 64 ++++++++++++++++++++++++++++++++++++
 4 files changed, 70 insertions(+), 1 deletion(-)
 create mode 100644 misc-utils/flash_otp_erase.c

diff --git a/.gitignore b/.gitignore
index 4c04c1a..1644ef0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,7 @@ fectest
 flash_erase
 flash_lock
 flash_otp_dump
+flash_otp_erase
 flash_otp_info
 flash_otp_lock
 flash_otp_write
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index bcd7496..a54c386 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -201,6 +201,8 @@ struct otp_info {
  * modes (see "struct mtd_write_req")
  */
 #define MEMWRITE		_IOWR('M', 24, struct mtd_write_req)
+/* Erase a given range of user data (must be in mode %MTD_FILE_MODE_OTP_USER) */
+#define OTPERASE		_IOW('M', 25, struct otp_info)
 
 /*
  * Obsolete legacy interface. Keep it in order not to break userspace
diff --git a/misc-utils/Makemodule.am b/misc-utils/Makemodule.am
index b15c119..bc69b1c 100644
--- a/misc-utils/Makemodule.am
+++ b/misc-utils/Makemodule.am
@@ -32,6 +32,8 @@ flash_otp_dump_SOURCES = misc-utils/flash_otp_dump.c
 
 flash_otp_lock_SOURCES = misc-utils/flash_otp_lock.c
 
+flash_otp_erase_SOURCES = misc-utils/flash_otp_erase.c
+
 flash_otp_write_SOURCES = misc-utils/flash_otp_write.c
 
 flashcp_SOURCES = misc-utils/flashcp.c
@@ -43,7 +45,7 @@ sbin_PROGRAMS += \
 	ftl_format doc_loadbios ftl_check mtd_debug docfdisk \
 	serve_image recv_image fectest flash_erase flash_lock \
 	flash_unlock flash_otp_info flash_otp_dump flash_otp_lock \
-	flash_otp_write flashcp mtdpart
+	flash_otp_erase flash_otp_write flashcp mtdpart
 
 MISC_SH = \
 	misc-utils/flash_eraseall
diff --git a/misc-utils/flash_otp_erase.c b/misc-utils/flash_otp_erase.c
new file mode 100644
index 0000000..771e230
--- /dev/null
+++ b/misc-utils/flash_otp_erase.c
@@ -0,0 +1,64 @@
+/*
+ * flash_otp_erase.c -- erase area of One-Time-Program data
+ */
+
+#define PROGRAM_NAME "flash_otp_erase"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#include <mtd/mtd-user.h>
+#include "common.h"
+
+int main(int argc,char *argv[])
+{
+	int fd, val, ret, offset, size;
+	struct otp_info info;
+	char *p;
+
+	if (argc != 5 || strcmp(argv[1], "-u")) {
+		fprintf(stderr, "Usage: %s -u <device> <offset> <size>\n", PROGRAM_NAME);
+		fprintf(stderr, "offset and size must match on OTP region boundaries\n");
+		return EINVAL;
+	}
+
+	fd = open(argv[2], O_WRONLY);
+	if (fd < 0) {
+		perror(argv[2]);
+		return errno;
+	}
+
+	val = MTD_OTP_USER;
+	ret = ioctl(fd, OTPSELECT, &val);
+	if (ret < 0) {
+		perror("OTPSELECT");
+		return errno;
+	}
+
+	offset = strtoul(argv[3], &p, 0);
+	if (argv[3][0] == 0 || *p != 0) {
+		fprintf(stderr, "%s: bad offset value\n", PROGRAM_NAME);
+		return ERANGE;
+	}
+
+	size = strtoul(argv[4], &p, 0);
+	if (argv[4][0] == 0 || *p != 0) {
+		fprintf(stderr, "%s: bad size value\n", PROGRAM_NAME);
+		return ERANGE;
+	}
+
+	info.start = offset;
+	info.length = size;
+	ret = ioctl(fd, OTPERASE, &info);
+	if (ret	< 0) {
+		perror("OTPERASE");
+		return errno;
+	}
+
+	return 0;
+}
-- 
2.20.1




More information about the linux-mtd mailing list