blob: 787e47db0b9a4a19af2fe3cdad1c71762d679d62 [file] [log] [blame]
Stefan Tauner9b32de92014-08-08 23:52:33 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
5 * Copyright (C) 2009 Carl-Daniel Hailfinger
6 * Copyright (C) 2011-2014 Stefan Tauner
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
Stefan Tauner9b32de92014-08-08 23:52:33 +000017 */
18
19#include <stdlib.h>
20#include <string.h>
Nico Huber0da839b2023-02-11 01:40:07 +010021#include <sys/stat.h>
Nico Huber34e783a2023-02-11 00:30:27 +010022
Stefan Tauner9b32de92014-08-08 23:52:33 +000023#include "flash.h"
Nico Huber34e783a2023-02-11 00:30:27 +010024#include "cli.h"
25
Nico Huberd91822a2023-02-11 00:43:54 +010026int cli_check_filename(const char *const filename, const char *const type)
27{
28 if (!filename || (filename[0] == '\0')) {
29 fprintf(stderr, "Error: No %s file specified.\n", type);
30 return 1;
31 }
32 /* Not an error, but maybe the user intended to specify a CLI option instead of a file name. */
33 if (filename[0] == '-' && filename[1] != '\0')
34 fprintf(stderr, "Warning: Supplied %s file name starts with -\n", type);
35 return 0;
36}
37
Nico Huberdf6ce9f2023-02-11 16:16:04 +010038int cli_parse_log_args(struct log_args *const args, const int opt, const char *const optarg)
39{
40 switch (opt) {
41 case OPTION_VERBOSE:
42 args->screen_level++;
43 if (args->screen_level > args->logfile_level)
44 args->logfile_level = args->screen_level;
45 break;
46 case OPTION_LOGFILE:
47 if (cli_check_filename(optarg, "log"))
48 return 1;
49
50 if (args->logfile) {
51 fprintf(stderr, "Warning: -o/--output specified multiple times.\n");
52 free(args->logfile);
53 }
54
55 args->logfile = strdup(optarg);
56 if (!args->logfile) {
57 fprintf(stderr, "Out of memory!\n");
58 return 2;
59 }
60 break;
61 }
62
63 return 0;
64}
65
Nico Huber34e783a2023-02-11 00:30:27 +010066int cli_parse_flash_args(struct flash_args *const args, const int opt, const char *const optarg)
67{
68 switch (opt) {
69 case OPTION_PROGRAMMER:
70 if (args->prog_name) {
71 fprintf(stderr,
72 "Error: --programmer specified more than once. You can separate multiple\n"
73 "arguments for a programmer with ','. Please see the man page for details.\n");
74 return 1;
75 }
76 const char *const colon = strchr(optarg, ':');
77 if (colon) {
78 args->prog_name = strndup(optarg, colon - optarg);
79 args->prog_args = strdup(colon + 1);
80 } else {
81 args->prog_name = strdup(optarg);
82 }
83 if (!args->prog_name || (colon && !args->prog_args)) {
84 fprintf(stderr, "Out of memory!\n");
85 return 2;
86 }
87 break;
88 case OPTION_CHIP:
89 if (args->chip) {
90 fprintf(stderr, "Error: --chip specified more than once.\n");
91 return 1;
92 }
93 args->chip = strdup(optarg);
94 if (!args->chip) {
95 fprintf(stderr, "Out of memory!\n");
96 return 2;
97 }
98 break;
99 }
100
101 return 0;
102}
Stefan Tauner9b32de92014-08-08 23:52:33 +0000103
Nico Huberd91822a2023-02-11 00:43:54 +0100104int cli_parse_layout_args(struct layout_args *const args, const int opt, const char *const optarg)
105{
106 if (args->layoutfile || args->ifd || args->fmap || args->fmapfile) {
107 fprintf(stderr, "Error: Only one layout source may be specified.\n");
108 return 1;
109 }
110
111 switch (opt) {
112 case OPTION_LAYOUT:
113 if (cli_check_filename(optarg, "layout"))
114 return 1;
115
116 args->layoutfile = strdup(optarg);
117 if (!args->layoutfile) {
118 fprintf(stderr, "Out of memory!\n");
119 return 2;
120 }
121 break;
122 case OPTION_IFD:
123 args->ifd = true;
124 break;
125 case OPTION_FMAP:
126 args->fmap = true;
127 break;
128 case OPTION_FMAP_FILE:
129 if (cli_check_filename(optarg, "fmap"))
130 return 1;
131
132 args->fmapfile = strdup(optarg);
133 if (!args->fmapfile) {
134 fprintf(stderr, "Out of memory!\n");
135 return 2;
136 }
137 break;
138 }
139
140 return 0;
141}
142
Nico Huber0da839b2023-02-11 01:40:07 +0100143int cli_process_layout_args(struct flashprog_layout **const layout,
144 struct flashprog_flashctx *const flash,
145 const struct layout_args *const args)
146{
147 *layout = NULL;
148
149 if (args->layoutfile) {
150 if (layout_from_file(layout, args->layoutfile))
151 return 1;
152 } else if (args->ifd) {
153 if (flashprog_layout_read_from_ifd(layout, flash, NULL, 0))
154 return 1;
155 } else if (args->fmap) {
156 if (flashprog_layout_read_fmap_from_rom(layout, flash, 0, flashprog_flash_getsize(flash)))
157 return 1;
158 } else if (args->fmapfile) {
159 struct stat s;
160 if (stat(args->fmapfile, &s) != 0) {
161 msg_gerr("Failed to stat fmapfile \"%s\"\n", args->fmapfile);
162 return 1;
163 }
164
165 size_t fmapfile_size = s.st_size;
166 uint8_t *fmapfile_buffer = malloc(fmapfile_size);
167 if (!fmapfile_buffer) {
168 fprintf(stderr, "Out of memory!\n");
169 return 1;
170 }
171
172 if (read_buf_from_file(fmapfile_buffer, fmapfile_size, args->fmapfile)) {
173 free(fmapfile_buffer);
174 return 1;
175 }
176
177 if (flashprog_layout_read_fmap_from_buffer(layout, flash, fmapfile_buffer, fmapfile_size)) {
178 free(fmapfile_buffer);
179 return 1;
180 }
181 free(fmapfile_buffer);
182 }
183
184 return 0;
185}
186
Stefan Tauner9b32de92014-08-08 23:52:33 +0000187void print_chip_support_status(const struct flashchip *chip)
188{
189 if (chip->feature_bits & FEATURE_OTP) {
Nico Huberc3b02dc2023-08-12 01:13:45 +0200190 msg_cdbg("This chip may contain one-time programmable memory. flashprog cannot read\n"
Stefan Tauner9b32de92014-08-08 23:52:33 +0000191 "and may never be able to write it, hence it may not be able to completely\n"
192 "clone the contents of this chip (see man page for details).\n");
193 }
194
195 if ((chip->tested.erase == NA) && (chip->tested.write == NA)) {
196 msg_cdbg("This chip's main memory can not be erased/written by design.\n");
197 }
198
199 if ((chip->tested.probe == BAD) || (chip->tested.probe == NT) ||
200 (chip->tested.read == BAD) || (chip->tested.read == NT) ||
201 (chip->tested.erase == BAD) || (chip->tested.erase == NT) ||
Nico Huberbb4f3b02022-12-30 14:28:06 +0100202 (chip->tested.write == BAD) || (chip->tested.write == NT)) {
Stefan Tauner9b32de92014-08-08 23:52:33 +0000203 msg_cinfo("===\n");
204 if ((chip->tested.probe == BAD) ||
205 (chip->tested.read == BAD) ||
206 (chip->tested.erase == BAD) ||
Nico Huberbb4f3b02022-12-30 14:28:06 +0100207 (chip->tested.write == BAD)) {
Stefan Tauner9b32de92014-08-08 23:52:33 +0000208 msg_cinfo("This flash part has status NOT WORKING for operations:");
209 if (chip->tested.probe == BAD)
210 msg_cinfo(" PROBE");
211 if (chip->tested.read == BAD)
212 msg_cinfo(" READ");
213 if (chip->tested.erase == BAD)
214 msg_cinfo(" ERASE");
215 if (chip->tested.write == BAD)
216 msg_cinfo(" WRITE");
217 msg_cinfo("\n");
218 }
219 if ((chip->tested.probe == NT) ||
220 (chip->tested.read == NT) ||
221 (chip->tested.erase == NT) ||
Nico Huberbb4f3b02022-12-30 14:28:06 +0100222 (chip->tested.write == NT)) {
Stefan Tauner9b32de92014-08-08 23:52:33 +0000223 msg_cinfo("This flash part has status UNTESTED for operations:");
224 if (chip->tested.probe == NT)
225 msg_cinfo(" PROBE");
226 if (chip->tested.read == NT)
227 msg_cinfo(" READ");
228 if (chip->tested.erase == NT)
229 msg_cinfo(" ERASE");
230 if (chip->tested.write == NT)
231 msg_cinfo(" WRITE");
232 msg_cinfo("\n");
233 }
234 msg_cinfo("The test status of this chip may have been updated in the latest development\n"
Nico Huberc3b02dc2023-08-12 01:13:45 +0200235 "version of flashprog. If you are running the latest development version,\n"
236 "please email a report to flashprog@flashprog.org if any of the above\n"
Nico Huberac90af62022-12-18 00:22:47 +0000237 "operations work correctly for you with this flash chip. Please include the\n"
Nico Huberc3b02dc2023-08-12 01:13:45 +0200238 "flashprog log file for all operations you tested (see the man page for details),\n"
Nico Huberac90af62022-12-18 00:22:47 +0000239 "and mention which mainboard or programmer you tested in the subject line.\n"
Stefan Tauner9b32de92014-08-08 23:52:33 +0000240 "Thanks for your help!\n");
241 }
242}