1*0d6140beSAndroid Build Coastguard Worker /*
2*0d6140beSAndroid Build Coastguard Worker * This file is part of the flashrom project.
3*0d6140beSAndroid Build Coastguard Worker *
4*0d6140beSAndroid Build Coastguard Worker * Copyright (C) 2000 Silicon Integrated System Corporation
5*0d6140beSAndroid Build Coastguard Worker * Copyright (C) 2004 Tyan Corp <[email protected]>
6*0d6140beSAndroid Build Coastguard Worker * Copyright (C) 2005-2008 coresystems GmbH
7*0d6140beSAndroid Build Coastguard Worker * Copyright (C) 2008,2009,2010 Carl-Daniel Hailfinger
8*0d6140beSAndroid Build Coastguard Worker *
9*0d6140beSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify
10*0d6140beSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
11*0d6140beSAndroid Build Coastguard Worker * the Free Software Foundation; either version 2 of the License, or
12*0d6140beSAndroid Build Coastguard Worker * (at your option) any later version.
13*0d6140beSAndroid Build Coastguard Worker *
14*0d6140beSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
15*0d6140beSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
16*0d6140beSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17*0d6140beSAndroid Build Coastguard Worker * GNU General Public License for more details.
18*0d6140beSAndroid Build Coastguard Worker */
19*0d6140beSAndroid Build Coastguard Worker
20*0d6140beSAndroid Build Coastguard Worker #include <errno.h>
21*0d6140beSAndroid Build Coastguard Worker #include <stdio.h>
22*0d6140beSAndroid Build Coastguard Worker #include <fcntl.h>
23*0d6140beSAndroid Build Coastguard Worker #include <sys/stat.h>
24*0d6140beSAndroid Build Coastguard Worker #include <string.h>
25*0d6140beSAndroid Build Coastguard Worker #include <stdbool.h>
26*0d6140beSAndroid Build Coastguard Worker #include <stdlib.h>
27*0d6140beSAndroid Build Coastguard Worker #include <cli_classic.h>
28*0d6140beSAndroid Build Coastguard Worker #include "flash.h"
29*0d6140beSAndroid Build Coastguard Worker #include "flashchips.h"
30*0d6140beSAndroid Build Coastguard Worker #include "fmap.h"
31*0d6140beSAndroid Build Coastguard Worker #include "programmer.h"
32*0d6140beSAndroid Build Coastguard Worker
33*0d6140beSAndroid Build Coastguard Worker #include "libflashrom.h"
34*0d6140beSAndroid Build Coastguard Worker
35*0d6140beSAndroid Build Coastguard Worker enum {
36*0d6140beSAndroid Build Coastguard Worker OPTION_IFD = 0x0100,
37*0d6140beSAndroid Build Coastguard Worker OPTION_FMAP,
38*0d6140beSAndroid Build Coastguard Worker OPTION_FMAP_FILE,
39*0d6140beSAndroid Build Coastguard Worker OPTION_FLASH_CONTENTS,
40*0d6140beSAndroid Build Coastguard Worker OPTION_FLASH_NAME,
41*0d6140beSAndroid Build Coastguard Worker OPTION_FLASH_SIZE,
42*0d6140beSAndroid Build Coastguard Worker OPTION_WP_STATUS,
43*0d6140beSAndroid Build Coastguard Worker OPTION_WP_SET_RANGE,
44*0d6140beSAndroid Build Coastguard Worker OPTION_WP_SET_REGION,
45*0d6140beSAndroid Build Coastguard Worker OPTION_WP_ENABLE,
46*0d6140beSAndroid Build Coastguard Worker OPTION_WP_DISABLE,
47*0d6140beSAndroid Build Coastguard Worker OPTION_WP_LIST,
48*0d6140beSAndroid Build Coastguard Worker OPTION_PROGRESS,
49*0d6140beSAndroid Build Coastguard Worker };
50*0d6140beSAndroid Build Coastguard Worker
51*0d6140beSAndroid Build Coastguard Worker struct cli_options {
52*0d6140beSAndroid Build Coastguard Worker bool read_it, extract_it, write_it, erase_it, verify_it;
53*0d6140beSAndroid Build Coastguard Worker bool dont_verify_it, dont_verify_all;
54*0d6140beSAndroid Build Coastguard Worker bool list_supported;
55*0d6140beSAndroid Build Coastguard Worker #if CONFIG_PRINT_WIKI == 1
56*0d6140beSAndroid Build Coastguard Worker bool list_supported_wiki;
57*0d6140beSAndroid Build Coastguard Worker #endif
58*0d6140beSAndroid Build Coastguard Worker char *filename;
59*0d6140beSAndroid Build Coastguard Worker
60*0d6140beSAndroid Build Coastguard Worker const struct programmer_entry *prog;
61*0d6140beSAndroid Build Coastguard Worker char *pparam;
62*0d6140beSAndroid Build Coastguard Worker
63*0d6140beSAndroid Build Coastguard Worker bool ifd, fmap;
64*0d6140beSAndroid Build Coastguard Worker struct flashrom_layout *layout;
65*0d6140beSAndroid Build Coastguard Worker struct layout_include_args *include_args;
66*0d6140beSAndroid Build Coastguard Worker char *layoutfile;
67*0d6140beSAndroid Build Coastguard Worker char *fmapfile;
68*0d6140beSAndroid Build Coastguard Worker
69*0d6140beSAndroid Build Coastguard Worker unsigned int wp_start, wp_len;
70*0d6140beSAndroid Build Coastguard Worker bool enable_wp, disable_wp, print_wp_status;
71*0d6140beSAndroid Build Coastguard Worker bool set_wp_range, set_wp_region, print_wp_ranges;
72*0d6140beSAndroid Build Coastguard Worker char *wp_region;
73*0d6140beSAndroid Build Coastguard Worker
74*0d6140beSAndroid Build Coastguard Worker bool force;
75*0d6140beSAndroid Build Coastguard Worker bool flash_name, flash_size;
76*0d6140beSAndroid Build Coastguard Worker bool show_progress;
77*0d6140beSAndroid Build Coastguard Worker char *logfile;
78*0d6140beSAndroid Build Coastguard Worker char *referencefile;
79*0d6140beSAndroid Build Coastguard Worker const char *chip_to_probe;
80*0d6140beSAndroid Build Coastguard Worker };
81*0d6140beSAndroid Build Coastguard Worker
cli_classic_usage(const char * name)82*0d6140beSAndroid Build Coastguard Worker static void cli_classic_usage(const char *name)
83*0d6140beSAndroid Build Coastguard Worker {
84*0d6140beSAndroid Build Coastguard Worker printf("Usage: %s [-h|-R|-L|"
85*0d6140beSAndroid Build Coastguard Worker #if CONFIG_PRINT_WIKI == 1
86*0d6140beSAndroid Build Coastguard Worker "-z|"
87*0d6140beSAndroid Build Coastguard Worker #endif
88*0d6140beSAndroid Build Coastguard Worker "\n\t-p <programmername>[:<parameters>] [-c <chipname>]\n"
89*0d6140beSAndroid Build Coastguard Worker "\t\t(--flash-name|--flash-size|\n"
90*0d6140beSAndroid Build Coastguard Worker "\t\t [-E|-x|(-r|-w|-v) [<file>]]\n"
91*0d6140beSAndroid Build Coastguard Worker "\t\t [(-l <layoutfile>|--ifd|--fmap|--fmap-file <fmapfile>) [-i <region>[:<file>]]...]\n"
92*0d6140beSAndroid Build Coastguard Worker "\t\t [-n] [-N] [-f])]\n"
93*0d6140beSAndroid Build Coastguard Worker "\t[-V[V[V]]] [-o <logfile>]\n\n", name);
94*0d6140beSAndroid Build Coastguard Worker
95*0d6140beSAndroid Build Coastguard Worker printf(" -h | --help print this help text\n"
96*0d6140beSAndroid Build Coastguard Worker " -R | --version print version (release)\n"
97*0d6140beSAndroid Build Coastguard Worker " -r | --read [<file>] read flash and save to <file>\n"
98*0d6140beSAndroid Build Coastguard Worker " -w | --write [<file>|-] write <file> or the content provided\n"
99*0d6140beSAndroid Build Coastguard Worker " on the standard input to flash\n"
100*0d6140beSAndroid Build Coastguard Worker " -v | --verify [<file>|-] verify flash against <file>\n"
101*0d6140beSAndroid Build Coastguard Worker " or the content provided on the standard input\n"
102*0d6140beSAndroid Build Coastguard Worker " -E | --erase erase flash memory\n"
103*0d6140beSAndroid Build Coastguard Worker " -V | --verbose more verbose output\n"
104*0d6140beSAndroid Build Coastguard Worker " -c | --chip <chipname> probe only for specified flash chip\n"
105*0d6140beSAndroid Build Coastguard Worker " -f | --force force specific operations (see man page)\n"
106*0d6140beSAndroid Build Coastguard Worker " -n | --noverify don't auto-verify\n"
107*0d6140beSAndroid Build Coastguard Worker " -N | --noverify-all verify included regions only (cf. -i)\n"
108*0d6140beSAndroid Build Coastguard Worker " -x | --extract extract regions to files\n"
109*0d6140beSAndroid Build Coastguard Worker " -l | --layout <layoutfile> read ROM layout from <layoutfile>\n"
110*0d6140beSAndroid Build Coastguard Worker " --wp-disable disable write protection\n"
111*0d6140beSAndroid Build Coastguard Worker " --wp-enable enable write protection\n"
112*0d6140beSAndroid Build Coastguard Worker " --wp-list list supported write protection ranges\n"
113*0d6140beSAndroid Build Coastguard Worker " --wp-status show write protection status\n"
114*0d6140beSAndroid Build Coastguard Worker " --wp-range=<start>,<len> set write protection range (use --wp-range=0,0\n"
115*0d6140beSAndroid Build Coastguard Worker " to unprotect the entire flash)\n"
116*0d6140beSAndroid Build Coastguard Worker " --wp-region <region> set write protection region\n"
117*0d6140beSAndroid Build Coastguard Worker " --flash-name read out the detected flash name\n"
118*0d6140beSAndroid Build Coastguard Worker " --flash-size read out the detected flash size\n"
119*0d6140beSAndroid Build Coastguard Worker " --fmap read ROM layout from fmap embedded in ROM\n"
120*0d6140beSAndroid Build Coastguard Worker " --fmap-file <fmapfile> read ROM layout from fmap in <fmapfile>\n"
121*0d6140beSAndroid Build Coastguard Worker " --ifd read layout from an Intel Firmware Descriptor\n"
122*0d6140beSAndroid Build Coastguard Worker " -i | --include <region>[:<file>] only read/write image <region> from layout\n"
123*0d6140beSAndroid Build Coastguard Worker " (optionally with data from <file>)\n"
124*0d6140beSAndroid Build Coastguard Worker " --image <region>[:<file>] deprecated, please use --include\n"
125*0d6140beSAndroid Build Coastguard Worker " -o | --output <logfile> log output to <logfile>\n"
126*0d6140beSAndroid Build Coastguard Worker " --flash-contents <ref-file> assume flash contents to be <ref-file>\n"
127*0d6140beSAndroid Build Coastguard Worker " -L | --list-supported print supported devices\n"
128*0d6140beSAndroid Build Coastguard Worker #if CONFIG_PRINT_WIKI == 1
129*0d6140beSAndroid Build Coastguard Worker " -z | --list-supported-wiki print supported devices in wiki syntax\n"
130*0d6140beSAndroid Build Coastguard Worker #endif
131*0d6140beSAndroid Build Coastguard Worker " --progress show progress percentage on the standard output\n"
132*0d6140beSAndroid Build Coastguard Worker " -p | --programmer <name>[:<param>] specify the programmer device. One of\n");
133*0d6140beSAndroid Build Coastguard Worker list_programmers_linebreak(4, 80, 0);
134*0d6140beSAndroid Build Coastguard Worker printf(".\n\nYou can specify one of -h, -R, -L, "
135*0d6140beSAndroid Build Coastguard Worker #if CONFIG_PRINT_WIKI == 1
136*0d6140beSAndroid Build Coastguard Worker "-z, "
137*0d6140beSAndroid Build Coastguard Worker #endif
138*0d6140beSAndroid Build Coastguard Worker "-E, -r, -w, -v or no operation.\n"
139*0d6140beSAndroid Build Coastguard Worker "If no operation is specified, flashrom will only probe for flash chips.\n");
140*0d6140beSAndroid Build Coastguard Worker }
141*0d6140beSAndroid Build Coastguard Worker
cli_classic_abort_usage(const char * msg)142*0d6140beSAndroid Build Coastguard Worker static void cli_classic_abort_usage(const char *msg)
143*0d6140beSAndroid Build Coastguard Worker {
144*0d6140beSAndroid Build Coastguard Worker if (msg)
145*0d6140beSAndroid Build Coastguard Worker fprintf(stderr, "%s", msg);
146*0d6140beSAndroid Build Coastguard Worker printf("Please run \"flashrom --help\" for usage info.\n");
147*0d6140beSAndroid Build Coastguard Worker exit(1);
148*0d6140beSAndroid Build Coastguard Worker }
149*0d6140beSAndroid Build Coastguard Worker
cli_classic_validate_singleop(int * operation_specified)150*0d6140beSAndroid Build Coastguard Worker static void cli_classic_validate_singleop(int *operation_specified)
151*0d6140beSAndroid Build Coastguard Worker {
152*0d6140beSAndroid Build Coastguard Worker if (++(*operation_specified) > 1) {
153*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("More than one operation specified. Aborting.\n");
154*0d6140beSAndroid Build Coastguard Worker }
155*0d6140beSAndroid Build Coastguard Worker }
156*0d6140beSAndroid Build Coastguard Worker
check_filename(char * filename,const char * type)157*0d6140beSAndroid Build Coastguard Worker static int check_filename(char *filename, const char *type)
158*0d6140beSAndroid Build Coastguard Worker {
159*0d6140beSAndroid Build Coastguard Worker if (!filename || (filename[0] == '\0')) {
160*0d6140beSAndroid Build Coastguard Worker fprintf(stderr, "Error: No %s file specified.\n", type);
161*0d6140beSAndroid Build Coastguard Worker return 1;
162*0d6140beSAndroid Build Coastguard Worker }
163*0d6140beSAndroid Build Coastguard Worker /* Not an error, but maybe the user intended to specify a CLI option instead of a file name. */
164*0d6140beSAndroid Build Coastguard Worker if (filename[0] == '-' && filename[1] != '\0')
165*0d6140beSAndroid Build Coastguard Worker fprintf(stderr, "Warning: Supplied %s file name starts with -\n", type);
166*0d6140beSAndroid Build Coastguard Worker return 0;
167*0d6140beSAndroid Build Coastguard Worker }
168*0d6140beSAndroid Build Coastguard Worker
169*0d6140beSAndroid Build Coastguard Worker /* Ensure a file is open by means of fstat */
check_file(FILE * file)170*0d6140beSAndroid Build Coastguard Worker static bool check_file(FILE *file)
171*0d6140beSAndroid Build Coastguard Worker {
172*0d6140beSAndroid Build Coastguard Worker struct stat statbuf;
173*0d6140beSAndroid Build Coastguard Worker
174*0d6140beSAndroid Build Coastguard Worker if (fstat(fileno(file), &statbuf) < 0)
175*0d6140beSAndroid Build Coastguard Worker return false;
176*0d6140beSAndroid Build Coastguard Worker return true;
177*0d6140beSAndroid Build Coastguard Worker }
178*0d6140beSAndroid Build Coastguard Worker
parse_wp_range(unsigned int * start,unsigned int * len)179*0d6140beSAndroid Build Coastguard Worker static int parse_wp_range(unsigned int *start, unsigned int *len)
180*0d6140beSAndroid Build Coastguard Worker {
181*0d6140beSAndroid Build Coastguard Worker char *endptr = NULL, *token = NULL;
182*0d6140beSAndroid Build Coastguard Worker
183*0d6140beSAndroid Build Coastguard Worker if (!optarg) {
184*0d6140beSAndroid Build Coastguard Worker msg_gerr("Error: No wp-range values provided\n");
185*0d6140beSAndroid Build Coastguard Worker return -1;
186*0d6140beSAndroid Build Coastguard Worker }
187*0d6140beSAndroid Build Coastguard Worker
188*0d6140beSAndroid Build Coastguard Worker token = strtok(optarg, ",");
189*0d6140beSAndroid Build Coastguard Worker if (!token) {
190*0d6140beSAndroid Build Coastguard Worker msg_gerr("Error: Invalid wp-range argument format\n");
191*0d6140beSAndroid Build Coastguard Worker return -1;
192*0d6140beSAndroid Build Coastguard Worker }
193*0d6140beSAndroid Build Coastguard Worker *start = strtoul(token, &endptr, 0);
194*0d6140beSAndroid Build Coastguard Worker
195*0d6140beSAndroid Build Coastguard Worker token = strtok(NULL, ",");
196*0d6140beSAndroid Build Coastguard Worker if (!token) {
197*0d6140beSAndroid Build Coastguard Worker msg_gerr("Error: Invalid wp-range argument format\n");
198*0d6140beSAndroid Build Coastguard Worker return -1;
199*0d6140beSAndroid Build Coastguard Worker }
200*0d6140beSAndroid Build Coastguard Worker *len = strtoul(token, &endptr, 0);
201*0d6140beSAndroid Build Coastguard Worker
202*0d6140beSAndroid Build Coastguard Worker return 0;
203*0d6140beSAndroid Build Coastguard Worker }
204*0d6140beSAndroid Build Coastguard Worker
print_wp_range(struct flashrom_flashctx * flash,size_t start,size_t len)205*0d6140beSAndroid Build Coastguard Worker static int print_wp_range(struct flashrom_flashctx *flash, size_t start, size_t len)
206*0d6140beSAndroid Build Coastguard Worker {
207*0d6140beSAndroid Build Coastguard Worker /* Start address and length */
208*0d6140beSAndroid Build Coastguard Worker msg_ginfo("start=0x%08zx length=0x%08zx ", start, len);
209*0d6140beSAndroid Build Coastguard Worker
210*0d6140beSAndroid Build Coastguard Worker /* Easily readable description like 'none' or 'lower 1/8' */
211*0d6140beSAndroid Build Coastguard Worker size_t chip_len = flashrom_flash_getsize(flash);
212*0d6140beSAndroid Build Coastguard Worker
213*0d6140beSAndroid Build Coastguard Worker if (len == 0) {
214*0d6140beSAndroid Build Coastguard Worker msg_ginfo("(none)");
215*0d6140beSAndroid Build Coastguard Worker } else if (len == chip_len) {
216*0d6140beSAndroid Build Coastguard Worker msg_ginfo("(all)");
217*0d6140beSAndroid Build Coastguard Worker } else {
218*0d6140beSAndroid Build Coastguard Worker const char *location = "";
219*0d6140beSAndroid Build Coastguard Worker if (start == 0)
220*0d6140beSAndroid Build Coastguard Worker location = "lower ";
221*0d6140beSAndroid Build Coastguard Worker if (start == chip_len - len)
222*0d6140beSAndroid Build Coastguard Worker location = "upper ";
223*0d6140beSAndroid Build Coastguard Worker
224*0d6140beSAndroid Build Coastguard Worker /* Remove common factors of 2 to simplify */
225*0d6140beSAndroid Build Coastguard Worker /* the (range_len/chip_len) fraction. */
226*0d6140beSAndroid Build Coastguard Worker while ((chip_len % 2) == 0 && (len % 2) == 0) {
227*0d6140beSAndroid Build Coastguard Worker chip_len /= 2;
228*0d6140beSAndroid Build Coastguard Worker len /= 2;
229*0d6140beSAndroid Build Coastguard Worker }
230*0d6140beSAndroid Build Coastguard Worker
231*0d6140beSAndroid Build Coastguard Worker msg_ginfo("(%s%zu/%zu)", location, len, chip_len);
232*0d6140beSAndroid Build Coastguard Worker }
233*0d6140beSAndroid Build Coastguard Worker
234*0d6140beSAndroid Build Coastguard Worker return 0;
235*0d6140beSAndroid Build Coastguard Worker }
236*0d6140beSAndroid Build Coastguard Worker
get_wp_error_str(int err)237*0d6140beSAndroid Build Coastguard Worker static const char *get_wp_error_str(int err)
238*0d6140beSAndroid Build Coastguard Worker {
239*0d6140beSAndroid Build Coastguard Worker switch (err) {
240*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_ERR_CHIP_UNSUPPORTED:
241*0d6140beSAndroid Build Coastguard Worker return "WP operations are not implemented for this chip";
242*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_ERR_READ_FAILED:
243*0d6140beSAndroid Build Coastguard Worker return "failed to read the current WP configuration";
244*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_ERR_WRITE_FAILED:
245*0d6140beSAndroid Build Coastguard Worker return "failed to write the new WP configuration";
246*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_ERR_VERIFY_FAILED:
247*0d6140beSAndroid Build Coastguard Worker return "unexpected WP configuration read back from chip";
248*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_ERR_MODE_UNSUPPORTED:
249*0d6140beSAndroid Build Coastguard Worker return "the requested protection mode is not supported";
250*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_ERR_RANGE_UNSUPPORTED:
251*0d6140beSAndroid Build Coastguard Worker return "the requested protection range is not supported";
252*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_ERR_RANGE_LIST_UNAVAILABLE:
253*0d6140beSAndroid Build Coastguard Worker return "could not determine what protection ranges are available";
254*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_ERR_UNSUPPORTED_STATE:
255*0d6140beSAndroid Build Coastguard Worker return "can't operate on current WP configuration of the chip";
256*0d6140beSAndroid Build Coastguard Worker }
257*0d6140beSAndroid Build Coastguard Worker return "unknown WP error";
258*0d6140beSAndroid Build Coastguard Worker }
259*0d6140beSAndroid Build Coastguard Worker
wp_cli(struct flashctx * flash,bool enable_wp,bool disable_wp,bool print_wp_status,bool print_wp_ranges,bool set_wp_range,uint32_t wp_start,uint32_t wp_len)260*0d6140beSAndroid Build Coastguard Worker static int wp_cli(
261*0d6140beSAndroid Build Coastguard Worker struct flashctx *flash,
262*0d6140beSAndroid Build Coastguard Worker bool enable_wp,
263*0d6140beSAndroid Build Coastguard Worker bool disable_wp,
264*0d6140beSAndroid Build Coastguard Worker bool print_wp_status,
265*0d6140beSAndroid Build Coastguard Worker bool print_wp_ranges,
266*0d6140beSAndroid Build Coastguard Worker bool set_wp_range,
267*0d6140beSAndroid Build Coastguard Worker uint32_t wp_start,
268*0d6140beSAndroid Build Coastguard Worker uint32_t wp_len)
269*0d6140beSAndroid Build Coastguard Worker {
270*0d6140beSAndroid Build Coastguard Worker if (print_wp_ranges) {
271*0d6140beSAndroid Build Coastguard Worker struct flashrom_wp_ranges *list;
272*0d6140beSAndroid Build Coastguard Worker enum flashrom_wp_result ret = flashrom_wp_get_available_ranges(&list, flash);
273*0d6140beSAndroid Build Coastguard Worker if (ret != FLASHROM_WP_OK) {
274*0d6140beSAndroid Build Coastguard Worker msg_gerr("Failed to get list of protection ranges: %s\n",
275*0d6140beSAndroid Build Coastguard Worker get_wp_error_str(ret));
276*0d6140beSAndroid Build Coastguard Worker return 1;
277*0d6140beSAndroid Build Coastguard Worker }
278*0d6140beSAndroid Build Coastguard Worker size_t count = flashrom_wp_ranges_get_count(list);
279*0d6140beSAndroid Build Coastguard Worker
280*0d6140beSAndroid Build Coastguard Worker msg_ginfo("Available protection ranges:\n");
281*0d6140beSAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++) {
282*0d6140beSAndroid Build Coastguard Worker size_t start, len;
283*0d6140beSAndroid Build Coastguard Worker
284*0d6140beSAndroid Build Coastguard Worker flashrom_wp_ranges_get_range(&start, &len, list, i);
285*0d6140beSAndroid Build Coastguard Worker msg_ginfo("\t");
286*0d6140beSAndroid Build Coastguard Worker print_wp_range(flash, start, len);
287*0d6140beSAndroid Build Coastguard Worker msg_ginfo("\n");
288*0d6140beSAndroid Build Coastguard Worker }
289*0d6140beSAndroid Build Coastguard Worker
290*0d6140beSAndroid Build Coastguard Worker flashrom_wp_ranges_release(list);
291*0d6140beSAndroid Build Coastguard Worker }
292*0d6140beSAndroid Build Coastguard Worker
293*0d6140beSAndroid Build Coastguard Worker if (set_wp_range || disable_wp || enable_wp) {
294*0d6140beSAndroid Build Coastguard Worker enum flashrom_wp_mode old_mode = FLASHROM_WP_MODE_DISABLED;
295*0d6140beSAndroid Build Coastguard Worker struct flashrom_wp_cfg *cfg = NULL;
296*0d6140beSAndroid Build Coastguard Worker enum flashrom_wp_result ret = flashrom_wp_cfg_new(&cfg);
297*0d6140beSAndroid Build Coastguard Worker
298*0d6140beSAndroid Build Coastguard Worker if (ret == FLASHROM_WP_OK)
299*0d6140beSAndroid Build Coastguard Worker ret = flashrom_wp_read_cfg(cfg, flash);
300*0d6140beSAndroid Build Coastguard Worker
301*0d6140beSAndroid Build Coastguard Worker if (ret == FLASHROM_WP_OK) {
302*0d6140beSAndroid Build Coastguard Worker /* Store current WP mode for printing help text if */
303*0d6140beSAndroid Build Coastguard Worker /* changing the cfg fails. */
304*0d6140beSAndroid Build Coastguard Worker old_mode = flashrom_wp_get_mode(cfg);
305*0d6140beSAndroid Build Coastguard Worker
306*0d6140beSAndroid Build Coastguard Worker if (set_wp_range)
307*0d6140beSAndroid Build Coastguard Worker flashrom_wp_set_range(cfg, wp_start, wp_len);
308*0d6140beSAndroid Build Coastguard Worker
309*0d6140beSAndroid Build Coastguard Worker if (disable_wp)
310*0d6140beSAndroid Build Coastguard Worker flashrom_wp_set_mode(cfg, FLASHROM_WP_MODE_DISABLED);
311*0d6140beSAndroid Build Coastguard Worker
312*0d6140beSAndroid Build Coastguard Worker if (enable_wp)
313*0d6140beSAndroid Build Coastguard Worker flashrom_wp_set_mode(cfg, FLASHROM_WP_MODE_HARDWARE);
314*0d6140beSAndroid Build Coastguard Worker
315*0d6140beSAndroid Build Coastguard Worker ret = flashrom_wp_write_cfg(flash, cfg);
316*0d6140beSAndroid Build Coastguard Worker }
317*0d6140beSAndroid Build Coastguard Worker
318*0d6140beSAndroid Build Coastguard Worker flashrom_wp_cfg_release(cfg);
319*0d6140beSAndroid Build Coastguard Worker
320*0d6140beSAndroid Build Coastguard Worker if (ret != FLASHROM_WP_OK) {
321*0d6140beSAndroid Build Coastguard Worker msg_gerr("Failed to apply new WP settings: %s\n",
322*0d6140beSAndroid Build Coastguard Worker get_wp_error_str(ret));
323*0d6140beSAndroid Build Coastguard Worker
324*0d6140beSAndroid Build Coastguard Worker /* Warn user if active WP is likely to have caused failure */
325*0d6140beSAndroid Build Coastguard Worker if (ret == FLASHROM_WP_ERR_VERIFY_FAILED) {
326*0d6140beSAndroid Build Coastguard Worker switch (old_mode) {
327*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_MODE_HARDWARE:
328*0d6140beSAndroid Build Coastguard Worker msg_gerr("Note: hardware status register protection is enabled. "
329*0d6140beSAndroid Build Coastguard Worker "The chip's WP# pin must be set to an inactive voltage "
330*0d6140beSAndroid Build Coastguard Worker "level to be able to change the WP settings.\n");
331*0d6140beSAndroid Build Coastguard Worker break;
332*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_MODE_POWER_CYCLE:
333*0d6140beSAndroid Build Coastguard Worker msg_gerr("Note: power-cycle status register protection is enabled. "
334*0d6140beSAndroid Build Coastguard Worker "A power-off, power-on cycle is usually required to change "
335*0d6140beSAndroid Build Coastguard Worker "the chip's WP settings.\n");
336*0d6140beSAndroid Build Coastguard Worker break;
337*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_MODE_PERMANENT:
338*0d6140beSAndroid Build Coastguard Worker msg_gerr("Note: permanent status register protection is enabled. "
339*0d6140beSAndroid Build Coastguard Worker "The chip's WP settings cannot be modified.\n");
340*0d6140beSAndroid Build Coastguard Worker break;
341*0d6140beSAndroid Build Coastguard Worker default:
342*0d6140beSAndroid Build Coastguard Worker break;
343*0d6140beSAndroid Build Coastguard Worker }
344*0d6140beSAndroid Build Coastguard Worker }
345*0d6140beSAndroid Build Coastguard Worker
346*0d6140beSAndroid Build Coastguard Worker return 1;
347*0d6140beSAndroid Build Coastguard Worker }
348*0d6140beSAndroid Build Coastguard Worker
349*0d6140beSAndroid Build Coastguard Worker if (disable_wp)
350*0d6140beSAndroid Build Coastguard Worker msg_ginfo("Disabled hardware protection\n");
351*0d6140beSAndroid Build Coastguard Worker
352*0d6140beSAndroid Build Coastguard Worker if (enable_wp)
353*0d6140beSAndroid Build Coastguard Worker msg_ginfo("Enabled hardware protection\n");
354*0d6140beSAndroid Build Coastguard Worker
355*0d6140beSAndroid Build Coastguard Worker if (set_wp_range) {
356*0d6140beSAndroid Build Coastguard Worker msg_ginfo("Activated protection range: ");
357*0d6140beSAndroid Build Coastguard Worker print_wp_range(flash, wp_start, wp_len);
358*0d6140beSAndroid Build Coastguard Worker msg_ginfo("\n");
359*0d6140beSAndroid Build Coastguard Worker }
360*0d6140beSAndroid Build Coastguard Worker }
361*0d6140beSAndroid Build Coastguard Worker
362*0d6140beSAndroid Build Coastguard Worker if (print_wp_status) {
363*0d6140beSAndroid Build Coastguard Worker size_t start, len;
364*0d6140beSAndroid Build Coastguard Worker enum flashrom_wp_mode mode;
365*0d6140beSAndroid Build Coastguard Worker struct flashrom_wp_cfg *cfg = NULL;
366*0d6140beSAndroid Build Coastguard Worker enum flashrom_wp_result ret = flashrom_wp_cfg_new(&cfg);
367*0d6140beSAndroid Build Coastguard Worker
368*0d6140beSAndroid Build Coastguard Worker if (ret == FLASHROM_WP_OK)
369*0d6140beSAndroid Build Coastguard Worker ret = flashrom_wp_read_cfg(cfg, flash);
370*0d6140beSAndroid Build Coastguard Worker
371*0d6140beSAndroid Build Coastguard Worker if (ret != FLASHROM_WP_OK) {
372*0d6140beSAndroid Build Coastguard Worker msg_gerr("Failed to get WP status: %s\n",
373*0d6140beSAndroid Build Coastguard Worker get_wp_error_str(ret));
374*0d6140beSAndroid Build Coastguard Worker
375*0d6140beSAndroid Build Coastguard Worker flashrom_wp_cfg_release(cfg);
376*0d6140beSAndroid Build Coastguard Worker return 1;
377*0d6140beSAndroid Build Coastguard Worker }
378*0d6140beSAndroid Build Coastguard Worker
379*0d6140beSAndroid Build Coastguard Worker flashrom_wp_get_range(&start, &len, cfg);
380*0d6140beSAndroid Build Coastguard Worker mode = flashrom_wp_get_mode(cfg);
381*0d6140beSAndroid Build Coastguard Worker flashrom_wp_cfg_release(cfg);
382*0d6140beSAndroid Build Coastguard Worker
383*0d6140beSAndroid Build Coastguard Worker msg_ginfo("Protection range: ");
384*0d6140beSAndroid Build Coastguard Worker print_wp_range(flash, start, len);
385*0d6140beSAndroid Build Coastguard Worker msg_ginfo("\n");
386*0d6140beSAndroid Build Coastguard Worker
387*0d6140beSAndroid Build Coastguard Worker msg_ginfo("Protection mode: ");
388*0d6140beSAndroid Build Coastguard Worker switch (mode) {
389*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_MODE_DISABLED:
390*0d6140beSAndroid Build Coastguard Worker msg_ginfo("disabled");
391*0d6140beSAndroid Build Coastguard Worker break;
392*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_MODE_HARDWARE:
393*0d6140beSAndroid Build Coastguard Worker msg_ginfo("hardware");
394*0d6140beSAndroid Build Coastguard Worker break;
395*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_MODE_POWER_CYCLE:
396*0d6140beSAndroid Build Coastguard Worker msg_ginfo("power_cycle");
397*0d6140beSAndroid Build Coastguard Worker break;
398*0d6140beSAndroid Build Coastguard Worker case FLASHROM_WP_MODE_PERMANENT:
399*0d6140beSAndroid Build Coastguard Worker msg_ginfo("permanent");
400*0d6140beSAndroid Build Coastguard Worker break;
401*0d6140beSAndroid Build Coastguard Worker default:
402*0d6140beSAndroid Build Coastguard Worker msg_ginfo("unknown");
403*0d6140beSAndroid Build Coastguard Worker break;
404*0d6140beSAndroid Build Coastguard Worker }
405*0d6140beSAndroid Build Coastguard Worker msg_ginfo("\n");
406*0d6140beSAndroid Build Coastguard Worker }
407*0d6140beSAndroid Build Coastguard Worker
408*0d6140beSAndroid Build Coastguard Worker return 0;
409*0d6140beSAndroid Build Coastguard Worker }
410*0d6140beSAndroid Build Coastguard Worker
get_optional_filename(char * argv[])411*0d6140beSAndroid Build Coastguard Worker static char *get_optional_filename(char *argv[])
412*0d6140beSAndroid Build Coastguard Worker {
413*0d6140beSAndroid Build Coastguard Worker char *filename = NULL;
414*0d6140beSAndroid Build Coastguard Worker
415*0d6140beSAndroid Build Coastguard Worker /* filename was supplied in optarg (i.e. -rfilename) */
416*0d6140beSAndroid Build Coastguard Worker if (optarg != NULL)
417*0d6140beSAndroid Build Coastguard Worker filename = strdup(optarg);
418*0d6140beSAndroid Build Coastguard Worker /* filename is on optind if it is not another flag (i.e. -r filename)
419*0d6140beSAndroid Build Coastguard Worker * - is treated as stdin, so we still strdup in this case
420*0d6140beSAndroid Build Coastguard Worker */
421*0d6140beSAndroid Build Coastguard Worker else if (optarg == NULL && argv[optind] != NULL &&
422*0d6140beSAndroid Build Coastguard Worker (argv[optind][0] != '-' || argv[optind][1] == '\0'))
423*0d6140beSAndroid Build Coastguard Worker filename = strdup(argv[optind++]);
424*0d6140beSAndroid Build Coastguard Worker
425*0d6140beSAndroid Build Coastguard Worker return filename;
426*0d6140beSAndroid Build Coastguard Worker }
427*0d6140beSAndroid Build Coastguard Worker
flashrom_layout_read_fmap_from_file(struct flashrom_layout ** layout,struct flashrom_flashctx * flashctx,const char * fmapfile)428*0d6140beSAndroid Build Coastguard Worker static int flashrom_layout_read_fmap_from_file(struct flashrom_layout **layout,
429*0d6140beSAndroid Build Coastguard Worker struct flashrom_flashctx *flashctx, const char *fmapfile)
430*0d6140beSAndroid Build Coastguard Worker {
431*0d6140beSAndroid Build Coastguard Worker int ret = 1;
432*0d6140beSAndroid Build Coastguard Worker struct stat s;
433*0d6140beSAndroid Build Coastguard Worker if (stat(fmapfile, &s) != 0) {
434*0d6140beSAndroid Build Coastguard Worker return ret;
435*0d6140beSAndroid Build Coastguard Worker }
436*0d6140beSAndroid Build Coastguard Worker
437*0d6140beSAndroid Build Coastguard Worker size_t fmapfile_size = s.st_size;
438*0d6140beSAndroid Build Coastguard Worker uint8_t *fmapfile_buffer = malloc(fmapfile_size);
439*0d6140beSAndroid Build Coastguard Worker if (!fmapfile_buffer) {
440*0d6140beSAndroid Build Coastguard Worker return ret;
441*0d6140beSAndroid Build Coastguard Worker }
442*0d6140beSAndroid Build Coastguard Worker
443*0d6140beSAndroid Build Coastguard Worker if (read_buf_from_file(fmapfile_buffer, fmapfile_size, fmapfile)) {
444*0d6140beSAndroid Build Coastguard Worker goto out;
445*0d6140beSAndroid Build Coastguard Worker }
446*0d6140beSAndroid Build Coastguard Worker
447*0d6140beSAndroid Build Coastguard Worker ret = flashrom_layout_read_fmap_from_buffer(layout, flashctx, fmapfile_buffer, fmapfile_size);
448*0d6140beSAndroid Build Coastguard Worker out:
449*0d6140beSAndroid Build Coastguard Worker free(fmapfile_buffer);
450*0d6140beSAndroid Build Coastguard Worker return ret;
451*0d6140beSAndroid Build Coastguard Worker }
452*0d6140beSAndroid Build Coastguard Worker
453*0d6140beSAndroid Build Coastguard Worker /**
454*0d6140beSAndroid Build Coastguard Worker * @brief Reads content to buffer from one or more files.
455*0d6140beSAndroid Build Coastguard Worker *
456*0d6140beSAndroid Build Coastguard Worker * Reads content to supplied buffer from files. If a filename is specified for
457*0d6140beSAndroid Build Coastguard Worker * individual regions using the partial read syntax ('-i <region>[:<filename>]')
458*0d6140beSAndroid Build Coastguard Worker * then this will read file data into the corresponding region in the
459*0d6140beSAndroid Build Coastguard Worker * supplied buffer.
460*0d6140beSAndroid Build Coastguard Worker *
461*0d6140beSAndroid Build Coastguard Worker * @param layout The layout to be used.
462*0d6140beSAndroid Build Coastguard Worker * @param buf Chip-sized buffer to write data to
463*0d6140beSAndroid Build Coastguard Worker * @return 0 on success
464*0d6140beSAndroid Build Coastguard Worker */
read_buf_from_include_args(const struct flashrom_layout * const layout,unsigned char * buf)465*0d6140beSAndroid Build Coastguard Worker static int read_buf_from_include_args(const struct flashrom_layout *const layout, unsigned char *buf)
466*0d6140beSAndroid Build Coastguard Worker {
467*0d6140beSAndroid Build Coastguard Worker const struct romentry *entry = NULL;
468*0d6140beSAndroid Build Coastguard Worker
469*0d6140beSAndroid Build Coastguard Worker /*
470*0d6140beSAndroid Build Coastguard Worker * Content will be read from -i args, so they must not overlap since
471*0d6140beSAndroid Build Coastguard Worker * we need to know exactly what content to write to the ROM.
472*0d6140beSAndroid Build Coastguard Worker */
473*0d6140beSAndroid Build Coastguard Worker if (included_regions_overlap(layout)) {
474*0d6140beSAndroid Build Coastguard Worker msg_gerr("Error: Included regions must not overlap when writing.\n");
475*0d6140beSAndroid Build Coastguard Worker return 1;
476*0d6140beSAndroid Build Coastguard Worker }
477*0d6140beSAndroid Build Coastguard Worker
478*0d6140beSAndroid Build Coastguard Worker while ((entry = layout_next_included(layout, entry))) {
479*0d6140beSAndroid Build Coastguard Worker if (!entry->file)
480*0d6140beSAndroid Build Coastguard Worker continue;
481*0d6140beSAndroid Build Coastguard Worker const struct flash_region *region = &entry->region;
482*0d6140beSAndroid Build Coastguard Worker if (read_buf_from_file(buf + region->start,
483*0d6140beSAndroid Build Coastguard Worker region->end - region->start + 1, entry->file))
484*0d6140beSAndroid Build Coastguard Worker return 1;
485*0d6140beSAndroid Build Coastguard Worker }
486*0d6140beSAndroid Build Coastguard Worker return 0;
487*0d6140beSAndroid Build Coastguard Worker }
488*0d6140beSAndroid Build Coastguard Worker
489*0d6140beSAndroid Build Coastguard Worker /**
490*0d6140beSAndroid Build Coastguard Worker * @brief Writes content from buffer to one or more files.
491*0d6140beSAndroid Build Coastguard Worker *
492*0d6140beSAndroid Build Coastguard Worker * Writes content from supplied buffer to files. If a filename is specified for
493*0d6140beSAndroid Build Coastguard Worker * individual regions using the partial read syntax ('-i <region>[:<filename>]')
494*0d6140beSAndroid Build Coastguard Worker * then this will write files using data from the corresponding region in the
495*0d6140beSAndroid Build Coastguard Worker * supplied buffer.
496*0d6140beSAndroid Build Coastguard Worker *
497*0d6140beSAndroid Build Coastguard Worker * @param layout The layout to be used.
498*0d6140beSAndroid Build Coastguard Worker * @param buf Chip-sized buffer to read data from
499*0d6140beSAndroid Build Coastguard Worker * @return 0 on success
500*0d6140beSAndroid Build Coastguard Worker */
write_buf_to_include_args(const struct flashrom_layout * const layout,unsigned char * buf)501*0d6140beSAndroid Build Coastguard Worker static int write_buf_to_include_args(const struct flashrom_layout *const layout, unsigned char *buf)
502*0d6140beSAndroid Build Coastguard Worker {
503*0d6140beSAndroid Build Coastguard Worker const struct romentry *entry = NULL;
504*0d6140beSAndroid Build Coastguard Worker
505*0d6140beSAndroid Build Coastguard Worker while ((entry = layout_next_included(layout, entry))) {
506*0d6140beSAndroid Build Coastguard Worker if (!entry->file)
507*0d6140beSAndroid Build Coastguard Worker continue;
508*0d6140beSAndroid Build Coastguard Worker const struct flash_region *region = &entry->region;
509*0d6140beSAndroid Build Coastguard Worker if (write_buf_to_file(buf + region->start,
510*0d6140beSAndroid Build Coastguard Worker region->end - region->start + 1, entry->file))
511*0d6140beSAndroid Build Coastguard Worker return 1;
512*0d6140beSAndroid Build Coastguard Worker }
513*0d6140beSAndroid Build Coastguard Worker
514*0d6140beSAndroid Build Coastguard Worker return 0;
515*0d6140beSAndroid Build Coastguard Worker }
516*0d6140beSAndroid Build Coastguard Worker
do_read(struct flashctx * const flash,const char * const filename)517*0d6140beSAndroid Build Coastguard Worker static int do_read(struct flashctx *const flash, const char *const filename)
518*0d6140beSAndroid Build Coastguard Worker {
519*0d6140beSAndroid Build Coastguard Worker int ret;
520*0d6140beSAndroid Build Coastguard Worker
521*0d6140beSAndroid Build Coastguard Worker unsigned long size = flashrom_flash_getsize(flash);
522*0d6140beSAndroid Build Coastguard Worker unsigned char *buf = calloc(size, sizeof(unsigned char));
523*0d6140beSAndroid Build Coastguard Worker if (!buf) {
524*0d6140beSAndroid Build Coastguard Worker msg_gerr("Memory allocation failed!\n");
525*0d6140beSAndroid Build Coastguard Worker return 1;
526*0d6140beSAndroid Build Coastguard Worker }
527*0d6140beSAndroid Build Coastguard Worker
528*0d6140beSAndroid Build Coastguard Worker ret = flashrom_image_read(flash, buf, size);
529*0d6140beSAndroid Build Coastguard Worker if (ret > 0)
530*0d6140beSAndroid Build Coastguard Worker goto free_out;
531*0d6140beSAndroid Build Coastguard Worker
532*0d6140beSAndroid Build Coastguard Worker if (write_buf_to_include_args(get_layout(flash), buf)) {
533*0d6140beSAndroid Build Coastguard Worker ret = 1;
534*0d6140beSAndroid Build Coastguard Worker goto free_out;
535*0d6140beSAndroid Build Coastguard Worker }
536*0d6140beSAndroid Build Coastguard Worker if (filename)
537*0d6140beSAndroid Build Coastguard Worker ret = write_buf_to_file(buf, size, filename);
538*0d6140beSAndroid Build Coastguard Worker
539*0d6140beSAndroid Build Coastguard Worker free_out:
540*0d6140beSAndroid Build Coastguard Worker free(buf);
541*0d6140beSAndroid Build Coastguard Worker return ret;
542*0d6140beSAndroid Build Coastguard Worker }
543*0d6140beSAndroid Build Coastguard Worker
do_extract(struct flashctx * const flash)544*0d6140beSAndroid Build Coastguard Worker static int do_extract(struct flashctx *const flash)
545*0d6140beSAndroid Build Coastguard Worker {
546*0d6140beSAndroid Build Coastguard Worker prepare_layout_for_extraction(flash);
547*0d6140beSAndroid Build Coastguard Worker return do_read(flash, NULL);
548*0d6140beSAndroid Build Coastguard Worker }
549*0d6140beSAndroid Build Coastguard Worker
do_write(struct flashctx * const flash,const char * const filename,const char * const referencefile)550*0d6140beSAndroid Build Coastguard Worker static int do_write(struct flashctx *const flash, const char *const filename, const char *const referencefile)
551*0d6140beSAndroid Build Coastguard Worker {
552*0d6140beSAndroid Build Coastguard Worker const size_t flash_size = flashrom_flash_getsize(flash);
553*0d6140beSAndroid Build Coastguard Worker int ret = 1;
554*0d6140beSAndroid Build Coastguard Worker
555*0d6140beSAndroid Build Coastguard Worker uint8_t *const newcontents = malloc(flash_size);
556*0d6140beSAndroid Build Coastguard Worker uint8_t *const refcontents = referencefile ? malloc(flash_size) : NULL;
557*0d6140beSAndroid Build Coastguard Worker
558*0d6140beSAndroid Build Coastguard Worker if (!newcontents || (referencefile && !refcontents)) {
559*0d6140beSAndroid Build Coastguard Worker msg_gerr("Out of memory!\n");
560*0d6140beSAndroid Build Coastguard Worker goto _free_ret;
561*0d6140beSAndroid Build Coastguard Worker }
562*0d6140beSAndroid Build Coastguard Worker
563*0d6140beSAndroid Build Coastguard Worker /* Read '-w' argument first... */
564*0d6140beSAndroid Build Coastguard Worker if (filename) {
565*0d6140beSAndroid Build Coastguard Worker if (read_buf_from_file(newcontents, flash_size, filename))
566*0d6140beSAndroid Build Coastguard Worker goto _free_ret;
567*0d6140beSAndroid Build Coastguard Worker }
568*0d6140beSAndroid Build Coastguard Worker /*
569*0d6140beSAndroid Build Coastguard Worker * ... then update newcontents with contents from files provided to '-i'
570*0d6140beSAndroid Build Coastguard Worker * args if needed.
571*0d6140beSAndroid Build Coastguard Worker */
572*0d6140beSAndroid Build Coastguard Worker if (read_buf_from_include_args(get_layout(flash), newcontents))
573*0d6140beSAndroid Build Coastguard Worker goto _free_ret;
574*0d6140beSAndroid Build Coastguard Worker
575*0d6140beSAndroid Build Coastguard Worker if (referencefile) {
576*0d6140beSAndroid Build Coastguard Worker if (read_buf_from_file(refcontents, flash_size, referencefile))
577*0d6140beSAndroid Build Coastguard Worker goto _free_ret;
578*0d6140beSAndroid Build Coastguard Worker }
579*0d6140beSAndroid Build Coastguard Worker
580*0d6140beSAndroid Build Coastguard Worker ret = flashrom_image_write(flash, newcontents, flash_size, refcontents);
581*0d6140beSAndroid Build Coastguard Worker
582*0d6140beSAndroid Build Coastguard Worker _free_ret:
583*0d6140beSAndroid Build Coastguard Worker free(refcontents);
584*0d6140beSAndroid Build Coastguard Worker free(newcontents);
585*0d6140beSAndroid Build Coastguard Worker return ret;
586*0d6140beSAndroid Build Coastguard Worker }
587*0d6140beSAndroid Build Coastguard Worker
do_verify(struct flashctx * const flash,const char * const filename)588*0d6140beSAndroid Build Coastguard Worker static int do_verify(struct flashctx *const flash, const char *const filename)
589*0d6140beSAndroid Build Coastguard Worker {
590*0d6140beSAndroid Build Coastguard Worker const size_t flash_size = flashrom_flash_getsize(flash);
591*0d6140beSAndroid Build Coastguard Worker int ret = 1;
592*0d6140beSAndroid Build Coastguard Worker
593*0d6140beSAndroid Build Coastguard Worker uint8_t *const newcontents = malloc(flash_size);
594*0d6140beSAndroid Build Coastguard Worker if (!newcontents) {
595*0d6140beSAndroid Build Coastguard Worker msg_gerr("Out of memory!\n");
596*0d6140beSAndroid Build Coastguard Worker goto _free_ret;
597*0d6140beSAndroid Build Coastguard Worker }
598*0d6140beSAndroid Build Coastguard Worker
599*0d6140beSAndroid Build Coastguard Worker /* Read '-v' argument first... */
600*0d6140beSAndroid Build Coastguard Worker if (filename) {
601*0d6140beSAndroid Build Coastguard Worker if (read_buf_from_file(newcontents, flash_size, filename))
602*0d6140beSAndroid Build Coastguard Worker goto _free_ret;
603*0d6140beSAndroid Build Coastguard Worker }
604*0d6140beSAndroid Build Coastguard Worker /*
605*0d6140beSAndroid Build Coastguard Worker * ... then update newcontents with contents from files provided to '-i'
606*0d6140beSAndroid Build Coastguard Worker * args if needed.
607*0d6140beSAndroid Build Coastguard Worker */
608*0d6140beSAndroid Build Coastguard Worker if (read_buf_from_include_args(get_layout(flash), newcontents))
609*0d6140beSAndroid Build Coastguard Worker goto _free_ret;
610*0d6140beSAndroid Build Coastguard Worker
611*0d6140beSAndroid Build Coastguard Worker ret = flashrom_image_verify(flash, newcontents, flash_size);
612*0d6140beSAndroid Build Coastguard Worker
613*0d6140beSAndroid Build Coastguard Worker _free_ret:
614*0d6140beSAndroid Build Coastguard Worker free(newcontents);
615*0d6140beSAndroid Build Coastguard Worker return ret;
616*0d6140beSAndroid Build Coastguard Worker }
617*0d6140beSAndroid Build Coastguard Worker
618*0d6140beSAndroid Build Coastguard Worker /* Returns the number of buses commonly supported by the current programmer and flash chip where the latter
619*0d6140beSAndroid Build Coastguard Worker * can not be completely accessed due to size/address limits of the programmer. */
count_max_decode_exceedings(const struct flashctx * flash,const struct decode_sizes * max_rom_decode_)620*0d6140beSAndroid Build Coastguard Worker static unsigned int count_max_decode_exceedings(const struct flashctx *flash,
621*0d6140beSAndroid Build Coastguard Worker const struct decode_sizes *max_rom_decode_)
622*0d6140beSAndroid Build Coastguard Worker {
623*0d6140beSAndroid Build Coastguard Worker unsigned int limitexceeded = 0;
624*0d6140beSAndroid Build Coastguard Worker uint32_t size = flash->chip->total_size * 1024;
625*0d6140beSAndroid Build Coastguard Worker enum chipbustype buses = flash->mst->buses_supported & flash->chip->bustype;
626*0d6140beSAndroid Build Coastguard Worker
627*0d6140beSAndroid Build Coastguard Worker if ((buses & BUS_PARALLEL) && (max_rom_decode_->parallel < size)) {
628*0d6140beSAndroid Build Coastguard Worker limitexceeded++;
629*0d6140beSAndroid Build Coastguard Worker msg_pdbg("Chip size %"PRIu32" kB is bigger than supported "
630*0d6140beSAndroid Build Coastguard Worker "size %"PRIu32" kB of chipset/board/programmer "
631*0d6140beSAndroid Build Coastguard Worker "for %s interface, "
632*0d6140beSAndroid Build Coastguard Worker "probe/read/erase/write may fail. ", size / 1024,
633*0d6140beSAndroid Build Coastguard Worker max_rom_decode_->parallel / 1024, "Parallel");
634*0d6140beSAndroid Build Coastguard Worker }
635*0d6140beSAndroid Build Coastguard Worker if ((buses & BUS_LPC) && (max_rom_decode_->lpc < size)) {
636*0d6140beSAndroid Build Coastguard Worker limitexceeded++;
637*0d6140beSAndroid Build Coastguard Worker msg_pdbg("Chip size %"PRIu32" kB is bigger than supported "
638*0d6140beSAndroid Build Coastguard Worker "size %"PRIu32" kB of chipset/board/programmer "
639*0d6140beSAndroid Build Coastguard Worker "for %s interface, "
640*0d6140beSAndroid Build Coastguard Worker "probe/read/erase/write may fail. ", size / 1024,
641*0d6140beSAndroid Build Coastguard Worker max_rom_decode_->lpc / 1024, "LPC");
642*0d6140beSAndroid Build Coastguard Worker }
643*0d6140beSAndroid Build Coastguard Worker if ((buses & BUS_FWH) && (max_rom_decode_->fwh < size)) {
644*0d6140beSAndroid Build Coastguard Worker limitexceeded++;
645*0d6140beSAndroid Build Coastguard Worker msg_pdbg("Chip size %"PRIu32" kB is bigger than supported "
646*0d6140beSAndroid Build Coastguard Worker "size %"PRIu32" kB of chipset/board/programmer "
647*0d6140beSAndroid Build Coastguard Worker "for %s interface, "
648*0d6140beSAndroid Build Coastguard Worker "probe/read/erase/write may fail. ", size / 1024,
649*0d6140beSAndroid Build Coastguard Worker max_rom_decode_->fwh / 1024, "FWH");
650*0d6140beSAndroid Build Coastguard Worker }
651*0d6140beSAndroid Build Coastguard Worker if ((buses & BUS_SPI) && (max_rom_decode_->spi < size)) {
652*0d6140beSAndroid Build Coastguard Worker limitexceeded++;
653*0d6140beSAndroid Build Coastguard Worker msg_pdbg("Chip size %"PRIu32" kB is bigger than supported "
654*0d6140beSAndroid Build Coastguard Worker "size %"PRIu32" kB of chipset/board/programmer "
655*0d6140beSAndroid Build Coastguard Worker "for %s interface, "
656*0d6140beSAndroid Build Coastguard Worker "probe/read/erase/write may fail. ", size / 1024,
657*0d6140beSAndroid Build Coastguard Worker max_rom_decode_->spi / 1024, "SPI");
658*0d6140beSAndroid Build Coastguard Worker }
659*0d6140beSAndroid Build Coastguard Worker return limitexceeded;
660*0d6140beSAndroid Build Coastguard Worker }
661*0d6140beSAndroid Build Coastguard Worker
parse_options(int argc,char ** argv,const char * optstring,const struct option * long_options,struct cli_options * options)662*0d6140beSAndroid Build Coastguard Worker static void parse_options(int argc, char **argv, const char *optstring,
663*0d6140beSAndroid Build Coastguard Worker const struct option *long_options,
664*0d6140beSAndroid Build Coastguard Worker struct cli_options *options)
665*0d6140beSAndroid Build Coastguard Worker {
666*0d6140beSAndroid Build Coastguard Worker const char *name;
667*0d6140beSAndroid Build Coastguard Worker int namelen, opt;
668*0d6140beSAndroid Build Coastguard Worker int option_index = 0, operation_specified = 0;
669*0d6140beSAndroid Build Coastguard Worker
670*0d6140beSAndroid Build Coastguard Worker /* FIXME: Delay all operation_specified checks until after command
671*0d6140beSAndroid Build Coastguard Worker * line parsing to allow --help overriding everything else.
672*0d6140beSAndroid Build Coastguard Worker */
673*0d6140beSAndroid Build Coastguard Worker while ((opt = getopt_long(argc, argv, optstring,
674*0d6140beSAndroid Build Coastguard Worker long_options, &option_index)) != EOF) {
675*0d6140beSAndroid Build Coastguard Worker switch (opt) {
676*0d6140beSAndroid Build Coastguard Worker case 'r':
677*0d6140beSAndroid Build Coastguard Worker cli_classic_validate_singleop(&operation_specified);
678*0d6140beSAndroid Build Coastguard Worker options->filename = get_optional_filename(argv);
679*0d6140beSAndroid Build Coastguard Worker options->read_it = true;
680*0d6140beSAndroid Build Coastguard Worker break;
681*0d6140beSAndroid Build Coastguard Worker case 'w':
682*0d6140beSAndroid Build Coastguard Worker cli_classic_validate_singleop(&operation_specified);
683*0d6140beSAndroid Build Coastguard Worker options->filename = get_optional_filename(argv);
684*0d6140beSAndroid Build Coastguard Worker options->write_it = true;
685*0d6140beSAndroid Build Coastguard Worker break;
686*0d6140beSAndroid Build Coastguard Worker case 'v':
687*0d6140beSAndroid Build Coastguard Worker //FIXME: gracefully handle superfluous -v
688*0d6140beSAndroid Build Coastguard Worker cli_classic_validate_singleop(&operation_specified);
689*0d6140beSAndroid Build Coastguard Worker if (options->dont_verify_it) {
690*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("--verify and --noverify are mutually exclusive. Aborting.\n");
691*0d6140beSAndroid Build Coastguard Worker }
692*0d6140beSAndroid Build Coastguard Worker options->filename = get_optional_filename(argv);
693*0d6140beSAndroid Build Coastguard Worker options->verify_it = true;
694*0d6140beSAndroid Build Coastguard Worker break;
695*0d6140beSAndroid Build Coastguard Worker case 'n':
696*0d6140beSAndroid Build Coastguard Worker if (options->verify_it) {
697*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("--verify and --noverify are mutually exclusive. Aborting.\n");
698*0d6140beSAndroid Build Coastguard Worker }
699*0d6140beSAndroid Build Coastguard Worker options->dont_verify_it = true;
700*0d6140beSAndroid Build Coastguard Worker break;
701*0d6140beSAndroid Build Coastguard Worker case 'N':
702*0d6140beSAndroid Build Coastguard Worker options->dont_verify_all = true;
703*0d6140beSAndroid Build Coastguard Worker break;
704*0d6140beSAndroid Build Coastguard Worker case 'x':
705*0d6140beSAndroid Build Coastguard Worker cli_classic_validate_singleop(&operation_specified);
706*0d6140beSAndroid Build Coastguard Worker options->extract_it = true;
707*0d6140beSAndroid Build Coastguard Worker break;
708*0d6140beSAndroid Build Coastguard Worker case 'c':
709*0d6140beSAndroid Build Coastguard Worker options->chip_to_probe = strdup(optarg);
710*0d6140beSAndroid Build Coastguard Worker break;
711*0d6140beSAndroid Build Coastguard Worker case 'V':
712*0d6140beSAndroid Build Coastguard Worker verbose_screen++;
713*0d6140beSAndroid Build Coastguard Worker if (verbose_screen > FLASHROM_MSG_DEBUG2)
714*0d6140beSAndroid Build Coastguard Worker verbose_logfile = verbose_screen;
715*0d6140beSAndroid Build Coastguard Worker break;
716*0d6140beSAndroid Build Coastguard Worker case 'E':
717*0d6140beSAndroid Build Coastguard Worker cli_classic_validate_singleop(&operation_specified);
718*0d6140beSAndroid Build Coastguard Worker options->erase_it = true;
719*0d6140beSAndroid Build Coastguard Worker break;
720*0d6140beSAndroid Build Coastguard Worker case 'f':
721*0d6140beSAndroid Build Coastguard Worker options->force = true;
722*0d6140beSAndroid Build Coastguard Worker break;
723*0d6140beSAndroid Build Coastguard Worker case 'l':
724*0d6140beSAndroid Build Coastguard Worker if (options->layoutfile)
725*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: --layout specified more than once. Aborting.\n");
726*0d6140beSAndroid Build Coastguard Worker if (options->ifd)
727*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: --layout and --ifd both specified. Aborting.\n");
728*0d6140beSAndroid Build Coastguard Worker if (options->fmap)
729*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: --layout and --fmap-file both specified. Aborting.\n");
730*0d6140beSAndroid Build Coastguard Worker options->layoutfile = strdup(optarg);
731*0d6140beSAndroid Build Coastguard Worker break;
732*0d6140beSAndroid Build Coastguard Worker case OPTION_IFD:
733*0d6140beSAndroid Build Coastguard Worker if (options->layoutfile)
734*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: --layout and --ifd both specified. Aborting.\n");
735*0d6140beSAndroid Build Coastguard Worker if (options->fmap)
736*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: --fmap-file and --ifd both specified. Aborting.\n");
737*0d6140beSAndroid Build Coastguard Worker options->ifd = true;
738*0d6140beSAndroid Build Coastguard Worker break;
739*0d6140beSAndroid Build Coastguard Worker case OPTION_FMAP_FILE:
740*0d6140beSAndroid Build Coastguard Worker if (options->fmap)
741*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: --fmap or --fmap-file specified "
742*0d6140beSAndroid Build Coastguard Worker "more than once. Aborting.\n");
743*0d6140beSAndroid Build Coastguard Worker if (options->ifd)
744*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: --fmap-file and --ifd both specified. Aborting.\n");
745*0d6140beSAndroid Build Coastguard Worker if (options->layoutfile)
746*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: --fmap-file and --layout both specified. Aborting.\n");
747*0d6140beSAndroid Build Coastguard Worker options->fmapfile = strdup(optarg);
748*0d6140beSAndroid Build Coastguard Worker options->fmap = true;
749*0d6140beSAndroid Build Coastguard Worker break;
750*0d6140beSAndroid Build Coastguard Worker case OPTION_FMAP:
751*0d6140beSAndroid Build Coastguard Worker if (options->fmap)
752*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: --fmap or --fmap-file specified "
753*0d6140beSAndroid Build Coastguard Worker "more than once. Aborting.\n");
754*0d6140beSAndroid Build Coastguard Worker if (options->ifd)
755*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: --fmap and --ifd both specified. Aborting.\n");
756*0d6140beSAndroid Build Coastguard Worker if (options->layoutfile)
757*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: --layout and --fmap both specified. Aborting.\n");
758*0d6140beSAndroid Build Coastguard Worker options->fmap = true;
759*0d6140beSAndroid Build Coastguard Worker break;
760*0d6140beSAndroid Build Coastguard Worker case 'i':
761*0d6140beSAndroid Build Coastguard Worker if (register_include_arg(&options->include_args, optarg))
762*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage(NULL);
763*0d6140beSAndroid Build Coastguard Worker break;
764*0d6140beSAndroid Build Coastguard Worker case OPTION_FLASH_CONTENTS:
765*0d6140beSAndroid Build Coastguard Worker if (options->referencefile)
766*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: --flash-contents specified more than once."
767*0d6140beSAndroid Build Coastguard Worker "Aborting.\n");
768*0d6140beSAndroid Build Coastguard Worker options->referencefile = strdup(optarg);
769*0d6140beSAndroid Build Coastguard Worker break;
770*0d6140beSAndroid Build Coastguard Worker case OPTION_FLASH_NAME:
771*0d6140beSAndroid Build Coastguard Worker cli_classic_validate_singleop(&operation_specified);
772*0d6140beSAndroid Build Coastguard Worker options->flash_name = true;
773*0d6140beSAndroid Build Coastguard Worker break;
774*0d6140beSAndroid Build Coastguard Worker case OPTION_FLASH_SIZE:
775*0d6140beSAndroid Build Coastguard Worker cli_classic_validate_singleop(&operation_specified);
776*0d6140beSAndroid Build Coastguard Worker options->flash_size = true;
777*0d6140beSAndroid Build Coastguard Worker break;
778*0d6140beSAndroid Build Coastguard Worker case OPTION_WP_STATUS:
779*0d6140beSAndroid Build Coastguard Worker options->print_wp_status = true;
780*0d6140beSAndroid Build Coastguard Worker break;
781*0d6140beSAndroid Build Coastguard Worker case OPTION_WP_LIST:
782*0d6140beSAndroid Build Coastguard Worker options->print_wp_ranges = true;
783*0d6140beSAndroid Build Coastguard Worker break;
784*0d6140beSAndroid Build Coastguard Worker case OPTION_WP_SET_RANGE:
785*0d6140beSAndroid Build Coastguard Worker if (parse_wp_range(&options->wp_start, &options->wp_len) < 0)
786*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Incorrect wp-range arguments provided.\n");
787*0d6140beSAndroid Build Coastguard Worker
788*0d6140beSAndroid Build Coastguard Worker options->set_wp_range = true;
789*0d6140beSAndroid Build Coastguard Worker break;
790*0d6140beSAndroid Build Coastguard Worker case OPTION_WP_SET_REGION:
791*0d6140beSAndroid Build Coastguard Worker options->set_wp_region = true;
792*0d6140beSAndroid Build Coastguard Worker options->wp_region = strdup(optarg);
793*0d6140beSAndroid Build Coastguard Worker break;
794*0d6140beSAndroid Build Coastguard Worker case OPTION_WP_ENABLE:
795*0d6140beSAndroid Build Coastguard Worker options->enable_wp = true;
796*0d6140beSAndroid Build Coastguard Worker break;
797*0d6140beSAndroid Build Coastguard Worker case OPTION_WP_DISABLE:
798*0d6140beSAndroid Build Coastguard Worker options->disable_wp = true;
799*0d6140beSAndroid Build Coastguard Worker break;
800*0d6140beSAndroid Build Coastguard Worker case 'L':
801*0d6140beSAndroid Build Coastguard Worker cli_classic_validate_singleop(&operation_specified);
802*0d6140beSAndroid Build Coastguard Worker options->list_supported = true;
803*0d6140beSAndroid Build Coastguard Worker break;
804*0d6140beSAndroid Build Coastguard Worker case 'z':
805*0d6140beSAndroid Build Coastguard Worker #if CONFIG_PRINT_WIKI == 1
806*0d6140beSAndroid Build Coastguard Worker cli_classic_validate_singleop(&operation_specified);
807*0d6140beSAndroid Build Coastguard Worker options->list_supported_wiki = true;
808*0d6140beSAndroid Build Coastguard Worker #else
809*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: Wiki output was not "
810*0d6140beSAndroid Build Coastguard Worker "compiled in. Aborting.\n");
811*0d6140beSAndroid Build Coastguard Worker #endif
812*0d6140beSAndroid Build Coastguard Worker break;
813*0d6140beSAndroid Build Coastguard Worker case 'p':
814*0d6140beSAndroid Build Coastguard Worker if (options->prog != NULL) {
815*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: --programmer specified "
816*0d6140beSAndroid Build Coastguard Worker "more than once. You can separate "
817*0d6140beSAndroid Build Coastguard Worker "multiple\nparameters for a programmer "
818*0d6140beSAndroid Build Coastguard Worker "with \",\". Please see the man page "
819*0d6140beSAndroid Build Coastguard Worker "for details.\n");
820*0d6140beSAndroid Build Coastguard Worker }
821*0d6140beSAndroid Build Coastguard Worker size_t p;
822*0d6140beSAndroid Build Coastguard Worker for (p = 0; p < programmer_table_size; p++) {
823*0d6140beSAndroid Build Coastguard Worker name = programmer_table[p]->name;
824*0d6140beSAndroid Build Coastguard Worker namelen = strlen(name);
825*0d6140beSAndroid Build Coastguard Worker if (strncmp(optarg, name, namelen) == 0) {
826*0d6140beSAndroid Build Coastguard Worker switch (optarg[namelen]) {
827*0d6140beSAndroid Build Coastguard Worker case ':':
828*0d6140beSAndroid Build Coastguard Worker options->pparam = strdup(optarg + namelen + 1);
829*0d6140beSAndroid Build Coastguard Worker if (!strlen(options->pparam)) {
830*0d6140beSAndroid Build Coastguard Worker free(options->pparam);
831*0d6140beSAndroid Build Coastguard Worker options->pparam = NULL;
832*0d6140beSAndroid Build Coastguard Worker }
833*0d6140beSAndroid Build Coastguard Worker options->prog = programmer_table[p];
834*0d6140beSAndroid Build Coastguard Worker break;
835*0d6140beSAndroid Build Coastguard Worker case '\0':
836*0d6140beSAndroid Build Coastguard Worker options->prog = programmer_table[p];
837*0d6140beSAndroid Build Coastguard Worker break;
838*0d6140beSAndroid Build Coastguard Worker default:
839*0d6140beSAndroid Build Coastguard Worker /* The continue refers to the
840*0d6140beSAndroid Build Coastguard Worker * for loop. It is here to be
841*0d6140beSAndroid Build Coastguard Worker * able to differentiate between
842*0d6140beSAndroid Build Coastguard Worker * foo and foobar.
843*0d6140beSAndroid Build Coastguard Worker */
844*0d6140beSAndroid Build Coastguard Worker continue;
845*0d6140beSAndroid Build Coastguard Worker }
846*0d6140beSAndroid Build Coastguard Worker break;
847*0d6140beSAndroid Build Coastguard Worker }
848*0d6140beSAndroid Build Coastguard Worker }
849*0d6140beSAndroid Build Coastguard Worker if (options->prog == NULL) {
850*0d6140beSAndroid Build Coastguard Worker fprintf(stderr, "Error: Unknown programmer \"%s\". Valid choices are:\n",
851*0d6140beSAndroid Build Coastguard Worker optarg);
852*0d6140beSAndroid Build Coastguard Worker list_programmers_linebreak(0, 80, 0);
853*0d6140beSAndroid Build Coastguard Worker msg_ginfo(".\n");
854*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage(NULL);
855*0d6140beSAndroid Build Coastguard Worker }
856*0d6140beSAndroid Build Coastguard Worker break;
857*0d6140beSAndroid Build Coastguard Worker case 'R':
858*0d6140beSAndroid Build Coastguard Worker /* print_version() is always called during startup. */
859*0d6140beSAndroid Build Coastguard Worker cli_classic_validate_singleop(&operation_specified);
860*0d6140beSAndroid Build Coastguard Worker exit(0);
861*0d6140beSAndroid Build Coastguard Worker break;
862*0d6140beSAndroid Build Coastguard Worker case 'h':
863*0d6140beSAndroid Build Coastguard Worker cli_classic_validate_singleop(&operation_specified);
864*0d6140beSAndroid Build Coastguard Worker cli_classic_usage(argv[0]);
865*0d6140beSAndroid Build Coastguard Worker exit(0);
866*0d6140beSAndroid Build Coastguard Worker break;
867*0d6140beSAndroid Build Coastguard Worker case 'o':
868*0d6140beSAndroid Build Coastguard Worker if (options->logfile) {
869*0d6140beSAndroid Build Coastguard Worker fprintf(stderr, "Warning: -o/--output specified multiple times.\n");
870*0d6140beSAndroid Build Coastguard Worker free(options->logfile);
871*0d6140beSAndroid Build Coastguard Worker }
872*0d6140beSAndroid Build Coastguard Worker
873*0d6140beSAndroid Build Coastguard Worker options->logfile = strdup(optarg);
874*0d6140beSAndroid Build Coastguard Worker if (options->logfile[0] == '\0') {
875*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("No log filename specified.\n");
876*0d6140beSAndroid Build Coastguard Worker }
877*0d6140beSAndroid Build Coastguard Worker break;
878*0d6140beSAndroid Build Coastguard Worker case OPTION_PROGRESS:
879*0d6140beSAndroid Build Coastguard Worker options->show_progress = true;
880*0d6140beSAndroid Build Coastguard Worker break;
881*0d6140beSAndroid Build Coastguard Worker default:
882*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage(NULL);
883*0d6140beSAndroid Build Coastguard Worker break;
884*0d6140beSAndroid Build Coastguard Worker }
885*0d6140beSAndroid Build Coastguard Worker }
886*0d6140beSAndroid Build Coastguard Worker
887*0d6140beSAndroid Build Coastguard Worker if (optind < argc)
888*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage("Error: Extra parameter found.\n");
889*0d6140beSAndroid Build Coastguard Worker }
890*0d6140beSAndroid Build Coastguard Worker
free_options(struct cli_options * options)891*0d6140beSAndroid Build Coastguard Worker static void free_options(struct cli_options *options)
892*0d6140beSAndroid Build Coastguard Worker {
893*0d6140beSAndroid Build Coastguard Worker cleanup_include_args(&options->include_args);
894*0d6140beSAndroid Build Coastguard Worker free(options->filename);
895*0d6140beSAndroid Build Coastguard Worker free(options->fmapfile);
896*0d6140beSAndroid Build Coastguard Worker free(options->referencefile);
897*0d6140beSAndroid Build Coastguard Worker free(options->layoutfile);
898*0d6140beSAndroid Build Coastguard Worker free(options->pparam);
899*0d6140beSAndroid Build Coastguard Worker free(options->wp_region);
900*0d6140beSAndroid Build Coastguard Worker free(options->logfile);
901*0d6140beSAndroid Build Coastguard Worker free((char *)options->chip_to_probe);
902*0d6140beSAndroid Build Coastguard Worker }
903*0d6140beSAndroid Build Coastguard Worker
main(int argc,char * argv[])904*0d6140beSAndroid Build Coastguard Worker int main(int argc, char *argv[])
905*0d6140beSAndroid Build Coastguard Worker {
906*0d6140beSAndroid Build Coastguard Worker const struct flashchip *chip = NULL;
907*0d6140beSAndroid Build Coastguard Worker /* Probe for up to eight flash chips. */
908*0d6140beSAndroid Build Coastguard Worker struct flashctx flashes[8] = {{0}};
909*0d6140beSAndroid Build Coastguard Worker struct flashctx *fill_flash;
910*0d6140beSAndroid Build Coastguard Worker char *tempstr = NULL;
911*0d6140beSAndroid Build Coastguard Worker int startchip = -1, chipcount = 0;
912*0d6140beSAndroid Build Coastguard Worker int i, j;
913*0d6140beSAndroid Build Coastguard Worker int ret = 0;
914*0d6140beSAndroid Build Coastguard Worker
915*0d6140beSAndroid Build Coastguard Worker struct cli_options options = { 0 };
916*0d6140beSAndroid Build Coastguard Worker static const char optstring[] = "r::Rw::v::nNVEfc:l:i:p:Lzho:x";
917*0d6140beSAndroid Build Coastguard Worker static const struct option long_options[] = {
918*0d6140beSAndroid Build Coastguard Worker {"read", 2, NULL, 'r'},
919*0d6140beSAndroid Build Coastguard Worker {"write", 2, NULL, 'w'},
920*0d6140beSAndroid Build Coastguard Worker {"erase", 0, NULL, 'E'},
921*0d6140beSAndroid Build Coastguard Worker {"verify", 2, NULL, 'v'},
922*0d6140beSAndroid Build Coastguard Worker {"noverify", 0, NULL, 'n'},
923*0d6140beSAndroid Build Coastguard Worker {"noverify-all", 0, NULL, 'N'},
924*0d6140beSAndroid Build Coastguard Worker {"extract", 0, NULL, 'x'},
925*0d6140beSAndroid Build Coastguard Worker {"chip", 1, NULL, 'c'},
926*0d6140beSAndroid Build Coastguard Worker {"verbose", 0, NULL, 'V'},
927*0d6140beSAndroid Build Coastguard Worker {"force", 0, NULL, 'f'},
928*0d6140beSAndroid Build Coastguard Worker {"layout", 1, NULL, 'l'},
929*0d6140beSAndroid Build Coastguard Worker {"ifd", 0, NULL, OPTION_IFD},
930*0d6140beSAndroid Build Coastguard Worker {"fmap", 0, NULL, OPTION_FMAP},
931*0d6140beSAndroid Build Coastguard Worker {"fmap-file", 1, NULL, OPTION_FMAP_FILE},
932*0d6140beSAndroid Build Coastguard Worker {"image", 1, NULL, 'i'}, // (deprecated): back compatibility.
933*0d6140beSAndroid Build Coastguard Worker {"include", 1, NULL, 'i'},
934*0d6140beSAndroid Build Coastguard Worker {"flash-contents", 1, NULL, OPTION_FLASH_CONTENTS},
935*0d6140beSAndroid Build Coastguard Worker {"flash-name", 0, NULL, OPTION_FLASH_NAME},
936*0d6140beSAndroid Build Coastguard Worker {"flash-size", 0, NULL, OPTION_FLASH_SIZE},
937*0d6140beSAndroid Build Coastguard Worker {"get-size", 0, NULL, OPTION_FLASH_SIZE}, // (deprecated): back compatibility.
938*0d6140beSAndroid Build Coastguard Worker {"wp-status", 0, NULL, OPTION_WP_STATUS},
939*0d6140beSAndroid Build Coastguard Worker {"wp-list", 0, NULL, OPTION_WP_LIST},
940*0d6140beSAndroid Build Coastguard Worker {"wp-range", 1, NULL, OPTION_WP_SET_RANGE},
941*0d6140beSAndroid Build Coastguard Worker {"wp-region", 1, NULL, OPTION_WP_SET_REGION},
942*0d6140beSAndroid Build Coastguard Worker {"wp-enable", 0, NULL, OPTION_WP_ENABLE},
943*0d6140beSAndroid Build Coastguard Worker {"wp-disable", 0, NULL, OPTION_WP_DISABLE},
944*0d6140beSAndroid Build Coastguard Worker {"list-supported", 0, NULL, 'L'},
945*0d6140beSAndroid Build Coastguard Worker {"list-supported-wiki", 0, NULL, 'z'},
946*0d6140beSAndroid Build Coastguard Worker {"programmer", 1, NULL, 'p'},
947*0d6140beSAndroid Build Coastguard Worker {"help", 0, NULL, 'h'},
948*0d6140beSAndroid Build Coastguard Worker {"version", 0, NULL, 'R'},
949*0d6140beSAndroid Build Coastguard Worker {"output", 1, NULL, 'o'},
950*0d6140beSAndroid Build Coastguard Worker {"progress", 0, NULL, OPTION_PROGRESS},
951*0d6140beSAndroid Build Coastguard Worker {NULL, 0, NULL, 0},
952*0d6140beSAndroid Build Coastguard Worker };
953*0d6140beSAndroid Build Coastguard Worker
954*0d6140beSAndroid Build Coastguard Worker /*
955*0d6140beSAndroid Build Coastguard Worker * Safety-guard against a user who has (mistakenly) closed
956*0d6140beSAndroid Build Coastguard Worker * stdout or stderr before exec'ing flashrom. We disable
957*0d6140beSAndroid Build Coastguard Worker * logging in this case to prevent writing log data to a flash
958*0d6140beSAndroid Build Coastguard Worker * chip when a flash device gets opened with fd 1 or 2.
959*0d6140beSAndroid Build Coastguard Worker */
960*0d6140beSAndroid Build Coastguard Worker if (check_file(stdout) && check_file(stderr)) {
961*0d6140beSAndroid Build Coastguard Worker flashrom_set_log_callback(&flashrom_print_cb);
962*0d6140beSAndroid Build Coastguard Worker }
963*0d6140beSAndroid Build Coastguard Worker
964*0d6140beSAndroid Build Coastguard Worker print_version();
965*0d6140beSAndroid Build Coastguard Worker print_banner();
966*0d6140beSAndroid Build Coastguard Worker
967*0d6140beSAndroid Build Coastguard Worker setbuf(stdout, NULL);
968*0d6140beSAndroid Build Coastguard Worker
969*0d6140beSAndroid Build Coastguard Worker parse_options(argc, argv, optstring, long_options, &options);
970*0d6140beSAndroid Build Coastguard Worker
971*0d6140beSAndroid Build Coastguard Worker if (options.filename && check_filename(options.filename, "image"))
972*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage(NULL);
973*0d6140beSAndroid Build Coastguard Worker if (options.layoutfile && check_filename(options.layoutfile, "layout"))
974*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage(NULL);
975*0d6140beSAndroid Build Coastguard Worker if (options.fmapfile && check_filename(options.fmapfile, "fmap"))
976*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage(NULL);
977*0d6140beSAndroid Build Coastguard Worker if (options.referencefile && check_filename(options.referencefile, "reference"))
978*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage(NULL);
979*0d6140beSAndroid Build Coastguard Worker if (options.logfile && check_filename(options.logfile, "log"))
980*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage(NULL);
981*0d6140beSAndroid Build Coastguard Worker if (options.logfile && open_logfile(options.logfile))
982*0d6140beSAndroid Build Coastguard Worker cli_classic_abort_usage(NULL);
983*0d6140beSAndroid Build Coastguard Worker
984*0d6140beSAndroid Build Coastguard Worker #if CONFIG_PRINT_WIKI == 1
985*0d6140beSAndroid Build Coastguard Worker if (options.list_supported_wiki) {
986*0d6140beSAndroid Build Coastguard Worker print_supported_wiki();
987*0d6140beSAndroid Build Coastguard Worker goto out;
988*0d6140beSAndroid Build Coastguard Worker }
989*0d6140beSAndroid Build Coastguard Worker #endif
990*0d6140beSAndroid Build Coastguard Worker
991*0d6140beSAndroid Build Coastguard Worker if (options.list_supported) {
992*0d6140beSAndroid Build Coastguard Worker if (print_supported())
993*0d6140beSAndroid Build Coastguard Worker ret = 1;
994*0d6140beSAndroid Build Coastguard Worker goto out;
995*0d6140beSAndroid Build Coastguard Worker }
996*0d6140beSAndroid Build Coastguard Worker
997*0d6140beSAndroid Build Coastguard Worker start_logging();
998*0d6140beSAndroid Build Coastguard Worker
999*0d6140beSAndroid Build Coastguard Worker print_buildinfo();
1000*0d6140beSAndroid Build Coastguard Worker msg_gdbg("Command line (%i args):", argc - 1);
1001*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < argc; i++) {
1002*0d6140beSAndroid Build Coastguard Worker msg_gdbg(" %s", argv[i]);
1003*0d6140beSAndroid Build Coastguard Worker }
1004*0d6140beSAndroid Build Coastguard Worker msg_gdbg("\n");
1005*0d6140beSAndroid Build Coastguard Worker
1006*0d6140beSAndroid Build Coastguard Worker if (options.layoutfile && layout_from_file(&options.layout, options.layoutfile)) {
1007*0d6140beSAndroid Build Coastguard Worker ret = 1;
1008*0d6140beSAndroid Build Coastguard Worker goto out;
1009*0d6140beSAndroid Build Coastguard Worker }
1010*0d6140beSAndroid Build Coastguard Worker
1011*0d6140beSAndroid Build Coastguard Worker /* If the user specifies a -i argument and no layout, then we do fmap
1012*0d6140beSAndroid Build Coastguard Worker * parsing. */
1013*0d6140beSAndroid Build Coastguard Worker if ((options.include_args || options.extract_it) && !options.layoutfile && !options.ifd) {
1014*0d6140beSAndroid Build Coastguard Worker msg_gdbg("-i argument specified, set fmap.\n");
1015*0d6140beSAndroid Build Coastguard Worker options.fmap = 1;
1016*0d6140beSAndroid Build Coastguard Worker }
1017*0d6140beSAndroid Build Coastguard Worker
1018*0d6140beSAndroid Build Coastguard Worker if (!options.ifd && !options.fmap && process_include_args(options.layout, options.include_args)) {
1019*0d6140beSAndroid Build Coastguard Worker ret = 1;
1020*0d6140beSAndroid Build Coastguard Worker goto out;
1021*0d6140beSAndroid Build Coastguard Worker }
1022*0d6140beSAndroid Build Coastguard Worker /* Does a chip with the requested name exist in the flashchips array? */
1023*0d6140beSAndroid Build Coastguard Worker if (options.chip_to_probe) {
1024*0d6140beSAndroid Build Coastguard Worker for (chip = flashchips; chip && chip->name; chip++)
1025*0d6140beSAndroid Build Coastguard Worker if (!strcmp(chip->name, options.chip_to_probe))
1026*0d6140beSAndroid Build Coastguard Worker break;
1027*0d6140beSAndroid Build Coastguard Worker if (!chip || !chip->name) {
1028*0d6140beSAndroid Build Coastguard Worker msg_cerr("Error: Unknown chip '%s' specified.\n", options.chip_to_probe);
1029*0d6140beSAndroid Build Coastguard Worker msg_gerr("Run flashrom -L to view the hardware supported in this flashrom version.\n");
1030*0d6140beSAndroid Build Coastguard Worker ret = 1;
1031*0d6140beSAndroid Build Coastguard Worker goto out;
1032*0d6140beSAndroid Build Coastguard Worker }
1033*0d6140beSAndroid Build Coastguard Worker /* Keep chip around for later usage in case a forced read is requested. */
1034*0d6140beSAndroid Build Coastguard Worker }
1035*0d6140beSAndroid Build Coastguard Worker
1036*0d6140beSAndroid Build Coastguard Worker if (options.prog == NULL) {
1037*0d6140beSAndroid Build Coastguard Worker const struct programmer_entry *const default_programmer = CONFIG_DEFAULT_PROGRAMMER_NAME;
1038*0d6140beSAndroid Build Coastguard Worker
1039*0d6140beSAndroid Build Coastguard Worker if (default_programmer) {
1040*0d6140beSAndroid Build Coastguard Worker options.prog = default_programmer;
1041*0d6140beSAndroid Build Coastguard Worker /* We need to strdup here because we free(pparam) unconditionally later. */
1042*0d6140beSAndroid Build Coastguard Worker options.pparam = strdup(CONFIG_DEFAULT_PROGRAMMER_ARGS);
1043*0d6140beSAndroid Build Coastguard Worker msg_pinfo("Using default programmer \"%s\" with arguments \"%s\".\n",
1044*0d6140beSAndroid Build Coastguard Worker default_programmer->name, options.pparam);
1045*0d6140beSAndroid Build Coastguard Worker } else {
1046*0d6140beSAndroid Build Coastguard Worker msg_perr("Please select a programmer with the --programmer parameter.\n"
1047*0d6140beSAndroid Build Coastguard Worker #if CONFIG_INTERNAL == 1
1048*0d6140beSAndroid Build Coastguard Worker "To choose the mainboard of this computer use 'internal'. "
1049*0d6140beSAndroid Build Coastguard Worker #endif
1050*0d6140beSAndroid Build Coastguard Worker "Valid choices are:\n");
1051*0d6140beSAndroid Build Coastguard Worker list_programmers_linebreak(0, 80, 0);
1052*0d6140beSAndroid Build Coastguard Worker msg_ginfo(".\n");
1053*0d6140beSAndroid Build Coastguard Worker ret = 1;
1054*0d6140beSAndroid Build Coastguard Worker goto out;
1055*0d6140beSAndroid Build Coastguard Worker }
1056*0d6140beSAndroid Build Coastguard Worker }
1057*0d6140beSAndroid Build Coastguard Worker
1058*0d6140beSAndroid Build Coastguard Worker /* FIXME: Delay calibration should happen in programmer code. */
1059*0d6140beSAndroid Build Coastguard Worker if (flashrom_init(1))
1060*0d6140beSAndroid Build Coastguard Worker exit(1);
1061*0d6140beSAndroid Build Coastguard Worker
1062*0d6140beSAndroid Build Coastguard Worker if (programmer_init(options.prog, options.pparam)) {
1063*0d6140beSAndroid Build Coastguard Worker msg_perr("Error: Programmer initialization failed.\n");
1064*0d6140beSAndroid Build Coastguard Worker ret = 1;
1065*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1066*0d6140beSAndroid Build Coastguard Worker }
1067*0d6140beSAndroid Build Coastguard Worker tempstr = flashbuses_to_text(get_buses_supported());
1068*0d6140beSAndroid Build Coastguard Worker msg_pdbg("The following protocols are supported: %s.\n", tempstr ? tempstr : "?");
1069*0d6140beSAndroid Build Coastguard Worker free(tempstr);
1070*0d6140beSAndroid Build Coastguard Worker tempstr = NULL;
1071*0d6140beSAndroid Build Coastguard Worker
1072*0d6140beSAndroid Build Coastguard Worker for (j = 0; j < registered_master_count; j++) {
1073*0d6140beSAndroid Build Coastguard Worker startchip = 0;
1074*0d6140beSAndroid Build Coastguard Worker while (chipcount < (int)ARRAY_SIZE(flashes)) {
1075*0d6140beSAndroid Build Coastguard Worker startchip = probe_flash(®istered_masters[j], startchip, &flashes[chipcount], 0, options.chip_to_probe);
1076*0d6140beSAndroid Build Coastguard Worker if (startchip == -1)
1077*0d6140beSAndroid Build Coastguard Worker break;
1078*0d6140beSAndroid Build Coastguard Worker chipcount++;
1079*0d6140beSAndroid Build Coastguard Worker startchip++;
1080*0d6140beSAndroid Build Coastguard Worker }
1081*0d6140beSAndroid Build Coastguard Worker }
1082*0d6140beSAndroid Build Coastguard Worker
1083*0d6140beSAndroid Build Coastguard Worker if (chipcount > 1) {
1084*0d6140beSAndroid Build Coastguard Worker msg_cinfo("Multiple flash chip definitions match the detected chip(s): \"%s\"",
1085*0d6140beSAndroid Build Coastguard Worker flashes[0].chip->name);
1086*0d6140beSAndroid Build Coastguard Worker for (i = 1; i < chipcount; i++)
1087*0d6140beSAndroid Build Coastguard Worker msg_cinfo(", \"%s\"", flashes[i].chip->name);
1088*0d6140beSAndroid Build Coastguard Worker msg_cinfo("\nPlease specify which chip definition to use with the -c <chipname> option.\n");
1089*0d6140beSAndroid Build Coastguard Worker ret = 1;
1090*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1091*0d6140beSAndroid Build Coastguard Worker } else if (!chipcount) {
1092*0d6140beSAndroid Build Coastguard Worker msg_cinfo("No EEPROM/flash device found.\n");
1093*0d6140beSAndroid Build Coastguard Worker if (!options.force || !options.chip_to_probe) {
1094*0d6140beSAndroid Build Coastguard Worker msg_cinfo("Note: flashrom can never write if the flash chip isn't found "
1095*0d6140beSAndroid Build Coastguard Worker "automatically.\n");
1096*0d6140beSAndroid Build Coastguard Worker }
1097*0d6140beSAndroid Build Coastguard Worker if (options.force && options.read_it && options.chip_to_probe) {
1098*0d6140beSAndroid Build Coastguard Worker struct registered_master *mst;
1099*0d6140beSAndroid Build Coastguard Worker int compatible_masters = 0;
1100*0d6140beSAndroid Build Coastguard Worker msg_cinfo("Force read (-f -r -c) requested, pretending the chip is there:\n");
1101*0d6140beSAndroid Build Coastguard Worker /* This loop just counts compatible controllers. */
1102*0d6140beSAndroid Build Coastguard Worker for (j = 0; j < registered_master_count; j++) {
1103*0d6140beSAndroid Build Coastguard Worker mst = ®istered_masters[j];
1104*0d6140beSAndroid Build Coastguard Worker /* chip is still set from the chip_to_probe earlier in this function. */
1105*0d6140beSAndroid Build Coastguard Worker if (mst->buses_supported & chip->bustype)
1106*0d6140beSAndroid Build Coastguard Worker compatible_masters++;
1107*0d6140beSAndroid Build Coastguard Worker }
1108*0d6140beSAndroid Build Coastguard Worker if (!compatible_masters) {
1109*0d6140beSAndroid Build Coastguard Worker msg_cinfo("No compatible controller found for the requested flash chip.\n");
1110*0d6140beSAndroid Build Coastguard Worker ret = 1;
1111*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1112*0d6140beSAndroid Build Coastguard Worker }
1113*0d6140beSAndroid Build Coastguard Worker if (compatible_masters > 1)
1114*0d6140beSAndroid Build Coastguard Worker msg_cinfo("More than one compatible controller found for the requested flash "
1115*0d6140beSAndroid Build Coastguard Worker "chip, using the first one.\n");
1116*0d6140beSAndroid Build Coastguard Worker for (j = 0; j < registered_master_count; j++) {
1117*0d6140beSAndroid Build Coastguard Worker mst = ®istered_masters[j];
1118*0d6140beSAndroid Build Coastguard Worker startchip = probe_flash(mst, 0, &flashes[0], 1, options.chip_to_probe);
1119*0d6140beSAndroid Build Coastguard Worker if (startchip != -1)
1120*0d6140beSAndroid Build Coastguard Worker break;
1121*0d6140beSAndroid Build Coastguard Worker }
1122*0d6140beSAndroid Build Coastguard Worker if (startchip == -1) {
1123*0d6140beSAndroid Build Coastguard Worker // FIXME: This should never happen! Ask for a bug report?
1124*0d6140beSAndroid Build Coastguard Worker msg_cinfo("Probing for flash chip '%s' failed.\n", options.chip_to_probe);
1125*0d6140beSAndroid Build Coastguard Worker ret = 1;
1126*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1127*0d6140beSAndroid Build Coastguard Worker }
1128*0d6140beSAndroid Build Coastguard Worker msg_cinfo("Please note that forced reads most likely contain garbage.\n");
1129*0d6140beSAndroid Build Coastguard Worker flashrom_flag_set(&flashes[0], FLASHROM_FLAG_FORCE, options.force);
1130*0d6140beSAndroid Build Coastguard Worker ret = do_read(&flashes[0], options.filename);
1131*0d6140beSAndroid Build Coastguard Worker free(flashes[0].chip);
1132*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1133*0d6140beSAndroid Build Coastguard Worker }
1134*0d6140beSAndroid Build Coastguard Worker ret = 1;
1135*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1136*0d6140beSAndroid Build Coastguard Worker } else if (!options.chip_to_probe) {
1137*0d6140beSAndroid Build Coastguard Worker /* repeat for convenience when looking at foreign logs */
1138*0d6140beSAndroid Build Coastguard Worker tempstr = flashbuses_to_text(flashes[0].chip->bustype);
1139*0d6140beSAndroid Build Coastguard Worker msg_gdbg("Found %s flash chip \"%s\" (%d kB, %s).\n",
1140*0d6140beSAndroid Build Coastguard Worker flashes[0].chip->vendor, flashes[0].chip->name, flashes[0].chip->total_size,
1141*0d6140beSAndroid Build Coastguard Worker tempstr ? tempstr : "?");
1142*0d6140beSAndroid Build Coastguard Worker free(tempstr);
1143*0d6140beSAndroid Build Coastguard Worker }
1144*0d6140beSAndroid Build Coastguard Worker
1145*0d6140beSAndroid Build Coastguard Worker fill_flash = &flashes[0];
1146*0d6140beSAndroid Build Coastguard Worker
1147*0d6140beSAndroid Build Coastguard Worker unsigned int progress_user_data[FLASHROM_PROGRESS_NR];
1148*0d6140beSAndroid Build Coastguard Worker struct flashrom_progress progress_state = {
1149*0d6140beSAndroid Build Coastguard Worker .user_data = progress_user_data
1150*0d6140beSAndroid Build Coastguard Worker };
1151*0d6140beSAndroid Build Coastguard Worker if (options.show_progress)
1152*0d6140beSAndroid Build Coastguard Worker flashrom_set_progress_callback(fill_flash, &flashrom_progress_cb, &progress_state);
1153*0d6140beSAndroid Build Coastguard Worker
1154*0d6140beSAndroid Build Coastguard Worker print_chip_support_status(fill_flash->chip);
1155*0d6140beSAndroid Build Coastguard Worker
1156*0d6140beSAndroid Build Coastguard Worker unsigned int limitexceeded = count_max_decode_exceedings(fill_flash, &max_rom_decode);
1157*0d6140beSAndroid Build Coastguard Worker if (limitexceeded > 0 && !options.force) {
1158*0d6140beSAndroid Build Coastguard Worker enum chipbustype commonbuses = fill_flash->mst->buses_supported & fill_flash->chip->bustype;
1159*0d6140beSAndroid Build Coastguard Worker
1160*0d6140beSAndroid Build Coastguard Worker /* Sometimes chip and programmer have more than one bus in common,
1161*0d6140beSAndroid Build Coastguard Worker * and the limit is not exceeded on all buses. Tell the user. */
1162*0d6140beSAndroid Build Coastguard Worker if ((bitcount(commonbuses) > limitexceeded)) {
1163*0d6140beSAndroid Build Coastguard Worker msg_pdbg("There is at least one interface available which could support the size of\n"
1164*0d6140beSAndroid Build Coastguard Worker "the selected flash chip.\n");
1165*0d6140beSAndroid Build Coastguard Worker }
1166*0d6140beSAndroid Build Coastguard Worker msg_cerr("This flash chip is too big for this programmer (--verbose/-V gives details).\n"
1167*0d6140beSAndroid Build Coastguard Worker "Use --force/-f to override at your own risk.\n");
1168*0d6140beSAndroid Build Coastguard Worker ret = 1;
1169*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1170*0d6140beSAndroid Build Coastguard Worker }
1171*0d6140beSAndroid Build Coastguard Worker
1172*0d6140beSAndroid Build Coastguard Worker const bool any_wp_op =
1173*0d6140beSAndroid Build Coastguard Worker options.set_wp_range || options.set_wp_region || options.enable_wp ||
1174*0d6140beSAndroid Build Coastguard Worker options.disable_wp || options.print_wp_status || options.print_wp_ranges;
1175*0d6140beSAndroid Build Coastguard Worker
1176*0d6140beSAndroid Build Coastguard Worker const bool any_op = options.read_it || options.write_it || options.verify_it ||
1177*0d6140beSAndroid Build Coastguard Worker options.erase_it || options.flash_name || options.flash_size ||
1178*0d6140beSAndroid Build Coastguard Worker options.extract_it || any_wp_op;
1179*0d6140beSAndroid Build Coastguard Worker
1180*0d6140beSAndroid Build Coastguard Worker if (!any_op) {
1181*0d6140beSAndroid Build Coastguard Worker msg_ginfo("No operations were specified.\n");
1182*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1183*0d6140beSAndroid Build Coastguard Worker }
1184*0d6140beSAndroid Build Coastguard Worker
1185*0d6140beSAndroid Build Coastguard Worker if (options.enable_wp && options.disable_wp) {
1186*0d6140beSAndroid Build Coastguard Worker msg_ginfo("Error: --wp-enable and --wp-disable are mutually exclusive\n");
1187*0d6140beSAndroid Build Coastguard Worker ret = 1;
1188*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1189*0d6140beSAndroid Build Coastguard Worker }
1190*0d6140beSAndroid Build Coastguard Worker if (options.set_wp_range && options.set_wp_region) {
1191*0d6140beSAndroid Build Coastguard Worker msg_gerr("Error: Cannot use both --wp-range and --wp-region simultaneously.\n");
1192*0d6140beSAndroid Build Coastguard Worker ret = 1;
1193*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1194*0d6140beSAndroid Build Coastguard Worker }
1195*0d6140beSAndroid Build Coastguard Worker
1196*0d6140beSAndroid Build Coastguard Worker /*
1197*0d6140beSAndroid Build Coastguard Worker * Common rules for -r/-w/-v syntax parsing:
1198*0d6140beSAndroid Build Coastguard Worker * - If no filename is specified at all, quit.
1199*0d6140beSAndroid Build Coastguard Worker * - If no filename is specified for -r/-w/-v, but files are specified
1200*0d6140beSAndroid Build Coastguard Worker * for -i, then the number of file arguments for -i options must be
1201*0d6140beSAndroid Build Coastguard Worker * equal to the total number of -i options.
1202*0d6140beSAndroid Build Coastguard Worker *
1203*0d6140beSAndroid Build Coastguard Worker * Rules for reading:
1204*0d6140beSAndroid Build Coastguard Worker * - If files are specified for -i args but not -r, do partial reads for
1205*0d6140beSAndroid Build Coastguard Worker * each -i arg, creating a new file for each region. Each -i option
1206*0d6140beSAndroid Build Coastguard Worker * must specify a filename.
1207*0d6140beSAndroid Build Coastguard Worker * - If filenames are specified for -r and -i args, then:
1208*0d6140beSAndroid Build Coastguard Worker * - Do partial read for each -i arg, creating a new file for
1209*0d6140beSAndroid Build Coastguard Worker * each region where a filename is provided (-i region:filename).
1210*0d6140beSAndroid Build Coastguard Worker * - Create a ROM-sized file with partially filled content. For each
1211*0d6140beSAndroid Build Coastguard Worker * -i arg, fill the corresponding offset with content from ROM.
1212*0d6140beSAndroid Build Coastguard Worker *
1213*0d6140beSAndroid Build Coastguard Worker * Rules for writing and verifying:
1214*0d6140beSAndroid Build Coastguard Worker * - If files are specified for both -w/-v and -i args, -i files take
1215*0d6140beSAndroid Build Coastguard Worker * priority.
1216*0d6140beSAndroid Build Coastguard Worker * - If file is specified for -w/-v and no files are specified with -i
1217*0d6140beSAndroid Build Coastguard Worker * args, then the file is to be used for writing/verifying the entire
1218*0d6140beSAndroid Build Coastguard Worker * ROM.
1219*0d6140beSAndroid Build Coastguard Worker * - If files are specified for -i args but not -w, do partial writes
1220*0d6140beSAndroid Build Coastguard Worker * for each -i arg. Likewise for -v and -i args. All -i args must
1221*0d6140beSAndroid Build Coastguard Worker * supply a filename. Any omission is considered ambiguous.
1222*0d6140beSAndroid Build Coastguard Worker * - Regions with a filename associated must not overlap. This is also
1223*0d6140beSAndroid Build Coastguard Worker * considered ambiguous. Note: This is checked later since it requires
1224*0d6140beSAndroid Build Coastguard Worker * processing the layout/fmap first.
1225*0d6140beSAndroid Build Coastguard Worker */
1226*0d6140beSAndroid Build Coastguard Worker if ((options.read_it | options.write_it | options.verify_it) && !options.filename) {
1227*0d6140beSAndroid Build Coastguard Worker if (!options.include_args) {
1228*0d6140beSAndroid Build Coastguard Worker msg_gerr("Error: No image file specified.\n");
1229*0d6140beSAndroid Build Coastguard Worker ret = 1;
1230*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1231*0d6140beSAndroid Build Coastguard Worker }
1232*0d6140beSAndroid Build Coastguard Worker
1233*0d6140beSAndroid Build Coastguard Worker if (check_include_args_filename(options.include_args)) {
1234*0d6140beSAndroid Build Coastguard Worker ret = 1;
1235*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1236*0d6140beSAndroid Build Coastguard Worker }
1237*0d6140beSAndroid Build Coastguard Worker }
1238*0d6140beSAndroid Build Coastguard Worker
1239*0d6140beSAndroid Build Coastguard Worker if (options.flash_name) {
1240*0d6140beSAndroid Build Coastguard Worker if (fill_flash->chip->vendor && fill_flash->chip->name) {
1241*0d6140beSAndroid Build Coastguard Worker printf("vendor=\"%s\" name=\"%s\"\n",
1242*0d6140beSAndroid Build Coastguard Worker fill_flash->chip->vendor,
1243*0d6140beSAndroid Build Coastguard Worker fill_flash->chip->name);
1244*0d6140beSAndroid Build Coastguard Worker } else {
1245*0d6140beSAndroid Build Coastguard Worker ret = -1;
1246*0d6140beSAndroid Build Coastguard Worker }
1247*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1248*0d6140beSAndroid Build Coastguard Worker }
1249*0d6140beSAndroid Build Coastguard Worker
1250*0d6140beSAndroid Build Coastguard Worker if (options.flash_size) {
1251*0d6140beSAndroid Build Coastguard Worker printf("%zu\n", flashrom_flash_getsize(fill_flash));
1252*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1253*0d6140beSAndroid Build Coastguard Worker }
1254*0d6140beSAndroid Build Coastguard Worker
1255*0d6140beSAndroid Build Coastguard Worker /*
1256*0d6140beSAndroid Build Coastguard Worker * FIXME: Align with upstream, maybe add build flag for this. Always
1257*0d6140beSAndroid Build Coastguard Worker * skip unreadable and unwritable regions in cros flashrom. Various
1258*0d6140beSAndroid Build Coastguard Worker * flashrom users (e.g. Tast tests, flashrom_tester) try to read or
1259*0d6140beSAndroid Build Coastguard Worker * write the entire flash and will fail on Intel platforms if the ME
1260*0d6140beSAndroid Build Coastguard Worker * regions are not automatically skipped.
1261*0d6140beSAndroid Build Coastguard Worker */
1262*0d6140beSAndroid Build Coastguard Worker flashrom_flag_set(fill_flash, FLASHROM_FLAG_SKIP_UNWRITABLE_REGIONS, true);
1263*0d6140beSAndroid Build Coastguard Worker flashrom_flag_set(fill_flash, FLASHROM_FLAG_SKIP_UNREADABLE_REGIONS, true);
1264*0d6140beSAndroid Build Coastguard Worker
1265*0d6140beSAndroid Build Coastguard Worker if (options.ifd && (flashrom_layout_read_from_ifd(&options.layout, fill_flash, NULL, 0) ||
1266*0d6140beSAndroid Build Coastguard Worker process_include_args(options.layout, options.include_args))) {
1267*0d6140beSAndroid Build Coastguard Worker ret = 1;
1268*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1269*0d6140beSAndroid Build Coastguard Worker } else if (options.fmap && options.fmapfile &&
1270*0d6140beSAndroid Build Coastguard Worker (flashrom_layout_read_fmap_from_file(&options.layout, fill_flash, options.fmapfile) ||
1271*0d6140beSAndroid Build Coastguard Worker process_include_args(options.layout, options.include_args))) {
1272*0d6140beSAndroid Build Coastguard Worker ret = 1;
1273*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1274*0d6140beSAndroid Build Coastguard Worker } else if (!options.ifd && options.fmap &&
1275*0d6140beSAndroid Build Coastguard Worker ((flashrom_layout_read_fmap_from_file(&options.layout, fill_flash, options.filename) &&
1276*0d6140beSAndroid Build Coastguard Worker flashrom_layout_read_fmap_from_rom(&options.layout, fill_flash, 0,
1277*0d6140beSAndroid Build Coastguard Worker flashrom_flash_getsize(fill_flash))) ||
1278*0d6140beSAndroid Build Coastguard Worker process_include_args(options.layout, options.include_args))) {
1279*0d6140beSAndroid Build Coastguard Worker ret = 1;
1280*0d6140beSAndroid Build Coastguard Worker goto out_shutdown;
1281*0d6140beSAndroid Build Coastguard Worker }
1282*0d6140beSAndroid Build Coastguard Worker flashrom_layout_set(fill_flash, options.layout);
1283*0d6140beSAndroid Build Coastguard Worker
1284*0d6140beSAndroid Build Coastguard Worker if (any_wp_op) {
1285*0d6140beSAndroid Build Coastguard Worker if (options.set_wp_region && options.wp_region) {
1286*0d6140beSAndroid Build Coastguard Worker if (!options.layout) {
1287*0d6140beSAndroid Build Coastguard Worker msg_gerr("Error: A flash layout must be specified to use --wp-region.\n");
1288*0d6140beSAndroid Build Coastguard Worker ret = 1;
1289*0d6140beSAndroid Build Coastguard Worker goto out_release;
1290*0d6140beSAndroid Build Coastguard Worker }
1291*0d6140beSAndroid Build Coastguard Worker
1292*0d6140beSAndroid Build Coastguard Worker ret = flashrom_layout_get_region_range(options.layout, options.wp_region, &options.wp_start, &options.wp_len);
1293*0d6140beSAndroid Build Coastguard Worker if (ret) {
1294*0d6140beSAndroid Build Coastguard Worker msg_gerr("Error: Region %s not found in flash layout.\n", options.wp_region);
1295*0d6140beSAndroid Build Coastguard Worker goto out_release;
1296*0d6140beSAndroid Build Coastguard Worker }
1297*0d6140beSAndroid Build Coastguard Worker options.set_wp_range = true;
1298*0d6140beSAndroid Build Coastguard Worker }
1299*0d6140beSAndroid Build Coastguard Worker ret = wp_cli(
1300*0d6140beSAndroid Build Coastguard Worker fill_flash,
1301*0d6140beSAndroid Build Coastguard Worker options.enable_wp,
1302*0d6140beSAndroid Build Coastguard Worker options.disable_wp,
1303*0d6140beSAndroid Build Coastguard Worker options.print_wp_status,
1304*0d6140beSAndroid Build Coastguard Worker options.print_wp_ranges,
1305*0d6140beSAndroid Build Coastguard Worker options.set_wp_range,
1306*0d6140beSAndroid Build Coastguard Worker options.wp_start,
1307*0d6140beSAndroid Build Coastguard Worker options.wp_len
1308*0d6140beSAndroid Build Coastguard Worker );
1309*0d6140beSAndroid Build Coastguard Worker if (ret)
1310*0d6140beSAndroid Build Coastguard Worker goto out_release;
1311*0d6140beSAndroid Build Coastguard Worker }
1312*0d6140beSAndroid Build Coastguard Worker
1313*0d6140beSAndroid Build Coastguard Worker flashrom_flag_set(fill_flash, FLASHROM_FLAG_FORCE, options.force);
1314*0d6140beSAndroid Build Coastguard Worker #if CONFIG_INTERNAL == 1
1315*0d6140beSAndroid Build Coastguard Worker flashrom_flag_set(fill_flash, FLASHROM_FLAG_FORCE_BOARDMISMATCH, force_boardmismatch);
1316*0d6140beSAndroid Build Coastguard Worker #endif
1317*0d6140beSAndroid Build Coastguard Worker flashrom_flag_set(fill_flash, FLASHROM_FLAG_VERIFY_AFTER_WRITE, !options.dont_verify_it);
1318*0d6140beSAndroid Build Coastguard Worker flashrom_flag_set(fill_flash, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, !options.dont_verify_all);
1319*0d6140beSAndroid Build Coastguard Worker
1320*0d6140beSAndroid Build Coastguard Worker /* FIXME: We should issue an unconditional chip reset here. This can be
1321*0d6140beSAndroid Build Coastguard Worker * done once we have a .reset function in struct flashchip.
1322*0d6140beSAndroid Build Coastguard Worker * Give the chip time to settle.
1323*0d6140beSAndroid Build Coastguard Worker */
1324*0d6140beSAndroid Build Coastguard Worker programmer_delay(fill_flash, 100000);
1325*0d6140beSAndroid Build Coastguard Worker if (options.read_it)
1326*0d6140beSAndroid Build Coastguard Worker ret = do_read(fill_flash, options.filename);
1327*0d6140beSAndroid Build Coastguard Worker else if (options.extract_it)
1328*0d6140beSAndroid Build Coastguard Worker ret = do_extract(fill_flash);
1329*0d6140beSAndroid Build Coastguard Worker else if (options.erase_it) {
1330*0d6140beSAndroid Build Coastguard Worker ret = flashrom_flash_erase(fill_flash);
1331*0d6140beSAndroid Build Coastguard Worker /*
1332*0d6140beSAndroid Build Coastguard Worker * FIXME: Do we really want the scary warning if erase failed?
1333*0d6140beSAndroid Build Coastguard Worker * After all, after erase the chip is either blank or partially
1334*0d6140beSAndroid Build Coastguard Worker * blank or it has the old contents. A blank chip won't boot,
1335*0d6140beSAndroid Build Coastguard Worker * so if the user wanted erase and reboots afterwards, the user
1336*0d6140beSAndroid Build Coastguard Worker * knows very well that booting won't work.
1337*0d6140beSAndroid Build Coastguard Worker */
1338*0d6140beSAndroid Build Coastguard Worker if (ret)
1339*0d6140beSAndroid Build Coastguard Worker emergency_help_message();
1340*0d6140beSAndroid Build Coastguard Worker }
1341*0d6140beSAndroid Build Coastguard Worker else if (options.write_it)
1342*0d6140beSAndroid Build Coastguard Worker ret = do_write(fill_flash, options.filename, options.referencefile);
1343*0d6140beSAndroid Build Coastguard Worker else if (options.verify_it)
1344*0d6140beSAndroid Build Coastguard Worker ret = do_verify(fill_flash, options.filename);
1345*0d6140beSAndroid Build Coastguard Worker
1346*0d6140beSAndroid Build Coastguard Worker msg_ginfo("%s\n", ret ? "FAILED" : "SUCCESS");
1347*0d6140beSAndroid Build Coastguard Worker
1348*0d6140beSAndroid Build Coastguard Worker out_release:
1349*0d6140beSAndroid Build Coastguard Worker flashrom_layout_release(options.layout);
1350*0d6140beSAndroid Build Coastguard Worker out_shutdown:
1351*0d6140beSAndroid Build Coastguard Worker flashrom_programmer_shutdown(NULL);
1352*0d6140beSAndroid Build Coastguard Worker out:
1353*0d6140beSAndroid Build Coastguard Worker
1354*0d6140beSAndroid Build Coastguard Worker for (i = 0; i < chipcount; i++) {
1355*0d6140beSAndroid Build Coastguard Worker flashrom_layout_release(flashes[i].default_layout);
1356*0d6140beSAndroid Build Coastguard Worker free(flashes[i].chip);
1357*0d6140beSAndroid Build Coastguard Worker }
1358*0d6140beSAndroid Build Coastguard Worker
1359*0d6140beSAndroid Build Coastguard Worker free_options(&options);
1360*0d6140beSAndroid Build Coastguard Worker ret |= close_logfile();
1361*0d6140beSAndroid Build Coastguard Worker return ret;
1362*0d6140beSAndroid Build Coastguard Worker }
1363