[flashrom] [PATCH] Add cli cmds to read/write raw status register values

Niklas Söderlund niklas.soderlund at ericsson.com
Thu Apr 5 11:31:40 CEST 2012


When working with a lot of different flash chips it's sometimes useful
to be able to print and update the status register directly as a separate
operation.

Add --print-status and --write-status command line options to that maps
to spi_read_status_register and spi_write_status_register.

The print operation reads the status register and prints it content to
the user. While the write operation takes a parameter as a hex value
(0x00 to 0xff) or a decimal value (0 to 255) and tries to write it to
the status register.

This operation is limited to flash chips that have a SPI bustype.

Signed-off-by: Niklas Söderlund <niklas.soderlund at ericsson.com>
---
 cli_classic.c |   37 ++++++++++++++++++++++++++++++++-----
 flash.h       |    2 +-
 flashrom.c    |   49 ++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 81 insertions(+), 7 deletions(-)

diff --git a/cli_classic.c b/cli_classic.c
index 972043b..87af1f3 100644
--- a/cli_classic.c
+++ b/cli_classic.c
@@ -144,11 +144,17 @@ static void cli_classic_usage(const char *name)
 	         "device\n");
 
 	list_programmers_linebreak(37, 80, 1);
+
+	printf("\nAdvance options (use at your own risk)\n"
+	       "   -P | --print-status               print status register\n"
+	       "   -W | --write-status <value>       write <value> to status "
+	       "register\n");
+
 	printf("\nYou can specify one of -h, -R, -L, "
 #if CONFIG_PRINT_WIKI == 1
 	         "-z, "
 #endif
-	         "-E, -r, -w, -v or no operation.\n"
+	         "-E, -r, -w, -v -P, -W or no operation.\n"
 	       "If no operation is specified, flashrom will only probe for "
 	         "flash chips.\n\n");
 }
@@ -173,15 +179,18 @@ int main(int argc, char *argv[])
 	int list_supported_wiki = 0;
 #endif
 	int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0;
+	int statusreg_op = 0;
 	int dont_verify_it = 0, list_supported = 0, operation_specified = 0;
 	enum programmer prog = PROGRAMMER_INVALID;
 	int ret = 0;
 
-	static const char optstring[] = "r:Rw:v:nVEfc:l:i:p:Lzh";
+	static const char optstring[] = "r:Rw:v:nVEfc:l:i:p:LzhPW:";
 	static const struct option long_options[] = {
 		{"read",		1, NULL, 'r'},
 		{"write",		1, NULL, 'w'},
 		{"erase",		0, NULL, 'E'},
+		{"print-status",	0, NULL, 'P'},
+		{"write-status",	1, NULL, 'W'},
 		{"verify",		1, NULL, 'v'},
 		{"noverify",		0, NULL, 'n'},
 		{"chip",		1, NULL, 'c'},
@@ -201,6 +210,7 @@ int main(int argc, char *argv[])
 	char *layoutfile = NULL;
 	char *tempstr = NULL;
 	char *pparam = NULL;
+	char *statusreg_value = NULL;
 
 	print_version();
 	print_banner();
@@ -270,6 +280,23 @@ int main(int argc, char *argv[])
 			}
 			erase_it = 1;
 			break;
+		case 'P':
+			if (++operation_specified > 1) {
+				fprintf(stderr, "More than one operation "
+					"specified. Aborting.\n");
+				cli_classic_abort_usage();
+			}
+			statusreg_op = 1;
+			break;
+		case 'W':
+			if (++operation_specified > 1) {
+				fprintf(stderr, "More than one operation "
+					"specified. Aborting.\n");
+				cli_classic_abort_usage();
+			}
+			statusreg_op = 1;
+			statusreg_value = strdup(optarg);
+			break;
 		case 'f':
 			force = 1;
 			break;
@@ -511,12 +538,12 @@ int main(int argc, char *argv[])
 		goto out_shutdown;
 	}
 
