From patchwork Tue Jul 5 20:28:05 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hatim Kanchwala X-Patchwork-Id: 644999 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail.coreboot.org (mail.coreboot.org [80.81.252.135]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3rkb971Nggz9sDb for ; Wed, 6 Jul 2016 06:30:03 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=hatimak-me.20150623.gappssmtp.com header.i=@hatimak-me.20150623.gappssmtp.com header.b=QSLRud8L; dkim-atps=neutral Received: from [127.0.0.1] (helo=ra.coresystems.de) by mail.coreboot.org with esmtp (Exim 4.86_2) (envelope-from ) id 1bKWxe-0007iC-SF; Tue, 05 Jul 2016 22:28:50 +0200 Received: from mail-pa0-f67.google.com ([209.85.220.67]) by mail.coreboot.org with esmtps (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.86_2) (envelope-from ) id 1bKWxK-0007e8-TQ for flashrom@flashrom.org; Tue, 05 Jul 2016 22:28:48 +0200 Received: by mail-pa0-f67.google.com with SMTP id dx3so2554338pab.2 for ; Tue, 05 Jul 2016 13:28:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hatimak-me.20150623.gappssmtp.com; s=20150623; h=from:to:subject:date:message-id:in-reply-to:references; bh=OztLlZZtCgbRotkFFwqCu5hli2LlbZI1e9uy8xWTypw=; b=QSLRud8L6zTM7kvkbNws9UGUMqGbGv/O7+QZtHpu8e/S6cm6+wF7gfPXjpA6Q3aa/x gWL71YpbOpM3uPZEFw+8HmEy1w1NEZvtfI2QO9mUfgvODJipxy7W9dB/ydTvVuCmVzXa N4eGj2mKCLkWyux0061P7mzsBqtKzU7JgclkbWrFKUpKKjJftG+vW3wURS3gUBJTotox D80SzWDlwKriaKRFYytCzVZOTHcCMT+kAVeVWP3wgZEJGEA6G8K24rFPILZ5J/QL7FNV rOcM3FGHLU3luc70wWoBYEPJqKQiLw9QEmbOlmCjHWi4E6BsYFxoBqUKc1iei3qSdLBS FoXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=OztLlZZtCgbRotkFFwqCu5hli2LlbZI1e9uy8xWTypw=; b=TAHFeK54nyWwsX1Dwsebb7tu8jCXaSWYLcXndDgkrxjIxKgKVu1MXUBhIysrOKGhe/ 5sgfppbyTxwUqhIZKLkbxK0V8oXvwclyHVZoK6j1ZYUASPJ5cvV13GCU76xBswnPsWWC 0m2yDb9guG7ONvAUclKqWYT5T+kZQYyU35SPb5en08GbRp6z2frbjPAdock4RfxSbf3+ 5BfDcxEIVqAdqU2Ww16tJK/USjMISXLlGDH53QwmUWfoulT5nby0rEIFv9GxKNDCfZnz vbaeMlVy/bkJiF+hxL2fWHMgKG7pPTmZ7F5h2HNP60ChEgFbz0Krlv36p4/fflDFb1OY U4kw== X-Gm-Message-State: ALyK8tKXU9fQaXwqARwloI5jdGo+nDkga41ljS5qSZ0OVGCxMe27Ofct0qrxJKUpS/dQtQ== X-Received: by 10.66.51.137 with SMTP id k9mr14599716pao.49.1467750507874; Tue, 05 Jul 2016 13:28:27 -0700 (PDT) Received: from ubuntu-lenovo-z580.domain.name ([103.240.193.150]) by smtp.gmail.com with ESMTPSA id f10sm7219958pfc.79.2016.07.05.13.28.26 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 05 Jul 2016 13:28:27 -0700 (PDT) From: Hatim Kanchwala To: flashrom@flashrom.org Date: Wed, 6 Jul 2016 01:58:05 +0530 Message-Id: <1467750485-29158-7-git-send-email-hatim@hatimak.me> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1467750485-29158-1-git-send-email-hatim@hatimak.me> References: <1467750485-29158-1-git-send-email-hatim@hatimak.me> X-Spam-Score: 7.0 (+++++++) X-Spam-Report: Spam detection software, running on the system "ra.coresystems.de", has identified this incoming email as possible spam. The original message has been attached to this so you can view it (if it isn't spam) or label similar future email. If you have any questions, see info@coresystems.de for details. Content analysis details: (7.0 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 3.5 URIBL_BLOCKED ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [URIs: hatimak.me] 1.9 RCVD_IN_CHILE RBL: Listed at dnsblchile [103.240.193.150 listed in dnsblchile.org] 1.9 RCVD_IN_BS_SPAM RBL: BACKSCATTERER: sender is a spam source [209.85.220.67 listed in ips.backscatterer.org] 1.9 RCVD_IN_UCEPROTECT2 RBL: Network listed in dnsbl-2.uceprotect.net [Net 103.240.192.0/22 is UCEPROTECT-Level2 listed] [because 42 abusers are hosted by /AS132453] [there. See: ] 1.9 RCVD_IN_MCAFEE RBL: Listed at cidr.bl.mcafee.com [Net 103.240.193.0/24 is UCEPROTECT-Level2 listed] [because 7 abusers are hosted by /AS132453 there.] [See: ] [103.240.193.150 listed in cidr.bl.mcafee.com] 1.9 RCVD_IN_APEWS RBL: Listed at APEWS [103.240.193.150 listed in l2.apews.org] -6.0 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-Spam-Flag: YES Subject: [flashrom] [PATCH 6/6] Add command-line interface to expose new infrastructure X-BeenThere: flashrom@flashrom.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: flashrom discussion and development mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: flashrom-bounces@flashrom.org Sender: "flashrom" X-Duff: Orig. Duff, Duff Lite, Duff Dry, Duff Dark, Raspberry Duff, Lady Duff, Red Duff, Tartar Control Duff - Following new CLI options added - - print-status-reg : print detailed contents of status register(s) - print-wp-status : print write protection mode of status register(s) - wp-list : print list of write protection ranges - wp-enable : enable write protection of status register(s) to optionally supplied MODE argument - wp-disable : disable any write protection of status register(s) - wp-set-range : set write protection range to supplied range - Updated man page with new CLI options Signed-off-by: Hatim Kanchwala --- cli_classic.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- flashrom.8.tmpl | 56 +++++++++++++++- 2 files changed, 250 insertions(+), 6 deletions(-) diff --git a/cli_classic.c b/cli_classic.c index a2c2014..1170d33 100644 --- a/cli_classic.c +++ b/cli_classic.c @@ -17,133 +17,172 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include +#include "chipdrivers.h" #include "flash.h" #include "flashchips.h" #include "programmer.h" +#include "writeprotect.h" + +enum LONGOPT_RETURN_VALUES { + /* Start after ASCII chars */ + LONGOPT_PRINT_STATUSREG = 256, + LONGOPT_PRINT_WP_STATUS, + LONGOPT_LIST_BP_RANGES, + LONGOPT_WP_ENABLE, + LONGOPT_WP_DISABLE, + LONGOPT_SET_BP_RANGE, +}; static void cli_classic_usage(const char *name) { printf("Please note that the command line interface for flashrom has changed between\n" "0.9.5 and 0.9.6 and will change again before flashrom 1.0.\n\n"); printf("Usage: %s [-h|-R|-L|" #if CONFIG_PRINT_WIKI == 1 "-z|" #endif "-p [:] [-c ]\n" "[-E|(-r|-w|-v) ] [-l [-i ]...] [-n] [-f]]\n" - "[-V[V[V]]] [-o ]\n\n", name); + "[-V[V[V]]] [-o ] [--print-status-reg] [--print-wp-status]\n" + "[--wp-list] [--wp-enable[=]] [--wp-disable]\n" + "[--wp-set-range start=,len=]\n\n", name); printf(" -h | --help print this help text\n" " -R | --version print version (release)\n" " -r | --read read flash and save to \n" " -w | --write write to flash\n" " -v | --verify verify flash against \n" " -E | --erase erase flash memory\n" " -V | --verbose more verbose output\n" " -c | --chip probe only for specified flash chip\n" " -f | --force force specific operations (see man page)\n" " -n | --noverify don't auto-verify\n" " -l | --layout read ROM layout from \n" " -i | --image only flash image from flash layout\n" " -o | --output log output to \n" " -L | --list-supported print supported devices\n" #if CONFIG_PRINT_WIKI == 1 " -z | --list-supported-wiki print supported devices in wiki syntax\n" #endif + " --print-status-reg print detailed contents of status register(s)\n" + " --print-wp-status print write protection mode of status register(s)\n" + " --wp-list print list of write protection ranges\n" + " --wp-enable[=MODE] enable write protection of status register(s)\n" + " MODE can be one of HARDWARE (default),\n" + " PERMANENT, POWER_CYCLE, SOFTWARE (see man page)\n" + " --wp-disable disable any write protection of status register(s)\n" + " --wp-set-range start=,len=\n" + " set write protection range (see man page)\n" " -p | --programmer [:] specify the programmer device. One of\n"); list_programmers_linebreak(4, 80, 0); printf(".\n\nYou can specify one of -h, -R, -L, " #if CONFIG_PRINT_WIKI == 1 "-z, " #endif "-E, -r, -w, -v or no operation.\n" "If no operation is specified, flashrom will only probe for flash chips.\n"); } static void cli_classic_abort_usage(void) { printf("Please run \"flashrom --help\" for usage info.\n"); exit(1); } +static void cli_statreg_wp_support(struct flashctx *flash) +{ + msg_ginfo("flashrom does not (yet) support write protection for chip \"%s\".\n" + "You could add support and send the patch to flashrom@flashrom.org\n", + flash->chip->name); +} + static int check_filename(char *filename, char *type) { if (!filename || (filename[0] == '\0')) { fprintf(stderr, "Error: No %s file specified.\n", type); return 1; } /* Not an error, but maybe the user intended to specify a CLI option instead of a file name. */ if (filename[0] == '-') fprintf(stderr, "Warning: Supplied %s file name starts with -\n", type); return 0; } int main(int argc, char *argv[]) { const struct flashchip *chip = NULL; /* Probe for up to eight flash chips. */ struct flashctx flashes[8] = {{0}}; struct flashctx *fill_flash; const char *name; int namelen, opt, i, j; int startchip = -1, chipcount = 0, option_index = 0, force = 0; #if CONFIG_PRINT_WIKI == 1 int list_supported_wiki = 0; #endif - int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0; + int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0, print_status_reg = 0; + int print_wp_status = 0, wp_list = 0, wp_enable = 0, wp_disable = 0, wp_set_range = 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:Lzho:"; static const struct option long_options[] = { {"read", 1, NULL, 'r'}, {"write", 1, NULL, 'w'}, {"erase", 0, NULL, 'E'}, {"verify", 1, NULL, 'v'}, {"noverify", 0, NULL, 'n'}, {"chip", 1, NULL, 'c'}, {"verbose", 0, NULL, 'V'}, {"force", 0, NULL, 'f'}, {"layout", 1, NULL, 'l'}, {"image", 1, NULL, 'i'}, {"list-supported", 0, NULL, 'L'}, {"list-supported-wiki", 0, NULL, 'z'}, {"programmer", 1, NULL, 'p'}, {"help", 0, NULL, 'h'}, {"version", 0, NULL, 'R'}, {"output", 1, NULL, 'o'}, + {"print-status-reg", 0, NULL, LONGOPT_PRINT_STATUSREG}, + {"print-wp-status", 0, NULL, LONGOPT_PRINT_WP_STATUS}, + {"wp-list", 0, NULL, LONGOPT_LIST_BP_RANGES}, + {"wp-enable", optional_argument, NULL, LONGOPT_WP_ENABLE}, + {"wp-disable", 0, NULL, LONGOPT_WP_DISABLE}, + {"wp-set-range", 1, NULL, LONGOPT_SET_BP_RANGE}, {NULL, 0, NULL, 0}, }; char *filename = NULL; char *layoutfile = NULL; #ifndef STANDALONE char *logfile = NULL; #endif /* !STANDALONE */ char *tempstr = NULL; char *pparam = NULL; + char *wp_mode_opt = NULL; + char const *wp_set_range_opt = NULL; print_version(); print_banner(); if (selfcheck()) exit(1); setbuf(stdout, NULL); /* FIXME: Delay all operation_specified checks until after command * line parsing to allow --help overriding everything else. */ while ((opt = getopt_long(argc, argv, optstring, long_options, &option_index)) != EOF) { @@ -305,26 +344,81 @@ int main(int argc, char *argv[]) break; case 'o': #ifdef STANDALONE fprintf(stderr, "Log file not supported in standalone mode. Aborting.\n"); cli_classic_abort_usage(); #else /* STANDALONE */ logfile = strdup(optarg); if (logfile[0] == '\0') { fprintf(stderr, "No log filename specified.\n"); cli_classic_abort_usage(); } #endif /* STANDALONE */ break; + /* FIXME(hatim): For the following long options, not _all_ + * of them are mutually exclusive per se (like wp_set_range + * and wp_enable makes sense). There is scope for improvement + * here, but for now let's treat each one as separate operation. */ + case LONGOPT_PRINT_STATUSREG: + if (++operation_specified > 1) { + fprintf(stderr, "More than one operation " + "specified. Aborting.\n"); + cli_classic_abort_usage(); + } + print_status_reg = 1; + break; + case LONGOPT_PRINT_WP_STATUS: + if (++operation_specified > 1) { + fprintf(stderr, "More than one operation " + "specified. Aborting.\n"); + cli_classic_abort_usage(); + } + print_wp_status = 1; + break; + case LONGOPT_LIST_BP_RANGES: + if (++operation_specified > 1) { + fprintf(stderr, "More than one operation " + "specified. Aborting.\n"); + cli_classic_abort_usage(); + } + wp_list = 1; + break; + case LONGOPT_WP_ENABLE: + if (++operation_specified > 1) { + fprintf(stderr, "More than one operation " + "specified. Aborting.\n"); + cli_classic_abort_usage(); + } + wp_enable = 1; + if (optarg) + wp_mode_opt = strdup(optarg); + break; + case LONGOPT_WP_DISABLE: + if (++operation_specified > 1) { + fprintf(stderr, "More than one operation " + "specified. Aborting.\n"); + cli_classic_abort_usage(); + } + wp_disable = 1; + break; + case LONGOPT_SET_BP_RANGE: + if (++operation_specified > 1) { + fprintf(stderr, "More than one operation " + "specified. Aborting.\n"); + cli_classic_abort_usage(); + } + wp_set_range_opt = strdup(optarg); + wp_set_range = 1; + break; default: cli_classic_abort_usage(); break; } } if (optind < argc) { fprintf(stderr, "Error: Extra parameter found.\n"); cli_classic_abort_usage(); } if ((read_it | write_it | verify_it) && check_filename(filename, "image")) { cli_classic_abort_usage(); @@ -512,41 +606,141 @@ int main(int argc, char *argv[]) /* Sometimes chip and programmer have more than one bus in common, * and the limit is not exceeded on all buses. Tell the user. */ if ((bitcount(commonbuses) > limitexceeded)) { msg_pdbg("There is at least one interface available which could support the size of\n" "the selected flash chip.\n"); } msg_cerr("This flash chip is too big for this programmer (--verbose/-V gives details).\n" "Use --force/-f to override at your own risk.\n"); ret = 1; goto out_shutdown; } - if (!(read_it | write_it | verify_it | erase_it)) { + if (!(read_it | write_it | verify_it | erase_it | print_status_reg | + print_wp_status | wp_list | wp_enable | wp_disable | wp_set_range)) { msg_ginfo("No operations were specified.\n"); goto out_shutdown; } /* Always verify write operations unless -n is used. */ if (write_it && !dont_verify_it) verify_it = 1; /* Map the selected flash chip again. */ if (map_flash(fill_flash) != 0) { ret = 1; goto out_shutdown; } + if (print_status_reg) { + verbose_screen++; + if (fill_flash->chip->status_register) { + for (enum status_register_num SRn = SR1; SRn <= top_status_register(fill_flash); SRn++) + fill_flash->chip->status_register->print(fill_flash, SRn); + fill_flash->chip->status_register->print_wp_mode(fill_flash); + if (fill_flash->chip->wp) + print_range_generic(fill_flash); + } else + cli_statreg_wp_support(fill_flash); + goto out_shutdown; + } + + if (print_wp_status) { + verbose_screen++; + if (fill_flash->chip->status_register || fill_flash->chip->wp) { + msg_ginfo("WP status -\n"); + fill_flash->chip->status_register->print_wp_mode(fill_flash); + if (fill_flash->chip->wp) + print_range_generic(fill_flash); + } else + cli_statreg_wp_support(fill_flash); + goto out_shutdown; + } + + if (wp_list) { + verbose_screen++; + if (fill_flash->chip->wp) { + msg_ginfo("Valid write protection ranges for chip \"%s\" are -\n", + fill_flash->chip->name); + fill_flash->chip->wp->print_table(fill_flash); + } else + cli_statreg_wp_support(fill_flash); + goto out_shutdown; + } + + if (wp_disable) { + verbose_screen++; + if (fill_flash->chip->wp) { + ret = fill_flash->chip->wp->disable(fill_flash); + } else + cli_statreg_wp_support(fill_flash); + goto out_shutdown; + } + + if (wp_set_range) { + verbose_screen++; + if (fill_flash->chip->wp) { + char *endptr = NULL; + uint8_t start_cmp, end_cmp, has_cmp = pos_bit(fill_flash, CMP) != -1; + if (has_cmp) + start_cmp = get_cmp(fill_flash); + /* FIXME(hatim): Implement error checking */ + uint32_t start = strtoul(extract_param(&wp_set_range_opt, "start", ","), &endptr, 0); + uint32_t len = strtoul(extract_param(&wp_set_range_opt, "len", ","), &endptr, 0); + msg_ginfo("Trying to protect %d kB starting from address 0x%06x...\n", len, start); + ret = fill_flash->chip->wp->set_range(fill_flash, start, len); + if (has_cmp && start_cmp != (end_cmp = get_cmp(fill_flash))) + msg_ginfo("CMP bit was %sset\n", end_cmp ? "" : "un"); + if (ret) + msg_gerr("Failed to protect\n"); + else + msg_ginfo("Protection successful!\n"); + } else + cli_statreg_wp_support(fill_flash); + goto out_shutdown; + } + + if (wp_enable) { + verbose_screen++; + if (fill_flash->chip->status_register) { + enum wp_mode wp_mode = WP_MODE_HARDWARE_UNPROTECTED; + + if (wp_mode_opt) { + if (!strcasecmp(wp_mode_opt, "PERMANENT")) { + wp_mode = WP_MODE_PERMANENT; + } else if (!strcasecmp(wp_mode_opt, "POWER_CYCLE")) { + wp_mode = WP_MODE_POWER_CYCLE; + } else if (!strcasecmp(wp_mode_opt, "SOFTWARE")) { + wp_mode = WP_MODE_SOFTWARE; + } else if (!strcasecmp(wp_mode_opt, "HARDWARE")) { + wp_mode = WP_MODE_HARDWARE_UNPROTECTED; + } else { + msg_gerr("Invalid write protection mode for status register(s)\n"); + cli_classic_abort_usage(); + ret = 1; + goto out_shutdown; + } + } + msg_ginfo("Setting write protection mode to %s ...\n", + wp_mode_opt ? wp_mode_opt : "HARDWARE"); + fill_flash->chip->status_register->set_wp_mode(fill_flash, wp_mode); + ret = !(wp_mode == fill_flash->chip->status_register->get_wp_mode(fill_flash)); + msg_gerr("%s\n", ret ? "Failed" : "Success"); + } else + cli_statreg_wp_support(fill_flash); + goto out_shutdown; + } + /* FIXME: We should issue an unconditional chip reset here. This can be * done once we have a .reset function in struct flashchip. * Give the chip time to settle. */ programmer_delay(100000); ret |= doit(fill_flash, force, filename, read_it, write_it, erase_it, verify_it); unmap_flash(fill_flash); out_shutdown: programmer_shutdown(); out: for (i = 0; i < chipcount; i++) free(flashes[i].chip); diff --git a/flashrom.8.tmpl b/flashrom.8.tmpl index 34e1fe7..d068ad9 100644 --- a/flashrom.8.tmpl +++ b/flashrom.8.tmpl @@ -30,36 +30,39 @@ .de MTOB . ie (\n[groffhtml]==1) \{\ . MTO \\$@ . \} . el \{\ . ie "\\$2"" \{\ . BR "\\$1" "\\$3" . \} . el \{\ . RB "\\$2 \(la" "\\$1" "\(ra\\$3" . \} . \} .. -.TH FLASHROM 8 "" "" +.TH FLASHROM 8 "2016-03-13" "0.9.9-unknown" .SH NAME flashrom \- detect, read, write, verify and erase flash chips .SH SYNOPSIS .B flashrom \fR[\fB\-h\fR|\fB\-R\fR|\fB\-L\fR|\fB\-z\fR|\ \fB\-p\fR [:] - [\fB\-E\fR|\fB\-r\fR |\fB\-w\fR |\fB\-v\fR ] \ + [\fB\-E\fR|\fB\-r\fR |\fB\-w\fR |\fB\-v\fR ] \ [\fB\-c\fR ] - [\fB\-l\fR [\fB\-i\fR ]] [\fB\-n\fR] [\fB\-f\fR]] + [\fB\-l\fR [\fB\-i\fR ]] [\fB\-n\fR] [\fB\-f\fR]] [\fB\-V\fR[\fBV\fR[\fBV\fR]]] [\fB-o\fR ] + [\fB--print-status-reg\fR] [\fB--print-wp-status\fR] + [\fB--wp-list\fR] [\fB--wp-enable\fR[=]] + [\fB--wp-disable\fR] [\fB--wp-set-range\fR start=,len=] .SH DESCRIPTION .B flashrom is a utility for detecting, reading, writing, verifying and erasing flash chips. It's often used to flash BIOS/EFI/coreboot/firmware images in-system using a supported mainboard. However, it also supports various external PCI/USB/parallel-port/serial-port based devices which can program flash chips, including some network cards (NICs), SATA/IDE controller cards, graphics cards, the Bus Pirate device, various FTDI FT2232/FT4232H/FT232H based USB devices, and more. .PP It supports a wide range of DIP32, PLCC32, DIP8, SO8/SOIC8, TSOP32, TSOP40, TSOP48, and BGA chips, which use various protocols such as LPC, FWH, parallel flash, or SPI. .SH OPTIONS @@ -122,26 +125,73 @@ Erase the flash ROM chip. .B "\-V, \-\-verbose" More verbose output. This option can be supplied multiple times (max. 3 times, i.e. .BR \-VVV ) for even more debug output. .TP .B "\-c, \-\-chip" Probe only for the specified flash ROM chip. This option takes the chip name as printed by .B "flashrom \-L" without the vendor name as parameter. Please note that the chip name is case sensitive. .TP +.B "\-\-print\-status\-reg" +Print the contents of the status register(s) with bit description along with +write protection mode of status register(s) and protected range. +.TP +.B "\-\-print\-wp\-status" +Print the write protection mode of status register(s) and protected range. +.TP +.B "\-\-wp\-list" +List the valid write protection ranges for the chip. +.TP +.B "\-\-wp\-enable[=]" +Set write protection mode of status register(s). +.sp +.B "" +is optional argument (case insensitive) that takes one of - +.sp +* +.B "HARDWARE" +mode (default) allows writes to status register(s) as long as WP# is high. \ +Writes are disallowed as long as WP# is low. +.sp +* +.B "PERMANENT" +mode will lock the status register(s) and all future attempts to write to it \ +will fail. +.sp +* +.B "POWER_CYCLE" +mode will lock the status register(s) until the next power down-up cycle. \ +After the cycle, SOFTWARE mode will be in effect. +.sp +* +.B "SOFTWARE" +mode allows writes to status register(s) irrespective of level of WP# pin. +.TP +.B "\-\-wp\-disable" +Disable any write protection of status register(s) in effect. SOFTWARE mode \ +will be applied after disabling. +.TP +.B "\-\-wp\-set\-range start=,len=" +Configure status register(s) to protect +.B "" + kB of memory starting from address +.B "". +Both start and len must be supplied. (Consider setting a write protection \ +mode to prevent against configuration changes to status register(s).) +.TP .B "\-f, \-\-force" Force one or more of the following actions: .sp * Force chip read and pretend the chip is there. .sp * Force chip access even if the chip is bigger than the maximum supported \ size for the flash bus. .sp * Force erase even if erase is known bad. .sp * Force write even if write is known bad. .TP .B "\-l, \-\-layout "