blob: b3fb42132b7557bff208cdb1ec53ee93572a9cd2 [file] [log] [blame]
David Hendricksf7924d12010-06-10 21:26:44 -07001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2000 Silicon Integrated System Corporation
5 * Copyright (C) 2004 Tyan Corp <yhlu@tyan.com>
6 * Copyright (C) 2005-2008 coresystems GmbH
7 * Copyright (C) 2008,2009,2010 Carl-Daniel Hailfinger
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
David Hendricksf7924d12010-06-10 21:26:44 -070018 */
19
Daniel Campello15e10992021-04-19 15:17:33 -060020#include <errno.h>
David Hendricksf7924d12010-06-10 21:26:44 -070021#include <stdio.h>
22#include <fcntl.h>
David Hendricksf7924d12010-06-10 21:26:44 -070023#include <sys/stat.h>
24#include <string.h>
Jack Rosenthal7a4b5ba2021-04-09 10:03:14 -060025#include <stdbool.h>
David Hendricksf7924d12010-06-10 21:26:44 -070026#include <stdlib.h>
27#include <getopt.h>
David Hendricks4b832f52011-01-20 14:28:34 -080028#include "big_lock.h"
David Hendricksf7924d12010-06-10 21:26:44 -070029#include "flash.h"
30#include "flashchips.h"
Edward O'Callaghanf0a3b3d2020-11-01 18:27:36 +110031#include "fmap.h"
David Hendricks42ad6522011-08-09 16:08:10 -070032#include "power.h"
David Hendricks82fd8ae2010-08-04 14:34:54 -070033#include "programmer.h"
David Hendricks23cd7782010-08-25 12:42:38 -070034#include "writeprotect.h"
David Hendricksf7924d12010-06-10 21:26:44 -070035
David Hendricksf91c3592014-10-10 16:41:19 -070036#define LOCK_TIMEOUT_SECS 180
David Hendricks4b832f52011-01-20 14:28:34 -080037
Shik Chen5fc35bc2012-08-07 17:51:42 +080038int set_ignore_lock = 0;
Louis Yung-Chieh Lo1f6bbf52011-04-06 10:24:38 +080039
Edward O'Callaghanf0e80772020-12-04 15:36:04 +110040#include "libflashrom.h"
hailfinger969e2f32011-09-08 00:00:29 +000041
Edward O'Callaghan76bde712019-09-03 15:25:31 +100042static void cli_classic_usage(const char *name)
David Hendricksf7924d12010-06-10 21:26:44 -070043{
Edward O'Callaghanba9dbca2021-01-27 12:13:29 +110044 printf("Usage: %s [-h|-R|-L|"
David Hendricksf7924d12010-06-10 21:26:44 -070045#if CONFIG_PRINT_WIKI == 1
Edward O'Callaghan53a44b62020-07-27 14:16:34 +100046 "-z|"
David Hendricksf7924d12010-06-10 21:26:44 -070047#endif
Edward O'Callaghanba9dbca2021-01-27 12:13:29 +110048 "\n\t-p <programmername>[:<parameters>] [-c <chipname>]\n"
49 "\t\t(--flash-name|--flash-size|\n"
Daniel Campello3adfd2d2021-04-15 10:36:04 -060050 "\t\t [-E|-x|(-r|-w|-v) [<file>]]\n"
Daniel Campelloc7afa3a2021-04-26 07:04:14 -060051 "\t\t [(-l <layoutfile>|--ifd|--fmap|--fmap-file <fmapfile>) [-i <region>[:<file>]]...]\n"
Edward O'Callaghanba9dbca2021-01-27 12:13:29 +110052 "\t\t [-n] [-N] [-f])]\n"
53 "\t[-V[V[V]]] [-o <logfile>]\n\n", name);
David Hendricksf7924d12010-06-10 21:26:44 -070054
Edward O'Callaghan53a44b62020-07-27 14:16:34 +100055 printf(" -h | --help print this help text\n"
56 " -R | --version print version (release)\n"
Daniel Campello3adfd2d2021-04-15 10:36:04 -060057 " -r | --read [<file>] read flash and save to <file>\n"
Daniel Campello15e10992021-04-19 15:17:33 -060058 " -w | --write [<file|->] write <file> or the content provided\n"
59 " on the standard input to flash\n"
60 " -v | --verify [<file|->] verify flash against <file>\n"
61 " or the content provided on the standard input\n"
Edward O'Callaghan53a44b62020-07-27 14:16:34 +100062 " -E | --erase erase flash memory\n"
63 " -V | --verbose more verbose output\n"
64 " -c | --chip <chipname> probe only for specified flash chip\n"
65 " -f | --force force specific operations (see man page)\n"
66 " -n | --noverify don't auto-verify\n"
Edward O'Callaghan0d7e73a2020-09-22 13:16:04 +100067 " -N | --noverify-all verify included regions only (cf. -i)\n"
Daniel Campello83752f82021-04-16 14:54:27 -060068 " -x | --extract extract regions to files\n"
Edward O'Callaghan53a44b62020-07-27 14:16:34 +100069 " -l | --layout <layoutfile> read ROM layout from <layoutfile>\n"
Edward O'Callaghan7580a522021-02-16 14:26:16 +110070 " --wp-disable disable write protection\n"
71 " --wp-enable enable write protection\n"
72 " --wp-list list write protect range\n"
73 " --wp-status show write protect status\n"
Daniel Campello99b95502021-05-03 20:56:13 -060074 " --wp-range=<start>,<len> set write protect range\n"
75 " --wp-region <region> set write protect region\n"
Edward O'Callaghan8b9a9ac2021-01-27 11:06:38 +110076 " --flash-name read out the detected flash name\n"
77 " --flash-size read out the detected flash size\n"
Daniel Campelloc7afa3a2021-04-26 07:04:14 -060078 " --fmap read ROM layout from fmap embedded in ROM\n"
79 " --fmap-file <fmapfile> read ROM layout from fmap in <fmapfile>\n"
Daniel Campelloc6e22b72021-04-19 12:47:16 -060080 " --ifd read layout from an Intel Firmware Descriptor\n"
Daniel Campello2fdc8372021-04-16 17:52:51 -060081 " -i | --image <region>[:<file>] only read/write image <region> from layout\n"
82 " (optionally with data from <file>)\n"
Edward O'Callaghan53a44b62020-07-27 14:16:34 +100083 " -o | --output <logfile> log output to <logfile>\n"
Edward O'Callaghan5da5bb12021-01-22 23:41:45 +110084 " --flash-contents <ref-file> assume flash contents to be <ref-file>\n"
Daniel Campello15e10992021-04-19 15:17:33 -060085 " --do-not-diff do not diff with chip contents\n"
86 " (should be used with erased chips only)\n"
87 " --ignore-lock do not acquire big lock\n"
Edward O'Callaghan53a44b62020-07-27 14:16:34 +100088 " -L | --list-supported print supported devices\n"
David Hendricksf7924d12010-06-10 21:26:44 -070089#if CONFIG_PRINT_WIKI == 1
Edward O'Callaghan53a44b62020-07-27 14:16:34 +100090 " -z | --list-supported-wiki print supported devices in wiki syntax\n"
David Hendricksf7924d12010-06-10 21:26:44 -070091#endif
Edward O'Callaghan53a44b62020-07-27 14:16:34 +100092 " -p | --programmer <name>[:<param>] specify the programmer device. One of\n");
Edward O'Callaghan53a44b62020-07-27 14:16:34 +100093 list_programmers_linebreak(4, 80, 0);
Edward O'Callaghan53a44b62020-07-27 14:16:34 +100094 printf(".\n\nYou can specify one of -h, -R, -L, "
David Hendricksf7924d12010-06-10 21:26:44 -070095#if CONFIG_PRINT_WIKI == 1
96 "-z, "
97#endif
98 "-E, -r, -w, -v or no operation.\n"
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +100099 "If no operation is specified, flashrom will only probe for flash chips.\n");
David Hendricksf7924d12010-06-10 21:26:44 -0700100}
101
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000102static void cli_classic_abort_usage(const char *msg)
David Hendricksf7924d12010-06-10 21:26:44 -0700103{
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000104 if (msg)
105 fprintf(stderr, "%s", msg);
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000106 printf("Please run \"flashrom --help\" for usage info.\n");
David Hendricksf7924d12010-06-10 21:26:44 -0700107 exit(1);
108}
109
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000110static void cli_classic_validate_singleop(int *operation_specified)
111{
112 if (++(*operation_specified) > 1) {
113 cli_classic_abort_usage("More than one operation specified. Aborting.\n");
114 }
115}
116
Edward O'Callaghan4675aec2021-01-06 19:20:06 +1100117static int check_filename(char *filename, const char *type)
Souvik Ghosh3c963a42016-07-19 18:48:15 -0700118{
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000119 if (!filename || (filename[0] == '\0')) {
Souvik Ghosh3c963a42016-07-19 18:48:15 -0700120 fprintf(stderr, "Error: No %s file specified.\n", type);
121 return 1;
122 }
123 /* Not an error, but maybe the user intended to specify a CLI option instead of a file name. */
Daniel Campello3adfd2d2021-04-15 10:36:04 -0600124 if (filename[0] == '-' && filename[1] != '\0')
Souvik Ghosh3c963a42016-07-19 18:48:15 -0700125 fprintf(stderr, "Warning: Supplied %s file name starts with -\n", type);
126 return 0;
127}
128
Jack Rosenthal7a4b5ba2021-04-09 10:03:14 -0600129/* Ensure a file is open by means of fstat */
130static bool check_file(FILE *file)
131{
132#ifndef STANDALONE
133 struct stat statbuf;
134
135 if (fstat(fileno(file), &statbuf) < 0)
136 return false;
137#endif /* !STANDALONE */
138 return true;
139}
140
Daniel Campello99b95502021-05-03 20:56:13 -0600141static int parse_wp_range(unsigned int *start, unsigned int *len)
Daniel Campello02bcfc92021-04-20 08:18:29 -0600142{
143 char *endptr = NULL, *token = NULL;
144
Daniel Campello99b95502021-05-03 20:56:13 -0600145 if (!optarg) {
Daniel Campello02bcfc92021-04-20 08:18:29 -0600146 msg_gerr("Error: No wp-range values provided\n");
147 return -1;
148 }
149
Daniel Campello99b95502021-05-03 20:56:13 -0600150 token = strtok(optarg, ",");
Daniel Campello02bcfc92021-04-20 08:18:29 -0600151 if (!token) {
152 msg_gerr("Error: Invalid wp-range argument format\n");
153 return -1;
154 }
155 *start = strtoul(token, &endptr, 0);
156
157 token = strtok(NULL, ",");
158 if (!token) {
159 msg_gerr("Error: Invalid wp-range argument format\n");
160 return -1;
161 }
162 *len = strtoul(token, &endptr, 0);
163
164 return 0;
165}
166
Daniel Campello17a3db92021-04-13 23:28:55 -0600167static char *get_optional_filename(char *argv[])
168{
169 char *filename = NULL;
170
171 /* filename was supplied in optarg (i.e. -rfilename) */
172 if (optarg != NULL)
173 filename = strdup(optarg);
174 /* filename is on optind if it is not another flag (i.e. -r filename)
175 * - is treated as stdin, so we still strdup in this case
176 */
177 else if (optarg == NULL && argv[optind] != NULL &&
178 (argv[optind][0] != '-' || argv[optind][1] == '\0'))
179 filename = strdup(argv[optind++]);
180
181 return filename;
182}
183
Daniel Campello241c6bf2021-04-19 09:58:47 -0600184static int flashrom_layout_read_fmap_from_file(struct flashrom_layout **layout,
185 struct flashrom_flashctx *flashctx, const char *fmapfile)
186{
187 int ret = 1;
188 struct stat s;
189 if (stat(fmapfile, &s) != 0) {
190 return ret;
191 }
192
193 size_t fmapfile_size = s.st_size;
194 uint8_t *fmapfile_buffer = malloc(fmapfile_size);
195 if (!fmapfile_buffer) {
196 return ret;
197 }
198
199 if (read_buf_from_file(fmapfile_buffer, fmapfile_size, fmapfile)) {
200 goto out;
201 }
202
203 ret = flashrom_layout_read_fmap_from_buffer(layout, flashctx, fmapfile_buffer, fmapfile_size);
204out:
205 free(fmapfile_buffer);
206 return ret;
207}
208
uwe9fbda662011-08-20 14:14:22 +0000209int main(int argc, char *argv[])
David Hendricksf7924d12010-06-10 21:26:44 -0700210{
Edward O'Callaghanf93b3742019-02-24 17:24:27 +1100211 const struct flashchip *chip = NULL;
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100212 /* Probe for up to eight flash chips. */
213 struct flashctx flashes[8] = {{0}};
David Hendricksac1d25c2016-08-09 17:00:58 -0700214 struct flashctx *fill_flash;
David Hendricksf7924d12010-06-10 21:26:44 -0700215 const char *name;
Edward O'Callaghan5aada9e2020-09-22 13:35:45 +1000216 int namelen, opt, i, j;
Daniel Campelloc7afa3a2021-04-26 07:04:14 -0600217 int startchip = -1, chipcount = 0, option_index = 0, force = 0, ifd = 0, fmap = 0;
David Hendricksf7924d12010-06-10 21:26:44 -0700218#if CONFIG_PRINT_WIKI == 1
219 int list_supported_wiki = 0;
220#endif
Edward O'Callaghan5aada9e2020-09-22 13:35:45 +1000221 int flash_name = 0, flash_size = 0;
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100222 int set_wp_enable = 0, set_wp_disable = 0, wp_status = 0;
223 int set_wp_range = 0, set_wp_region = 0, wp_list = 0;
Daniel Campello83752f82021-04-16 14:54:27 -0600224 int read_it = 0, extract_it = 0, write_it = 0, erase_it = 0, verify_it = 0;
Edward O'Callaghan0d7e73a2020-09-22 13:16:04 +1000225 int dont_verify_it = 0, dont_verify_all = 0, list_supported = 0, operation_specified = 0;
Daniel Campello15e10992021-04-19 15:17:33 -0600226 int do_not_diff = 0;
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600227 struct flashrom_layout *layout = NULL;
hailfinger969e2f32011-09-08 00:00:29 +0000228 enum programmer prog = PROGRAMMER_INVALID;
Edward O'Callaghan5c062c62020-07-27 13:27:57 +1000229 enum {
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600230 OPTION_IFD = 0x0100,
Daniel Campelloc7afa3a2021-04-26 07:04:14 -0600231 OPTION_FMAP,
232 OPTION_FMAP_FILE,
Edward O'Callaghan5da5bb12021-01-22 23:41:45 +1100233 OPTION_FLASH_CONTENTS,
Edward O'Callaghan5c062c62020-07-27 13:27:57 +1000234 OPTION_FLASH_NAME,
235 OPTION_FLASH_SIZE,
236 OPTION_WP_STATUS,
237 OPTION_WP_SET_RANGE,
238 OPTION_WP_SET_REGION,
239 OPTION_WP_ENABLE,
240 OPTION_WP_DISABLE,
241 OPTION_WP_LIST,
Daniel Campello15e10992021-04-19 15:17:33 -0600242 OPTION_DO_NOT_DIFF,
Edward O'Callaghan5c062c62020-07-27 13:27:57 +1000243 OPTION_IGNORE_LOCK,
Edward O'Callaghan5c062c62020-07-27 13:27:57 +1000244 };
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000245 int ret = 0;
Daniel Campello2fdc8372021-04-16 17:52:51 -0600246 unsigned int wp_start = 0, wp_len = 0;
David Hendricksf7924d12010-06-10 21:26:44 -0700247
Daniel Campello17a3db92021-04-13 23:28:55 -0600248 static const char optstring[] = "r::Rw::v::nNVEfc:l:i:p:Lzho:x";
Edward O'Callaghan1e6fd882020-07-27 13:06:38 +1000249 static const struct option long_options[] = {
Daniel Campello17a3db92021-04-13 23:28:55 -0600250 {"read", 2, NULL, 'r'},
251 {"write", 2, NULL, 'w'},
Edward O'Callaghan1e6fd882020-07-27 13:06:38 +1000252 {"erase", 0, NULL, 'E'},
Daniel Campello17a3db92021-04-13 23:28:55 -0600253 {"verify", 2, NULL, 'v'},
Edward O'Callaghan1e6fd882020-07-27 13:06:38 +1000254 {"noverify", 0, NULL, 'n'},
Daniel Campello15e10992021-04-19 15:17:33 -0600255 {"noverify-all", 0, NULL, 'N'},
Daniel Campello83752f82021-04-16 14:54:27 -0600256 {"extract", 0, NULL, 'x'},
Edward O'Callaghan1e6fd882020-07-27 13:06:38 +1000257 {"chip", 1, NULL, 'c'},
258 {"verbose", 0, NULL, 'V'},
259 {"force", 0, NULL, 'f'},
260 {"layout", 1, NULL, 'l'},
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600261 {"ifd", 0, NULL, OPTION_IFD},
Daniel Campelloc7afa3a2021-04-26 07:04:14 -0600262 {"fmap", 0, NULL, OPTION_FMAP},
263 {"fmap-file", 1, NULL, OPTION_FMAP_FILE},
Edward O'Callaghan1e6fd882020-07-27 13:06:38 +1000264 {"image", 1, NULL, 'i'},
Edward O'Callaghan5da5bb12021-01-22 23:41:45 +1100265 {"flash-contents", 1, NULL, OPTION_FLASH_CONTENTS},
Edward O'Callaghan5c062c62020-07-27 13:27:57 +1000266 {"flash-name", 0, NULL, OPTION_FLASH_NAME},
267 {"flash-size", 0, NULL, OPTION_FLASH_SIZE},
268 {"get-size", 0, NULL, OPTION_FLASH_SIZE}, // (deprecated): back compatibility.
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100269 {"wp-status", 0, 0, OPTION_WP_STATUS},
Daniel Campello99b95502021-05-03 20:56:13 -0600270 {"wp-range", required_argument, NULL, OPTION_WP_SET_RANGE},
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100271 {"wp-region", 1, 0, OPTION_WP_SET_REGION},
272 {"wp-enable", optional_argument, 0, OPTION_WP_ENABLE},
273 {"wp-disable", 0, 0, OPTION_WP_DISABLE},
274 {"wp-list", 0, 0, OPTION_WP_LIST},
Edward O'Callaghan1e6fd882020-07-27 13:06:38 +1000275 {"list-supported", 0, NULL, 'L'},
276 {"list-supported-wiki", 0, NULL, 'z'},
Edward O'Callaghan1e6fd882020-07-27 13:06:38 +1000277 {"programmer", 1, NULL, 'p'},
278 {"help", 0, NULL, 'h'},
279 {"version", 0, NULL, 'R'},
280 {"output", 1, NULL, 'o'},
Edward O'Callaghan5c062c62020-07-27 13:27:57 +1000281 {"do-not-diff", 0, 0, OPTION_DO_NOT_DIFF},
Edward O'Callaghan5c062c62020-07-27 13:27:57 +1000282 {"ignore-lock", 0, 0, OPTION_IGNORE_LOCK},
Edward O'Callaghan1e6fd882020-07-27 13:06:38 +1000283 {NULL, 0, NULL, 0},
David Hendricksf7924d12010-06-10 21:26:44 -0700284 };
285
286 char *filename = NULL;
Edward O'Callaghan5da5bb12021-01-22 23:41:45 +1100287 char *referencefile = NULL;
Carl-Daniel Hailfinger2166d482016-08-04 10:46:36 -0700288 char *layoutfile = NULL;
Daniel Campelloc7afa3a2021-04-26 07:04:14 -0600289 char *fmapfile = NULL;
Edward O'Callaghanbdb288e2021-01-27 12:15:49 +1100290#ifndef STANDALONE
Souvik Ghosh3c963a42016-07-19 18:48:15 -0700291 char *logfile = NULL;
Edward O'Callaghanbdb288e2021-01-27 12:15:49 +1100292#endif /* !STANDALONE */
David Hendricksf7924d12010-06-10 21:26:44 -0700293 char *tempstr = NULL;
David Hendricks82fd8ae2010-08-04 14:34:54 -0700294 char *pparam = NULL;
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100295 struct layout_include_args *include_args = NULL;
David Hendricks1c09f802012-10-03 11:03:48 -0700296 char *wp_mode_opt = NULL;
David Hendricksc36685a2016-09-12 20:41:05 -0700297 char *wp_region = NULL;
David Hendricksf7924d12010-06-10 21:26:44 -0700298
Jack Rosenthal7a4b5ba2021-04-09 10:03:14 -0600299 /*
300 * Safety-guard against a user who has (mistakenly) closed
301 * stdout or stderr before exec'ing flashrom. We disable
302 * logging in this case to prevent writing log data to a flash
303 * chip when a flash device gets opened with fd 1 or 2.
304 */
305 if (check_file(stdout) && check_file(stderr)) {
306 flashrom_set_log_callback(
307 (flashrom_log_callback *)&flashrom_print_cb);
308 }
Edward O'Callaghanf0e80772020-12-04 15:36:04 +1100309
David Hendricksf7924d12010-06-10 21:26:44 -0700310 print_version();
Edward O'Callaghand68fd2f2020-07-24 16:54:42 +1000311 print_banner();
Edward O'Callaghana87d5e62019-06-04 13:46:17 +1000312
David Hendricksf7924d12010-06-10 21:26:44 -0700313 if (selfcheck())
314 exit(1);
315
316 setbuf(stdout, NULL);
317 /* FIXME: Delay all operation_specified checks until after command
318 * line parsing to allow --help overriding everything else.
319 */
320 while ((opt = getopt_long(argc, argv, optstring,
321 long_options, &option_index)) != EOF) {
322 switch (opt) {
323 case 'r':
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000324 cli_classic_validate_singleop(&operation_specified);
Daniel Campello17a3db92021-04-13 23:28:55 -0600325 filename = get_optional_filename(argv);
David Hendricksf7924d12010-06-10 21:26:44 -0700326 read_it = 1;
327 break;
328 case 'w':
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000329 cli_classic_validate_singleop(&operation_specified);
Daniel Campello17a3db92021-04-13 23:28:55 -0600330 filename = get_optional_filename(argv);
David Hendricksf7924d12010-06-10 21:26:44 -0700331 write_it = 1;
332 break;
333 case 'v':
334 //FIXME: gracefully handle superfluous -v
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000335 cli_classic_validate_singleop(&operation_specified);
David Hendricksf7924d12010-06-10 21:26:44 -0700336 if (dont_verify_it) {
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000337 cli_classic_abort_usage("--verify and --noverify are mutually exclusive. Aborting.\n");
David Hendricksf7924d12010-06-10 21:26:44 -0700338 }
Daniel Campello17a3db92021-04-13 23:28:55 -0600339 filename = get_optional_filename(argv);
Edward O'Callaghan4eb85102020-12-18 13:17:08 +1100340 verify_it = 1;
David Hendricksf7924d12010-06-10 21:26:44 -0700341 break;
342 case 'n':
343 if (verify_it) {
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000344 cli_classic_abort_usage("--verify and --noverify are mutually exclusive. Aborting.\n");
David Hendricksf7924d12010-06-10 21:26:44 -0700345 }
346 dont_verify_it = 1;
347 break;
Edward O'Callaghan0d7e73a2020-09-22 13:16:04 +1000348 case 'N':
349 dont_verify_all = 1;
Edward O'Callaghan0d7e73a2020-09-22 13:16:04 +1000350 break;
Daniel Campello83752f82021-04-16 14:54:27 -0600351 case 'x':
352 cli_classic_validate_singleop(&operation_specified);
353 extract_it = 1;
354 break;
David Hendricksf7924d12010-06-10 21:26:44 -0700355 case 'c':
356 chip_to_probe = strdup(optarg);
357 break;
358 case 'V':
Souvik Ghosh3c963a42016-07-19 18:48:15 -0700359 verbose_screen++;
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000360 if (verbose_screen > FLASHROM_MSG_DEBUG2)
Souvik Ghosh3c963a42016-07-19 18:48:15 -0700361 verbose_logfile = verbose_screen;
David Hendricksf7924d12010-06-10 21:26:44 -0700362 break;
363 case 'E':
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000364 cli_classic_validate_singleop(&operation_specified);
David Hendricksf7924d12010-06-10 21:26:44 -0700365 erase_it = 1;
366 break;
David Hendricksf7924d12010-06-10 21:26:44 -0700367 case 'f':
368 force = 1;
369 break;
370 case 'l':
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000371 if (layoutfile)
372 cli_classic_abort_usage("Error: --layout specified more than once. Aborting.\n");
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600373 if (ifd)
374 cli_classic_abort_usage("Error: --layout and --ifd both specified. Aborting.\n");
Daniel Campelloc7afa3a2021-04-26 07:04:14 -0600375 if (fmap)
376 cli_classic_abort_usage("Error: --layout and --fmap-file both specified. Aborting.\n");
Carl-Daniel Hailfinger2166d482016-08-04 10:46:36 -0700377 layoutfile = strdup(optarg);
David Hendricksf7924d12010-06-10 21:26:44 -0700378 break;
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600379 case OPTION_IFD:
380 if (layoutfile)
381 cli_classic_abort_usage("Error: --layout and --ifd both specified. Aborting.\n");
Daniel Campelloc7afa3a2021-04-26 07:04:14 -0600382 if (fmap)
383 cli_classic_abort_usage("Error: --fmap-file and --ifd both specified. Aborting.\n");
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600384 ifd = 1;
385 break;
Daniel Campelloc7afa3a2021-04-26 07:04:14 -0600386 case OPTION_FMAP_FILE:
387 if (fmap)
388 cli_classic_abort_usage("Error: --fmap or --fmap-file specified "
389 "more than once. Aborting.\n");
390 if (ifd)
391 cli_classic_abort_usage("Error: --fmap-file and --ifd both specified. Aborting.\n");
392 if (layoutfile)
393 cli_classic_abort_usage("Error: --fmap-file and --layout both specified. Aborting.\n");
394 fmapfile = strdup(optarg);
395 fmap = 1;
396 break;
397 case OPTION_FMAP:
398 if (fmap)
399 cli_classic_abort_usage("Error: --fmap or --fmap-file specified "
400 "more than once. Aborting.\n");
401 if (ifd)
402 cli_classic_abort_usage("Error: --fmap and --ifd both specified. Aborting.\n");
403 if (layoutfile)
404 cli_classic_abort_usage("Error: --layout and --fmap both specified. Aborting.\n");
405 fmap = 1;
406 break;
David Hendricksf7924d12010-06-10 21:26:44 -0700407 case 'i':
Daniel Campello2fdc8372021-04-16 17:52:51 -0600408 if (register_include_arg(&include_args, optarg))
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000409 cli_classic_abort_usage(NULL);
David Hendricksf7924d12010-06-10 21:26:44 -0700410 break;
Edward O'Callaghan5da5bb12021-01-22 23:41:45 +1100411 case OPTION_FLASH_CONTENTS:
412 if (referencefile)
413 cli_classic_abort_usage("Error: --flash-contents specified more than once."
414 "Aborting.\n");
Daniel Campello15e10992021-04-19 15:17:33 -0600415 if (do_not_diff)
416 cli_classic_abort_usage("Error: --flash-contents and --do-not-diff both "
417 "specified. Aborting.\n");
Edward O'Callaghan5da5bb12021-01-22 23:41:45 +1100418 referencefile = strdup(optarg);
419 break;
Edward O'Callaghan8b9a9ac2021-01-27 11:06:38 +1100420 case OPTION_FLASH_NAME:
421 cli_classic_validate_singleop(&operation_specified);
422 flash_name = 1;
423 break;
424 case OPTION_FLASH_SIZE:
425 cli_classic_validate_singleop(&operation_specified);
426 flash_size = 1;
427 break;
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100428 case OPTION_WP_STATUS:
429 wp_status = 1;
430 break;
431 case OPTION_WP_LIST:
432 wp_list = 1;
433 break;
434 case OPTION_WP_SET_RANGE:
Daniel Campello99b95502021-05-03 20:56:13 -0600435 if (parse_wp_range(&wp_start, &wp_len) < 0)
436 cli_classic_abort_usage("Incorrect wp-range arguments provided.\n");
437
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100438 set_wp_range = 1;
439 break;
440 case OPTION_WP_ENABLE:
441 set_wp_enable = 1;
442 if (optarg)
443 wp_mode_opt = strdup(optarg);
444 break;
445 case OPTION_WP_DISABLE:
446 set_wp_disable = 1;
447 break;
Edward O'Callaghan34d2f312021-02-16 13:49:25 +1100448 case 'L':
449 cli_classic_validate_singleop(&operation_specified);
450 list_supported = 1;
451 break;
David Hendricksf7924d12010-06-10 21:26:44 -0700452 case 'z':
453#if CONFIG_PRINT_WIKI == 1
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000454 cli_classic_validate_singleop(&operation_specified);
David Hendricksf7924d12010-06-10 21:26:44 -0700455 list_supported_wiki = 1;
456#else
Edward O'Callaghan44c28652021-01-27 11:20:00 +1100457 cli_classic_abort_usage("Error: Wiki output was not "
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000458 "compiled in. Aborting.\n");
David Hendricksf7924d12010-06-10 21:26:44 -0700459#endif
460 break;
461 case 'p':
hailfinger969e2f32011-09-08 00:00:29 +0000462 if (prog != PROGRAMMER_INVALID) {
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000463 cli_classic_abort_usage("Error: --programmer specified "
hailfinger969e2f32011-09-08 00:00:29 +0000464 "more than once. You can separate "
465 "multiple\nparameters for a programmer "
466 "with \",\". Please see the man page "
467 "for details.\n");
hailfinger969e2f32011-09-08 00:00:29 +0000468 }
469 for (prog = 0; prog < PROGRAMMER_INVALID; prog++) {
470 name = programmer_table[prog].name;
David Hendricksf7924d12010-06-10 21:26:44 -0700471 namelen = strlen(name);
472 if (strncmp(optarg, name, namelen) == 0) {
473 switch (optarg[namelen]) {
474 case ':':
David Hendricks82fd8ae2010-08-04 14:34:54 -0700475 pparam = strdup(optarg + namelen + 1);
476 if (!strlen(pparam)) {
477 free(pparam);
478 pparam = NULL;
David Hendricksf7924d12010-06-10 21:26:44 -0700479 }
480 break;
481 case '\0':
482 break;
483 default:
484 /* The continue refers to the
485 * for loop. It is here to be
486 * able to differentiate between
487 * foo and foobar.
488 */
489 continue;
490 }
491 break;
492 }
493 }
Edward O'Callaghan5b16a082020-10-20 16:30:16 +1100494 if (prog == PROGRAMMER_INVALID) {
Edward O'Callaghanb9532fa2020-07-24 17:27:50 +1000495 fprintf(stderr, "Error: Unknown programmer \"%s\". Valid choices are:\n",
496 optarg);
497 list_programmers_linebreak(0, 80, 0);
498 msg_ginfo(".\n");
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000499 cli_classic_abort_usage(NULL);
David Hendricksf7924d12010-06-10 21:26:44 -0700500 }
501 break;
502 case 'R':
503 /* print_version() is always called during startup. */
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000504 cli_classic_validate_singleop(&operation_specified);
David Hendricksf7924d12010-06-10 21:26:44 -0700505 exit(0);
506 break;
507 case 'h':
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000508 cli_classic_validate_singleop(&operation_specified);
Edward O'Callaghan1a3fd132019-06-04 14:18:55 +1000509 cli_classic_usage(argv[0]);
David Hendricksf7924d12010-06-10 21:26:44 -0700510 exit(0);
511 break;
Souvik Ghosh3c963a42016-07-19 18:48:15 -0700512 case 'o':
513#ifdef STANDALONE
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000514 cli_classic_abort_usage("Log file not supported in standalone mode. Aborting.\n");
Souvik Ghosh3c963a42016-07-19 18:48:15 -0700515#else /* STANDALONE */
Edward O'Callaghan64d1f172020-08-19 12:52:01 +1000516 if (logfile) {
517 fprintf(stderr, "Warning: -o/--output specified multiple times.\n");
518 free(logfile);
519 }
520
Souvik Ghosh3c963a42016-07-19 18:48:15 -0700521 logfile = strdup(optarg);
522 if (logfile[0] == '\0') {
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000523 cli_classic_abort_usage("No log filename specified.\n");
Souvik Ghosh3c963a42016-07-19 18:48:15 -0700524 }
525#endif /* STANDALONE */
526 break;
Edward O'Callaghan5c062c62020-07-27 13:27:57 +1000527 case OPTION_DO_NOT_DIFF:
Daniel Campello15e10992021-04-19 15:17:33 -0600528 if (referencefile)
529 cli_classic_abort_usage("Error: --flash-contents and --do-not-diff both "
530 "specified. Aborting.\n");
531 do_not_diff = 1;
Vadim Bendebury2f346a32018-05-21 10:24:18 -0700532 break;
Edward O'Callaghan5c062c62020-07-27 13:27:57 +1000533 case OPTION_WP_SET_REGION:
David Hendricksc36685a2016-09-12 20:41:05 -0700534 set_wp_region = 1;
535 wp_region = strdup(optarg);
536 break;
Edward O'Callaghan5c062c62020-07-27 13:27:57 +1000537 case OPTION_IGNORE_LOCK:
Shik Chen5fc35bc2012-08-07 17:51:42 +0800538 set_ignore_lock = 1;
539 break;
David Hendricksf7924d12010-06-10 21:26:44 -0700540 default:
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000541 cli_classic_abort_usage(NULL);
David Hendricksf7924d12010-06-10 21:26:44 -0700542 break;
543 }
544 }
545
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000546 if (optind < argc)
547 cli_classic_abort_usage("Error: Extra parameter found.\n");
Daniel Campello17a3db92021-04-13 23:28:55 -0600548 if (filename && check_filename(filename, "image"))
549 cli_classic_abort_usage(NULL);
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000550 if (layoutfile && check_filename(layoutfile, "layout"))
551 cli_classic_abort_usage(NULL);
Daniel Campelloc7afa3a2021-04-26 07:04:14 -0600552 if (fmapfile && check_filename(fmapfile, "fmap"))
553 cli_classic_abort_usage(NULL);
Edward O'Callaghan5da5bb12021-01-22 23:41:45 +1100554 if (referencefile && check_filename(referencefile, "reference"))
555 cli_classic_abort_usage(NULL);
Vadim Bendebury2f346a32018-05-21 10:24:18 -0700556
Souvik Ghosh3c963a42016-07-19 18:48:15 -0700557#ifndef STANDALONE
558 if (logfile && check_filename(logfile, "log"))
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000559 cli_classic_abort_usage(NULL);
Souvik Ghosh3c963a42016-07-19 18:48:15 -0700560 if (logfile && open_logfile(logfile))
Edward O'Callaghanacac0c82019-09-26 11:17:20 +1000561 cli_classic_abort_usage(NULL);
Souvik Ghosh3c963a42016-07-19 18:48:15 -0700562#endif /* !STANDALONE */
563
Edward O'Callaghan81072b82020-07-24 17:01:02 +1000564#if CONFIG_PRINT_WIKI == 1
565 if (list_supported_wiki) {
566 print_supported_wiki();
Edward O'Callaghan562c1d42020-08-19 12:45:04 +1000567 goto out;
Edward O'Callaghan81072b82020-07-24 17:01:02 +1000568 }
569#endif
570
571 if (list_supported) {
572 if (print_supported())
573 ret = 1;
Edward O'Callaghan562c1d42020-08-19 12:45:04 +1000574 goto out;
Edward O'Callaghan81072b82020-07-24 17:01:02 +1000575 }
David Hendricksdf29a832013-06-28 14:33:51 -0700576
Souvik Ghosh3c963a42016-07-19 18:48:15 -0700577#ifndef STANDALONE
578 start_logging();
579#endif /* !STANDALONE */
580
581 print_buildinfo();
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000582 msg_gdbg("Command line (%i args):", argc - 1);
Carl-Daniel Hailfinger2166d482016-08-04 10:46:36 -0700583 for (i = 0; i < argc; i++) {
584 msg_gdbg(" %s", argv[i]);
585 }
586 msg_gdbg("\n");
587
588 if (layoutfile && read_romlayout(layoutfile)) {
Edward O'Callaghan562c1d42020-08-19 12:45:04 +1000589 ret = 1;
590 goto out;
Carl-Daniel Hailfinger2166d482016-08-04 10:46:36 -0700591 }
592
Daniel Campelloc7afa3a2021-04-26 07:04:14 -0600593 /* If the user specifies a -i argument and no layout, then we do fmap
594 * parsing. */
595 if ((include_args || extract_it) && !layoutfile && !ifd) {
596 msg_gdbg("-i argument specified, set fmap.\n");
597 fmap = 1;
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600598 }
599
Daniel Campelloc7afa3a2021-04-26 07:04:14 -0600600 if (!ifd && !fmap && process_include_args(get_global_layout(), include_args)) {
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600601 ret = 1;
602 goto out;
603 }
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000604 /* Does a chip with the requested name exist in the flashchips array? */
David Hendricksf7924d12010-06-10 21:26:44 -0700605 if (chip_to_probe) {
Edward O'Callaghan5b4b4882021-01-22 00:56:42 +1100606 for (chip = flashchips; chip && chip->name; chip++)
607 if (!strcmp(chip->name, chip_to_probe))
David Hendricksf7924d12010-06-10 21:26:44 -0700608 break;
Edward O'Callaghan5b4b4882021-01-22 00:56:42 +1100609 if (!chip || !chip->name) {
Edward O'Callaghane9fa7372020-07-24 16:57:41 +1000610 msg_cerr("Error: Unknown chip '%s' specified.\n", chip_to_probe);
611 msg_gerr("Run flashrom -L to view the hardware supported in this flashrom version.\n");
Edward O'Callaghan562c1d42020-08-19 12:45:04 +1000612 ret = 1;
613 goto out;
David Hendricksf7924d12010-06-10 21:26:44 -0700614 }
Edward O'Callaghanf93b3742019-02-24 17:24:27 +1100615 /* Keep chip around for later usage in case a forced read is requested. */
David Hendricksf7924d12010-06-10 21:26:44 -0700616 }
617
Edward O'Callaghanb9532fa2020-07-24 17:27:50 +1000618 if (prog == PROGRAMMER_INVALID) {
619 if (CONFIG_DEFAULT_PROGRAMMER != PROGRAMMER_INVALID) {
620 prog = CONFIG_DEFAULT_PROGRAMMER;
621 /* We need to strdup here because we free(pparam) unconditionally later. */
Edward O'Callaghan5b16a082020-10-20 16:30:16 +1100622 pparam = strdup(CONFIG_DEFAULT_PROGRAMMER_ARGS);
Edward O'Callaghanb9532fa2020-07-24 17:27:50 +1000623 msg_pinfo("Using default programmer \"%s\" with arguments \"%s\".\n",
624 programmer_table[CONFIG_DEFAULT_PROGRAMMER].name, pparam);
625 } else {
626 msg_perr("Please select a programmer with the --programmer parameter.\n"
627#if CONFIG_INTERNAL == 1
628 "To choose the mainboard of this computer use 'internal'. "
629#endif
630 "Valid choices are:\n");
631 list_programmers_linebreak(0, 80, 0);
632 msg_ginfo(".\n");
633 ret = 1;
Edward O'Callaghan562c1d42020-08-19 12:45:04 +1000634 goto out;
Edward O'Callaghanb9532fa2020-07-24 17:27:50 +1000635 }
636 }
hailfinger969e2f32011-09-08 00:00:29 +0000637
David Hendricksde007992011-01-27 20:02:09 -0800638#if USE_BIG_LOCK == 1
639 /* get lock before doing any work that touches hardware */
Shik Chen5fc35bc2012-08-07 17:51:42 +0800640 if (!set_ignore_lock) {
641 msg_gdbg("Acquiring lock (timeout=%d sec)...\n", LOCK_TIMEOUT_SECS);
642 if (acquire_big_lock(LOCK_TIMEOUT_SECS) < 0) {
643 msg_gerr("Could not acquire lock.\n");
Edward O'Callaghan562c1d42020-08-19 12:45:04 +1000644 ret = 1;
645 goto out;
Shik Chen5fc35bc2012-08-07 17:51:42 +0800646 }
647 msg_gdbg("Lock acquired.\n");
David Hendricks4b832f52011-01-20 14:28:34 -0800648 }
David Hendricksde007992011-01-27 20:02:09 -0800649#endif
David Hendricks4b832f52011-01-20 14:28:34 -0800650
David Hendricks89a2adc2011-08-25 12:51:08 -0700651 /*
David Hendricks37006402014-09-10 14:26:37 -0700652 * Let powerd know that we're updating firmware so machine stays awake.
653 *
654 * A bit of history behind this small block of code:
655 * chromium-os:15025 - If broken_timer == 1, use busy loop instead of
656 * OS timers to avoid excessive usleep overhead during "long" operations
657 * involving reads, erases, and writes. This was mostly a problem on
658 * old machines with poor DVFS implementations.
659 *
660 * chromium-os:18895 - Disabled power management to prevent system from
661 * going to sleep while doing a destructive operation.
662 *
663 * chromium-os:19321 - Use OS timers for non-destructive operations to
664 * avoid UI jank.
665 *
666 * chromium:400641 - Powerd is smarter now, so instead of stopping it
667 * manually we'll use a file lock so it knows not to put the machine
668 * to sleep or do other things that can interfere.
669 *
David Hendricks89a2adc2011-08-25 12:51:08 -0700670 */
David Hendricks37006402014-09-10 14:26:37 -0700671 if (write_it || erase_it)
David Hendricks42ad6522011-08-09 16:08:10 -0700672 disable_power_management();
673
David Hendricksf7924d12010-06-10 21:26:44 -0700674 /* FIXME: Delay calibration should happen in programmer code. */
675 myusec_calibrate_delay();
676
David Hendricksac1d25c2016-08-09 17:00:58 -0700677 if (programmer_init(prog, pparam)) {
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000678 msg_perr("Error: Programmer initialization failed.\n");
679 ret = 1;
680 goto out_shutdown;
David Hendricksf7924d12010-06-10 21:26:44 -0700681 }
Edward O'Callaghan4b940572019-08-02 01:44:47 +1000682 tempstr = flashbuses_to_text(get_buses_supported());
683 msg_pdbg("The following protocols are supported: %s.\n", tempstr);
684 free(tempstr);
685 tempstr = NULL;
686
Edward O'Callaghan20596a82019-06-13 14:47:03 +1000687 for (j = 0; j < registered_master_count; j++) {
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100688 startchip = 0;
Edward O'Callaghanbab067c2019-08-30 14:52:01 +1000689 while (chipcount < (int)ARRAY_SIZE(flashes)) {
Edward O'Callaghane9fa7372020-07-24 16:57:41 +1000690 startchip = probe_flash(&registered_masters[j], startchip, &flashes[chipcount], 0);
Edward O'Callaghan20596a82019-06-13 14:47:03 +1000691 if (startchip == -1)
692 break;
693 chipcount++;
694 startchip++;
695 }
David Hendricksf7924d12010-06-10 21:26:44 -0700696 }
697
David Hendricks91040832011-07-08 20:01:09 -0700698 if (chipcount > 1) {
Edward O'Callaghane9fa7372020-07-24 16:57:41 +1000699 msg_cinfo("Multiple flash chip definitions match the detected chip(s): \"%s\"",
700 flashes[0].chip->name);
701 for (i = 1; i < chipcount; i++)
702 msg_cinfo(", \"%s\"", flashes[i].chip->name);
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000703 msg_cinfo("\nPlease specify which chip definition to use with the -c <chipname> option.\n");
704 ret = 1;
705 goto out_shutdown;
David Hendricks91040832011-07-08 20:01:09 -0700706 } else if (!chipcount) {
Edward O'Callaghane9fa7372020-07-24 16:57:41 +1000707 msg_cinfo("No EEPROM/flash device found.\n");
David Hendricksf7924d12010-06-10 21:26:44 -0700708 if (!force || !chip_to_probe) {
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000709 msg_cinfo("Note: flashrom can never write if the flash chip isn't found "
710 "automatically.\n");
David Hendricksf7924d12010-06-10 21:26:44 -0700711 }
712 if (force && read_it && chip_to_probe) {
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100713 struct registered_master *mst;
714 int compatible_masters = 0;
715 msg_cinfo("Force read (-f -r -c) requested, pretending the chip is there:\n");
716 /* This loop just counts compatible controllers. */
717 for (j = 0; j < registered_master_count; j++) {
718 mst = &registered_masters[j];
719 /* chip is still set from the chip_to_probe earlier in this function. */
720 if (mst->buses_supported & chip->bustype)
721 compatible_masters++;
722 }
723 if (!compatible_masters) {
724 msg_cinfo("No compatible controller found for the requested flash chip.\n");
725 ret = 1;
726 goto out_shutdown;
727 }
728 if (compatible_masters > 1)
729 msg_cinfo("More than one compatible controller found for the requested flash "
730 "chip, using the first one.\n");
731 for (j = 0; j < registered_master_count; j++) {
732 mst = &registered_masters[j];
733 startchip = probe_flash(mst, 0, &flashes[0], 1);
734 if (startchip != -1)
735 break;
736 }
David Hendricks91040832011-07-08 20:01:09 -0700737 if (startchip == -1) {
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000738 // FIXME: This should never happen! Ask for a bug report?
739 msg_cinfo("Probing for flash chip '%s' failed.\n", chip_to_probe);
740 ret = 1;
741 goto out_shutdown;
David Hendricksf7924d12010-06-10 21:26:44 -0700742 }
Edward O'Callaghan79357b32020-08-02 01:24:58 +1000743 if (map_flash(&flashes[0]) != 0) {
744 free(flashes[0].chip);
745 ret = 1;
746 goto out_shutdown;
747 }
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000748 msg_cinfo("Please note that forced reads most likely contain garbage.\n");
Edward O'Callaghan79357b32020-08-02 01:24:58 +1000749 ret = read_flash_to_file(&flashes[0], filename);
750 unmap_flash(&flashes[0]);
751 free(flashes[0].chip);
752 goto out_shutdown;
David Hendricksf7924d12010-06-10 21:26:44 -0700753 }
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000754 ret = 1;
755 goto out_shutdown;
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100756 } else if (!chip_to_probe) {
757 /* repeat for convenience when looking at foreign logs */
758 tempstr = flashbuses_to_text(flashes[0].chip->bustype);
759 msg_gdbg("Found %s flash chip \"%s\" (%d kB, %s).\n",
760 flashes[0].chip->vendor, flashes[0].chip->name, flashes[0].chip->total_size, tempstr);
761 free(tempstr);
David Hendricksf7924d12010-06-10 21:26:44 -0700762 }
763
David Hendricks91040832011-07-08 20:01:09 -0700764 fill_flash = &flashes[0];
David Hendricksac1d25c2016-08-09 17:00:58 -0700765
Edward O'Callaghan71e30b42019-06-04 16:16:13 +1000766 print_chip_support_status(fill_flash->chip);
David Hendricksf7924d12010-06-10 21:26:44 -0700767
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100768 unsigned int limitexceeded = count_max_decode_exceedings(fill_flash);
769 if (limitexceeded > 0 && !force) {
770 enum chipbustype commonbuses = fill_flash->mst->buses_supported & fill_flash->chip->bustype;
771
772 /* Sometimes chip and programmer have more than one bus in common,
773 * and the limit is not exceeded on all buses. Tell the user. */
774 if ((bitcount(commonbuses) > limitexceeded)) {
775 msg_pdbg("There is at least one interface available which could support the size of\n"
776 "the selected flash chip.\n");
777 }
778 msg_cerr("This flash chip is too big for this programmer (--verbose/-V gives details).\n"
779 "Use --force/-f to override at your own risk.\n");
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000780 ret = 1;
781 goto out_shutdown;
David Hendricksf7924d12010-06-10 21:26:44 -0700782 }
783
Edward O'Callaghanbba5b762021-01-27 12:20:47 +1100784 if (!(read_it | write_it | verify_it | erase_it | flash_name | flash_size
785 | set_wp_range | set_wp_region | set_wp_enable |
David Hendricksc36685a2016-09-12 20:41:05 -0700786 set_wp_disable | wp_status | wp_list | extract_it)) {
Edward O'Callaghanbba5b762021-01-27 12:20:47 +1100787 msg_ginfo("No operations were specified.\n");
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000788 goto out_shutdown;
David Hendricksf7924d12010-06-10 21:26:44 -0700789 }
790
David Hendricksdf29a832013-06-28 14:33:51 -0700791 /*
792 * Common rules for -r/-w/-v syntax parsing:
793 * - If no filename is specified at all, quit.
794 * - If no filename is specified for -r/-w/-v, but files are specified
795 * for -i, then the number of file arguments for -i options must be
796 * equal to the total number of -i options.
797 *
798 * Rules for reading:
799 * - If files are specified for -i args but not -r, do partial reads for
800 * each -i arg, creating a new file for each region. Each -i option
801 * must specify a filename.
802 * - If filenames are specified for -r and -i args, then:
803 * - Do partial read for each -i arg, creating a new file for
804 * each region where a filename is provided (-i region:filename).
805 * - Create a ROM-sized file with partially filled content. For each
806 * -i arg, fill the corresponding offset with content from ROM.
807 *
808 * Rules for writing and verifying:
809 * - If files are specified for both -w/-v and -i args, -i files take
Daniel Campello8cb2f812021-04-27 18:04:01 -0600810 * priority.
David Hendricksdf29a832013-06-28 14:33:51 -0700811 * - If file is specified for -w/-v and no files are specified with -i
812 * args, then the file is to be used for writing/verifying the entire
813 * ROM.
814 * - If files are specified for -i args but not -w, do partial writes
815 * for each -i arg. Likewise for -v and -i args. All -i args must
816 * supply a filename. Any omission is considered ambiguous.
817 * - Regions with a filename associated must not overlap. This is also
818 * considered ambiguous. Note: This is checked later since it requires
819 * processing the layout/fmap first.
820 */
Daniel Campelloa07961a2021-04-22 09:20:11 -0600821 if ((read_it | write_it | verify_it) && !filename) {
822 struct layout_include_args *arg;
823 if (!include_args) {
824 msg_gerr("Error: No image file specified.\n");
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000825 ret = 1;
826 goto out_shutdown;
Duncan Laurie04ca1172015-03-12 09:25:34 -0700827 }
David Hendricksdf29a832013-06-28 14:33:51 -0700828
Daniel Campelloa07961a2021-04-22 09:20:11 -0600829 for (arg = include_args; arg; arg = arg->next) {
830 if (check_filename(arg->file, "region")) {
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000831 ret = 1;
832 goto out_shutdown;
David Hendricksdf29a832013-06-28 14:33:51 -0700833 }
David Hendricksdf29a832013-06-28 14:33:51 -0700834 }
David Hendricksf7924d12010-06-10 21:26:44 -0700835 }
836
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100837 if (set_wp_enable && set_wp_disable) {
838 msg_ginfo("Error: --wp-enable and --wp-disable are mutually exclusive\n");
839 ret = 1;
840 goto out_shutdown;
841 }
842 if (set_wp_range && set_wp_region) {
843 msg_gerr("Error: Cannot use both --wp-range and --wp-region simultaneously.\n");
844 ret = 1;
845 goto out_shutdown;
846 }
847
Nikolai Artemiev9d3980e2021-03-30 22:26:37 +1100848 struct wp *wp = get_wp_for_flashchip(fill_flash->chip);
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100849 if (set_wp_range || set_wp_region) {
Nikolai Artemiev9d3980e2021-03-30 22:26:37 +1100850 if (!wp || !wp->set_range) {
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100851 msg_gerr("Error: write protect is not supported on this flash chip.\n");
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000852 ret = 1;
853 goto out_shutdown;
Louis Yung-Chieh Lo78428182012-09-17 17:52:20 +0800854 }
David Hendricksc801adb2010-12-09 16:58:56 -0800855 }
856
David Hendricksf10ceb42011-12-20 21:21:18 -0800857 if (flash_name) {
Patrick Georgif3fa2992017-02-02 16:24:44 +0100858 if (fill_flash->chip->vendor && fill_flash->chip->name) {
Edward O'Callaghane9fa7372020-07-24 16:57:41 +1000859 printf("vendor=\"%s\" name=\"%s\"\n",
860 fill_flash->chip->vendor,
861 fill_flash->chip->name);
David Hendricksf10ceb42011-12-20 21:21:18 -0800862 } else {
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000863 ret = -1;
David Hendricksf10ceb42011-12-20 21:21:18 -0800864 }
Edward O'Callaghane9fa7372020-07-24 16:57:41 +1000865 goto out_shutdown;
David Hendricksf10ceb42011-12-20 21:21:18 -0800866 }
867
Edward O'Callaghanfdd9a1e2021-01-23 00:28:46 +1100868 if (flash_size) {
Edward O'Callaghana9bfa3d2021-02-16 14:28:00 +1100869 printf("%d\n", fill_flash->chip->total_size * 1024);
Edward O'Callaghanfdd9a1e2021-01-23 00:28:46 +1100870 goto out_shutdown;
871 }
872
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600873 if (layoutfile) {
874 layout = get_global_layout();
875 } else if (ifd && (flashrom_layout_read_from_ifd(&layout, fill_flash, NULL, 0) ||
876 process_include_args(layout, include_args))) {
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000877 ret = 1;
878 goto out_shutdown;
Daniel Campelloc7afa3a2021-04-26 07:04:14 -0600879 } else if (fmap && fmapfile &&
880 (flashrom_layout_read_fmap_from_file(&layout, fill_flash, fmapfile) ||
881 process_include_args(layout, include_args))) {
882 ret = 1;
883 goto out_shutdown;
884 } else if (!ifd && fmap &&
Daniel Campello241c6bf2021-04-19 09:58:47 -0600885 ((flashrom_layout_read_fmap_from_file(&layout, fill_flash, filename) &&
886 flashrom_layout_read_fmap_from_rom(&layout, fill_flash, 0,
887 fill_flash->chip->total_size * 1024)) ||
888 process_include_args(layout, include_args))) {
889 ret = 1;
890 goto out_shutdown;
David Hendrickse8c9d1a2016-10-28 20:11:52 -0700891 }
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600892 flashrom_layout_set(fill_flash, layout);
David Hendrickse8c9d1a2016-10-28 20:11:52 -0700893
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100894 if (wp_status) {
Nikolai Artemiev9d3980e2021-03-30 22:26:37 +1100895 if (wp && wp->wp_status) {
896 ret |= wp->wp_status(fill_flash);
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100897 } else {
898 msg_gerr("Error: write protect is not supported on this flash chip.\n");
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000899 ret = 1;
David Hendricksc36685a2016-09-12 20:41:05 -0700900 }
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600901 goto out_release;
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100902 }
David Hendricksc36685a2016-09-12 20:41:05 -0700903
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100904 /* Note: set_wp_disable should be done before setting the range */
905 if (set_wp_disable) {
Nikolai Artemiev9d3980e2021-03-30 22:26:37 +1100906 if (wp && wp->disable) {
907 ret |= wp->disable(fill_flash);
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100908 } else {
909 msg_gerr("Error: write protect is not supported on this flash chip.\n");
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000910 ret = 1;
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600911 goto out_release;
David Hendricksc36685a2016-09-12 20:41:05 -0700912 }
913 }
914
David Hendricksc801adb2010-12-09 16:58:56 -0800915 /* Note: set_wp_range must happen before set_wp_enable */
David Hendricksf7924d12010-06-10 21:26:44 -0700916 if (set_wp_range) {
Daniel Campello02bcfc92021-04-20 08:18:29 -0600917 ret |= wp->set_range(fill_flash, wp_start, wp_len);
David Hendricksc36685a2016-09-12 20:41:05 -0700918 }
919
920 if (set_wp_region && wp_region) {
Daniel Campello2fdc8372021-04-16 17:52:51 -0600921 if (get_region_range(layout, wp_region, &wp_start, &wp_len)) {
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000922 ret = 1;
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600923 goto out_release;
Louis Yung-Chieh Lo78428182012-09-17 17:52:20 +0800924 }
Daniel Campello2fdc8372021-04-16 17:52:51 -0600925 ret |= wp->set_range(fill_flash, wp_start, wp_len);
David Hendricksc36685a2016-09-12 20:41:05 -0700926 free(wp_region);
David Hendricksc801adb2010-12-09 16:58:56 -0800927 }
David Hendricksc36685a2016-09-12 20:41:05 -0700928
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000929 if (!ret && set_wp_enable) {
David Hendricks1c09f802012-10-03 11:03:48 -0700930 enum wp_mode wp_mode;
931
932 if (wp_mode_opt)
933 wp_mode = get_wp_mode(wp_mode_opt);
934 else
935 wp_mode = WP_MODE_HARDWARE; /* default */
936
937 if (wp_mode == WP_MODE_UNKNOWN) {
David Hendricks120495d2014-05-05 13:52:53 -0700938 msg_gerr("Error: Invalid WP mode: \"%s\"\n", wp_mode_opt);
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000939 ret = 1;
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600940 goto out_release;
David Hendricks1c09f802012-10-03 11:03:48 -0700941 }
942
Nikolai Artemiev9d3980e2021-03-30 22:26:37 +1100943 if (wp && wp->enable) {
944 ret |= wp->enable(fill_flash, wp_mode);
Louis Yung-Chieh Lo78428182012-09-17 17:52:20 +0800945 } else {
Edward O'Callaghan05f740b2020-10-22 12:32:39 +1100946 msg_gerr("Error: write protect is not supported on this flash chip.\n");
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000947 ret = 1;
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600948 goto out_release;
Louis Yung-Chieh Lo78428182012-09-17 17:52:20 +0800949 }
David Hendricksc801adb2010-12-09 16:58:56 -0800950 }
Edward O'Callaghan1a3fd132019-06-04 14:18:55 +1000951
David Hendricks0f7f5382011-02-11 18:12:31 -0800952 if (wp_list) {
David Hendricks77ea6bd2014-05-05 13:38:19 -0700953 msg_ginfo("Valid write protection ranges:\n");
Nikolai Artemiev9d3980e2021-03-30 22:26:37 +1100954 if (wp && wp->list_ranges) {
955 ret |= wp->list_ranges(fill_flash);
Louis Yung-Chieh Lo78428182012-09-17 17:52:20 +0800956 } else {
Edward O'Callaghan7580a522021-02-16 14:26:16 +1100957 msg_gerr("Error: write protect is not supported on this flash chip.\n");
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000958 ret = 1;
Louis Yung-Chieh Lo78428182012-09-17 17:52:20 +0800959 }
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600960 goto out_release;
David Hendricks0f7f5382011-02-11 18:12:31 -0800961 }
Louis Yung-Chieh Lobb9049c2011-05-10 16:06:28 +0800962
Edward O'Callaghanf0e80772020-12-04 15:36:04 +1100963 flashrom_flag_set(fill_flash, FLASHROM_FLAG_FORCE, !!force);
Daniel Campello15e10992021-04-19 15:17:33 -0600964 fill_flash->flags.do_not_diff = do_not_diff;
Edward O'Callaghan75f377d2021-01-27 12:17:42 +1100965#if CONFIG_INTERNAL == 1
966 flashrom_flag_set(fill_flash, FLASHROM_FLAG_FORCE_BOARDMISMATCH, !!force_boardmismatch);
967#endif
Edward O'Callaghanf0e80772020-12-04 15:36:04 +1100968 flashrom_flag_set(fill_flash, FLASHROM_FLAG_VERIFY_AFTER_WRITE, !dont_verify_it);
969 flashrom_flag_set(fill_flash, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, !dont_verify_all);
Edward O'Callaghan2c679272020-09-23 22:41:01 +1000970
Carl-Daniel Hailfinger11e5ecc2010-09-15 10:20:16 +0000971 /* FIXME: We should issue an unconditional chip reset here. This can be
972 * done once we have a .reset function in struct flashchip.
973 * Give the chip time to settle.
974 */
975 programmer_delay(100000);
Edward O'Callaghan020dfa12020-09-23 23:12:55 +1000976 if (read_it)
977 ret = do_read(fill_flash, filename);
Daniel Campello83752f82021-04-16 14:54:27 -0600978 else if (extract_it)
979 ret = do_extract(fill_flash);
Edward O'Callaghan020dfa12020-09-23 23:12:55 +1000980 else if (erase_it)
Edward O'Callaghan6e573be2020-12-18 10:38:06 +1100981 ret = do_erase(fill_flash);
Edward O'Callaghan020dfa12020-09-23 23:12:55 +1000982 else if (write_it)
Edward O'Callaghan5da5bb12021-01-22 23:41:45 +1100983 ret = do_write(fill_flash, filename, referencefile);
Edward O'Callaghan020dfa12020-09-23 23:12:55 +1000984 else if (verify_it)
Edward O'Callaghan6e573be2020-12-18 10:38:06 +1100985 ret = do_verify(fill_flash, filename);
David Hendricksc801adb2010-12-09 16:58:56 -0800986
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000987 msg_ginfo("%s\n", ret ? "FAILED" : "SUCCESS");
Edward O'Callaghan79357b32020-08-02 01:24:58 +1000988
Daniel Campelloc6e22b72021-04-19 12:47:16 -0600989out_release:
990 flashrom_layout_release(layout);
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +1000991out_shutdown:
Edward O'Callaghan44c28652021-01-27 11:20:00 +1100992 programmer_shutdown();
Edward O'Callaghan562c1d42020-08-19 12:45:04 +1000993out:
994
David Hendricksde007992011-01-27 20:02:09 -0800995#if USE_BIG_LOCK == 1
Shik Chen5fc35bc2012-08-07 17:51:42 +0800996 if (!set_ignore_lock)
997 release_big_lock();
David Hendricksde007992011-01-27 20:02:09 -0800998#endif
David Hendricks42ad6522011-08-09 16:08:10 -0700999 if (restore_power_management()) {
David Hendricks120495d2014-05-05 13:52:53 -07001000 msg_gerr("Unable to re-enable power management\n");
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +10001001 ret |= 1;
David Hendricks42ad6522011-08-09 16:08:10 -07001002 }
Edward O'Callaghan38cf0582021-01-22 01:00:23 +11001003 for (i = 0; i < chipcount; i++)
1004 free(flashes[i].chip);
Edward O'Callaghan627ca372019-09-07 18:52:30 +10001005
Edward O'Callaghan10bb9ae2020-12-17 13:06:10 +11001006 layout_cleanup(&include_args);
Daniel Campello17a3db92021-04-13 23:28:55 -06001007 free(filename);
Daniel Campelloc7afa3a2021-04-26 07:04:14 -06001008 free(fmapfile);
Edward O'Callaghan5da5bb12021-01-22 23:41:45 +11001009 free(referencefile);
Edward O'Callaghan38cf0582021-01-22 01:00:23 +11001010 free(layoutfile);
1011 free(pparam);
1012 /* clean up global variables */
1013 free((char *)chip_to_probe); /* Silence! Freeing is not modifying contents. */
1014 chip_to_probe = NULL;
Souvik Ghosh3c963a42016-07-19 18:48:15 -07001015#ifndef STANDALONE
Edward O'Callaghan64d1f172020-08-19 12:52:01 +10001016 free(logfile);
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +10001017 ret |= close_logfile();
Souvik Ghosh3c963a42016-07-19 18:48:15 -07001018#endif /* !STANDALONE */
Edward O'Callaghanc3c074c2019-09-06 14:06:37 +10001019 return ret;
David Hendricksf7924d12010-06-10 21:26:44 -07001020}