-	if (!(read_it | write_it | verify_it | erase_it)) {
+	if (!(read_it | write_it | verify_it | erase_it | statusreg_op)) {
 		printf("No operations were specified.\n");
 		goto out_shutdown;
 	}
 
-	if (!filename && !erase_it) {
+	if (!filename && !erase_it && !statusreg_op) {
 		printf("Error: No filename specified.\n");
 		ret = 1;
 		goto out_shutdown;
@@ -531,7 +558,7 @@ int main(int argc, char *argv[])
 	 * Give the chip time to settle.
 	 */
 	programmer_delay(100000);
-	return doit(fill_flash, force, filename, read_it, write_it, erase_it, verify_it);
+	return doit(fill_flash, force, filename, read_it, write_it, erase_it, verify_it, statusreg_op, statusreg_value);
 
 out_shutdown:
 	programmer_shutdown();
diff --git a/flash.h b/flash.h
index 0dac13d..65ee0af 100644
--- a/flash.h
+++ b/flash.h
@@ -247,7 +247,7 @@ void print_version(void);
 void print_banner(void);
 void list_programmers_linebreak(int startcol, int cols, int paren);
 int selfcheck(void);
-int doit(struct flashctx *flash, int force, const char *filename, int read_it, int write_it, int erase_it, int verify_it);
+int doit(struct flashctx *flash, int force, const char *filename, int read_it, int write_it, int erase_it, int verify_it, int statureg_op, const char *statusreg_op);
 int read_buf_from_file(unsigned char *buf, unsigned long size, const char *filename);
 int write_buf_to_file(unsigned char *buf, unsigned long size, const char *filename);
 
diff --git a/flashrom.c b/flashrom.c
index cad043b..b3ba376 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -31,12 +31,14 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <getopt.h>
+#include <errno.h>
 #if HAVE_UTSNAME == 1
 #include <sys/utsname.h>
 #endif
 #include "flash.h"
 #include "flashchips.h"
 #include "programmer.h"
+#include "chipdrivers.h"
 
 const char flashrom_version[] = FLASHROM_VERSION;
 char *chip_to_probe = NULL;
@@ -1396,6 +1398,45 @@ int erase_and_write_flash(struct flashctx *flash, uint8_t *oldcontents,
 	return ret;
 }
 
+int operate_on_statusregister(struct flashctx *flash, const char* value) {
+	long status;
+	char *endptr;
+
+	if (flash->bustype != BUS_SPI) {
+		msg_cerr("Flash is not on SPI bus. Can't operate on status register\n");
+		return 1;
+	}
+
+	if (value) {
+		/* Try to parse as hex then dec */
+		errno = 0;
+		status = strtol(value, &endptr, 0);
+		if (endptr == value || *endptr != '\0' || errno != 0) {
+			msg_cerr("Error parsing value %s for status register\n",
+					value);
+			return 1;
+		}
+
+		if (status < 0 || status > 0xFF) {
+			msg_cerr("Invalid status register value: %s\n", value);
+			return 1;
+		}
+
+		if (spi_write_status_register(flash, status)) {
+			msg_cerr("spi_write_status_register failed\n");
+			return 1;
+		}
+
+		msg_cinfo("Wrote 0x%02lx to status register\n", status);
+	}
+
+	/* Read and print current value */
+	status = spi_read_status_register(flash);
+	msg_cinfo("Status register: 0x%02lx\n", status);
+
+	return 0;
+}
+
 void nonfatal_help_message(void)
 {
 	msg_gerr("Writing to the flash chip apparently didn't do anything.\n"
@@ -1705,7 +1746,8 @@ int chip_safety_check(struct flashctx *flash, int force, int read_it,
  * Besides that, the function itself is a textbook example of abysmal code flow.
  */
 int doit(struct flashctx *flash, int force, const char *filename, int read_it,
-	 int write_it, int erase_it, int verify_it)
+	 int write_it, int erase_it, int verify_it,
+	 int statusreg_op, const char *statusreg_value)
 {
 	uint8_t *oldcontents;
 	uint8_t *newcontents;
@@ -1718,6 +1760,11 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it,
 		goto out_nofree;
 	}
 
+	if (statusreg_op) {
+		ret = operate_on_statusregister(flash, statusreg_value);
+		goto out_nofree;
+	}
+
 	/* Given the existence of read locks, we want to unlock for read,
 	 * erase and write.
 	 */
-- 
1.7.7





More information about the flashrom mailing list