blob: 400dc907b614a74123cfcf8158c384c2bf5938d4 [file] [log] [blame]
rminnich8d3ff912003-10-25 17:01:29 +00001/*
uweb25f1ea2007-08-29 17:52:32 +00002 * This file is part of the flashrom project.
rminnich8d3ff912003-10-25 17:01:29 +00003 *
uwe555dd972007-09-09 20:21:05 +00004 * Copyright (C) 2000 Silicon Integrated System Corporation
5 * Copyright (C) 2004 Tyan Corp <yhlu@tyan.com>
uwe4475e902009-05-19 14:14:21 +00006 * Copyright (C) 2005-2008 coresystems GmbH
hailfinger23060112009-05-08 12:49:03 +00007 * Copyright (C) 2008,2009 Carl-Daniel Hailfinger
Edward O'Callaghan0949b782019-11-10 23:23:20 +11008 * Copyright (C) 2016 secunet Security Networks AG
9 * (Written by Nico Huber <nico.huber@secunet.com> for secunet)
rminnich8d3ff912003-10-25 17:01:29 +000010 *
uweb25f1ea2007-08-29 17:52:32 +000011 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
rminnich8d3ff912003-10-25 17:01:29 +000015 *
uweb25f1ea2007-08-29 17:52:32 +000016 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
rminnich8d3ff912003-10-25 17:01:29 +000020 */
21
hailfingera83a5fe2010-05-30 22:24:40 +000022#include <stdio.h>
stepan1da96c02006-11-21 23:48:51 +000023#include <sys/types.h>
oxygene50275892010-09-30 17:03:32 +000024#ifndef __LIBPAYLOAD__
25#include <fcntl.h>
stepan1da96c02006-11-21 23:48:51 +000026#include <sys/stat.h>
oxygene50275892010-09-30 17:03:32 +000027#endif
rminnich8d3ff912003-10-25 17:01:29 +000028#include <string.h>
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +100029#include <unistd.h>
rminnich8d3ff912003-10-25 17:01:29 +000030#include <stdlib.h>
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +100031#include <errno.h>
hailfingerf76cc322010-11-09 22:00:31 +000032#include <ctype.h>
ollie6a600992005-11-26 21:55:36 +000033#include <getopt.h>
hailfinger3b471632010-03-27 16:36:40 +000034#if HAVE_UTSNAME == 1
35#include <sys/utsname.h>
36#endif
Vadim Bendebury2b4dcef2018-05-21 10:47:18 -070037
38#include "action_descriptor.h"
rminnich8d3ff912003-10-25 17:01:29 +000039#include "flash.h"
hailfinger66966da2009-06-15 14:14:48 +000040#include "flashchips.h"
hailfinger428f6852010-07-27 22:41:39 +000041#include "programmer.h"
Duncan Laurie25a4ca22019-04-25 12:08:52 -070042#include "spi.h"
Edward O'Callaghan99974452020-10-13 13:28:33 +110043#include "chipdrivers.h"
rminnich8d3ff912003-10-25 17:01:29 +000044
krause2eb76212011-01-17 07:50:42 +000045const char flashrom_version[] = FLASHROM_VERSION;
Edward O'Callaghanc4d1f1c2020-04-17 13:27:23 +100046const char *chip_to_probe = NULL;
hailfinger80422e22009-12-13 22:28:00 +000047
David Hendricks1ed1d352011-11-23 17:54:37 -080048/* error handling stuff */
Edward O'Callaghan0a92ce22020-12-09 17:10:37 +110049static enum error_action access_denied_action = error_ignore;
David Hendricks1ed1d352011-11-23 17:54:37 -080050
51int ignore_error(int err) {
52 int rc = 0;
53
54 switch(err) {
Edward O'Callaghan0a92ce22020-12-09 17:10:37 +110055 case SPI_ACCESS_DENIED:
David Hendricks1ed1d352011-11-23 17:54:37 -080056 if (access_denied_action == error_ignore)
57 rc = 1;
58 break;
59 default:
60 break;
61 }
62
63 return rc;
64}
65
hailfinger969e2f32011-09-08 00:00:29 +000066static enum programmer programmer = PROGRAMMER_INVALID;
Edward O'Callaghanc4d1f1c2020-04-17 13:27:23 +100067static const char *programmer_param = NULL;
stepan782fb172007-04-06 11:58:03 +000068
uwee15beb92010-08-08 17:01:18 +000069/*
hailfinger80422e22009-12-13 22:28:00 +000070 * Programmers supporting multiple buses can have differing size limits on
71 * each bus. Store the limits for each bus in a common struct.
72 */
hailfinger1ff33dc2010-07-03 11:02:10 +000073struct decode_sizes max_rom_decode;
74
75/* If nonzero, used as the start address of bottom-aligned flash. */
76unsigned long flashbase;
hailfinger80422e22009-12-13 22:28:00 +000077
hailfinger5828baf2010-07-03 12:14:25 +000078/* Is writing allowed with this programmer? */
79int programmer_may_write;
80
hailfingerabe249e2009-05-08 17:43:22 +000081const struct programmer_entry programmer_table[] = {
hailfinger90c7d542010-05-31 15:27:27 +000082#if CONFIG_INTERNAL == 1
hailfingerabe249e2009-05-08 17:43:22 +000083 {
hailfinger3548a9a2009-08-12 14:34:35 +000084 .name = "internal",
Edward O'Callaghan0949b782019-11-10 23:23:20 +110085 .type = OTHER,
86 .devs.note = NULL,
hailfinger6c69ab02009-05-11 15:46:43 +000087 .init = internal_init,
hailfinger11ae3c42009-05-11 14:13:25 +000088 .map_flash_region = physmap,
89 .unmap_flash_region = physunmap,
hailfingere5829f62009-06-05 17:48:08 +000090 .delay = internal_delay,
David Hendricks55cdd9c2015-11-25 14:37:26 -080091
92 /*
93 * "Internal" implies in-system programming on a live system, so
94 * handle with paranoia to catch errors early. If something goes
95 * wrong then hopefully the system will still be recoverable.
96 */
97 .paranoid = 1,
hailfingerabe249e2009-05-08 17:43:22 +000098 },
hailfinger80422e22009-12-13 22:28:00 +000099#endif
stepan927d4e22007-04-04 22:45:58 +0000100
hailfinger90c7d542010-05-31 15:27:27 +0000101#if CONFIG_DUMMY == 1
hailfingera9df33c2009-05-09 00:54:55 +0000102 {
hailfinger3548a9a2009-08-12 14:34:35 +0000103 .name = "dummy",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100104 .type = OTHER,
105 /* FIXME */
106 .devs.note = "Dummy device, does nothing and logs all accesses\n",
hailfinger6c69ab02009-05-11 15:46:43 +0000107 .init = dummy_init,
hailfinger11ae3c42009-05-11 14:13:25 +0000108 .map_flash_region = dummy_map,
109 .unmap_flash_region = dummy_unmap,
hailfingere5829f62009-06-05 17:48:08 +0000110 .delay = internal_delay,
hailfingera9df33c2009-05-09 00:54:55 +0000111 },
hailfinger571a6b32009-09-16 10:09:21 +0000112#endif
hailfingera9df33c2009-05-09 00:54:55 +0000113
Edward O'Callaghande8b7632020-09-11 14:33:57 +1000114#if CONFIG_MEC1308 == 1
115 {
116 .name = "mec1308",
117 .type = OTHER,
118 .devs.note = "Microchip MEC1308 Embedded Controller.\n",
119 .init = mec1308_init,
120 .map_flash_region = fallback_map,
121 .unmap_flash_region = fallback_unmap,
122 .delay = internal_delay,
123 },
124#endif
125
hailfinger90c7d542010-05-31 15:27:27 +0000126#if CONFIG_NIC3COM == 1
uwe0f5a3a22009-05-13 11:36:06 +0000127 {
hailfinger3548a9a2009-08-12 14:34:35 +0000128 .name = "nic3com",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100129 .type = PCI,
130 .devs.dev = nics_3com,
uwe0f5a3a22009-05-13 11:36:06 +0000131 .init = nic3com_init,
uwe3e656bd2009-05-17 23:12:17 +0000132 .map_flash_region = fallback_map,
133 .unmap_flash_region = fallback_unmap,
hailfingere5829f62009-06-05 17:48:08 +0000134 .delay = internal_delay,
uwe0f5a3a22009-05-13 11:36:06 +0000135 },
hailfinger571a6b32009-09-16 10:09:21 +0000136#endif
uwe0f5a3a22009-05-13 11:36:06 +0000137
hailfinger90c7d542010-05-31 15:27:27 +0000138#if CONFIG_NICREALTEK == 1
hailfinger5aa36982010-05-21 21:54:07 +0000139 {
hailfinger0d703d42011-03-07 01:08:09 +0000140 /* This programmer works for Realtek RTL8139 and SMC 1211. */
uwe8d342eb2011-07-28 08:13:25 +0000141 .name = "nicrealtek",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100142 .type = PCI,
143 .devs.dev = nics_realtek,
uwe8d342eb2011-07-28 08:13:25 +0000144 .init = nicrealtek_init,
145 .map_flash_region = fallback_map,
146 .unmap_flash_region = fallback_unmap,
uwe8d342eb2011-07-28 08:13:25 +0000147 .delay = internal_delay,
hailfinger5aa36982010-05-21 21:54:07 +0000148 },
hailfinger5aa36982010-05-21 21:54:07 +0000149#endif
150
hailfingerf0a368f2010-06-07 22:37:54 +0000151#if CONFIG_NICNATSEMI == 1
152 {
uwe8d342eb2011-07-28 08:13:25 +0000153 .name = "nicnatsemi",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100154 .type = PCI,
155 .devs.dev = nics_natsemi,
uwe8d342eb2011-07-28 08:13:25 +0000156 .init = nicnatsemi_init,
157 .map_flash_region = fallback_map,
158 .unmap_flash_region = fallback_unmap,
uwe8d342eb2011-07-28 08:13:25 +0000159 .delay = internal_delay,
hailfingerf0a368f2010-06-07 22:37:54 +0000160 },
161#endif
hailfinger5aa36982010-05-21 21:54:07 +0000162
hailfinger90c7d542010-05-31 15:27:27 +0000163#if CONFIG_GFXNVIDIA == 1
uweff4576d2009-09-30 18:29:55 +0000164 {
165 .name = "gfxnvidia",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100166 .type = PCI,
167 .devs.dev = gfx_nvidia,
uweff4576d2009-09-30 18:29:55 +0000168 .init = gfxnvidia_init,
uweff4576d2009-09-30 18:29:55 +0000169 .map_flash_region = fallback_map,
170 .unmap_flash_region = fallback_unmap,
uweff4576d2009-09-30 18:29:55 +0000171 .delay = internal_delay,
172 },
173#endif
174
Edward O'Callaghande8b7632020-09-11 14:33:57 +1000175#if CONFIG_RAIDEN_DEBUG_SPI == 1
176 {
177 .name = "raiden_debug_spi",
178 .type = USB,
179 .devs.dev = devs_raiden,
180 .init = raiden_debug_spi_init,
181 .map_flash_region = fallback_map,
182 .unmap_flash_region = fallback_unmap,
183 .delay = internal_delay,
184 },
185#endif
186
hailfinger90c7d542010-05-31 15:27:27 +0000187#if CONFIG_DRKAISER == 1
ruikda922a12009-05-17 19:39:27 +0000188 {
uwee2f95ef2009-09-02 23:00:46 +0000189 .name = "drkaiser",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100190 .type = PCI,
191 .devs.dev = drkaiser_pcidev,
uwee2f95ef2009-09-02 23:00:46 +0000192 .init = drkaiser_init,
uwee2f95ef2009-09-02 23:00:46 +0000193 .map_flash_region = fallback_map,
194 .unmap_flash_region = fallback_unmap,
uwee2f95ef2009-09-02 23:00:46 +0000195 .delay = internal_delay,
196 },
hailfinger571a6b32009-09-16 10:09:21 +0000197#endif
uwee2f95ef2009-09-02 23:00:46 +0000198
hailfinger90c7d542010-05-31 15:27:27 +0000199#if CONFIG_SATASII == 1
uwee2f95ef2009-09-02 23:00:46 +0000200 {
hailfinger3548a9a2009-08-12 14:34:35 +0000201 .name = "satasii",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100202 .type = PCI,
203 .devs.dev = satas_sii,
ruikda922a12009-05-17 19:39:27 +0000204 .init = satasii_init,
uwe3e656bd2009-05-17 23:12:17 +0000205 .map_flash_region = fallback_map,
206 .unmap_flash_region = fallback_unmap,
hailfingere5829f62009-06-05 17:48:08 +0000207 .delay = internal_delay,
ruikda922a12009-05-17 19:39:27 +0000208 },
hailfinger571a6b32009-09-16 10:09:21 +0000209#endif
ruikda922a12009-05-17 19:39:27 +0000210
hailfinger90c7d542010-05-31 15:27:27 +0000211#if CONFIG_ATAHPT == 1
uwe7e627c82010-02-21 21:17:00 +0000212 {
213 .name = "atahpt",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100214 .type = PCI,
215 .devs.dev = ata_hpt,
uwe7e627c82010-02-21 21:17:00 +0000216 .init = atahpt_init,
uwe7e627c82010-02-21 21:17:00 +0000217 .map_flash_region = fallback_map,
218 .unmap_flash_region = fallback_unmap,
uwe7e627c82010-02-21 21:17:00 +0000219 .delay = internal_delay,
220 },
221#endif
222
Edward O'Callaghande8b7632020-09-11 14:33:57 +1000223#if CONFIG_ATAVIA == 1
224 {
225 .name = "atavia",
226 .type = PCI,
227 .devs.dev = ata_via,
228 .init = atavia_init,
229 .map_flash_region = atavia_map,
230 .unmap_flash_region = fallback_unmap,
231 .delay = internal_delay,
232 },
233#endif
234
235#if CONFIG_ATAPROMISE == 1
236 {
237 .name = "atapromise",
238 .type = PCI,
239 .devs.dev = ata_promise,
240 .init = atapromise_init,
241 .map_flash_region = atapromise_map,
242 .unmap_flash_region = fallback_unmap,
243 .delay = internal_delay,
244 },
245#endif
246
247#if CONFIG_IT8212 == 1
248 {
249 .name = "it8212",
250 .type = PCI,
251 .devs.dev = devs_it8212,
252 .init = it8212_init,
253 .map_flash_region = fallback_map,
254 .unmap_flash_region = fallback_unmap,
255 .delay = internal_delay,
256 },
257#endif
258
hailfinger90c7d542010-05-31 15:27:27 +0000259#if CONFIG_FT2232_SPI == 1
hailfingerf31da3d2009-06-16 21:08:06 +0000260 {
hailfinger90c7d542010-05-31 15:27:27 +0000261 .name = "ft2232_spi",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100262 .type = USB,
Nikolai Artemievc347a852020-04-29 12:17:08 +1000263 .devs.dev = devs_ft2232spi,
hailfingerf31da3d2009-06-16 21:08:06 +0000264 .init = ft2232_spi_init,
hailfinger6fe23d62009-08-12 11:39:29 +0000265 .map_flash_region = fallback_map,
266 .unmap_flash_region = fallback_unmap,
hailfingerf31da3d2009-06-16 21:08:06 +0000267 .delay = internal_delay,
268 },
hailfingerd9dcfbd2009-08-19 13:27:58 +0000269#endif
hailfinger6fe23d62009-08-12 11:39:29 +0000270
hailfinger90c7d542010-05-31 15:27:27 +0000271#if CONFIG_SERPROG == 1
hailfinger37b4fbf2009-06-23 11:33:43 +0000272 {
hailfinger3548a9a2009-08-12 14:34:35 +0000273 .name = "serprog",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100274 .type = OTHER,
275 /* FIXME */
276 .devs.note = "All programmer devices speaking the serprog protocol\n",
hailfinger37b4fbf2009-06-23 11:33:43 +0000277 .init = serprog_init,
Edward O'Callaghan62018182020-10-03 00:16:48 +1000278 .map_flash_region = serprog_map,
hailfinger37b4fbf2009-06-23 11:33:43 +0000279 .unmap_flash_region = fallback_unmap,
hailfinger37b4fbf2009-06-23 11:33:43 +0000280 .delay = serprog_delay,
281 },
hailfinger74d88a72009-08-12 16:17:41 +0000282#endif
hailfingerf31da3d2009-06-16 21:08:06 +0000283
hailfinger90c7d542010-05-31 15:27:27 +0000284#if CONFIG_BUSPIRATE_SPI == 1
hailfinger9c5add72009-11-24 00:20:03 +0000285 {
hailfinger90c7d542010-05-31 15:27:27 +0000286 .name = "buspirate_spi",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100287 .type = OTHER,
288 /* FIXME */
289 .devs.note = "Dangerous Prototypes Bus Pirate\n",
hailfinger9c5add72009-11-24 00:20:03 +0000290 .init = buspirate_spi_init,
hailfinger9c5add72009-11-24 00:20:03 +0000291 .map_flash_region = fallback_map,
292 .unmap_flash_region = fallback_unmap,
hailfinger9c5add72009-11-24 00:20:03 +0000293 .delay = internal_delay,
294 },
295#endif
296
Edward O'Callaghande8b7632020-09-11 14:33:57 +1000297#if CONFIG_DEDIPROG == 1
Anton Staafb2647882014-09-17 15:13:43 -0700298 {
Edward O'Callaghande8b7632020-09-11 14:33:57 +1000299 .name = "dediprog",
Brian J. Nemecb42d6c12020-07-23 03:07:38 -0700300 .type = USB,
Edward O'Callaghanac1678b2020-07-27 15:55:45 +1000301 .devs.dev = devs_dediprog,
Edward O'Callaghande8b7632020-09-11 14:33:57 +1000302 .init = dediprog_init,
Anton Staafb2647882014-09-17 15:13:43 -0700303 .map_flash_region = fallback_map,
304 .unmap_flash_region = fallback_unmap,
305 .delay = internal_delay,
306 },
307#endif
308
Edward O'Callaghande8b7632020-09-11 14:33:57 +1000309#if CONFIG_DEVELOPERBOX_SPI == 1
hailfingerdfb32a02010-01-19 11:15:48 +0000310 {
Edward O'Callaghande8b7632020-09-11 14:33:57 +1000311 .name = "developerbox",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100312 .type = USB,
Edward O'Callaghande8b7632020-09-11 14:33:57 +1000313 .devs.dev = devs_developerbox_spi,
314 .init = developerbox_spi_init,
315 .map_flash_region = fallback_map,
316 .unmap_flash_region = fallback_unmap,
317 .delay = internal_delay,
318 },
319#endif
320
321#if CONFIG_ENE_LPC == 1
322 {
323 .name = "ene_lpc",
324 .type = OTHER,
325 .devs.note = "ENE LPC interface keyboard controller\n",
326 .init = ene_lpc_init,
hailfingerdfb32a02010-01-19 11:15:48 +0000327 .map_flash_region = fallback_map,
328 .unmap_flash_region = fallback_unmap,
hailfingerdfb32a02010-01-19 11:15:48 +0000329 .delay = internal_delay,
330 },
331#endif
332
hailfinger52c4fa02010-07-21 10:26:01 +0000333#if CONFIG_RAYER_SPI == 1
334 {
335 .name = "rayer_spi",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100336 .type = OTHER,
337 /* FIXME */
338 .devs.note = "RayeR parallel port programmer\n",
hailfinger52c4fa02010-07-21 10:26:01 +0000339 .init = rayer_spi_init,
hailfinger52c4fa02010-07-21 10:26:01 +0000340 .map_flash_region = fallback_map,
341 .unmap_flash_region = fallback_unmap,
hailfinger52c4fa02010-07-21 10:26:01 +0000342 .delay = internal_delay,
343 },
344#endif
345
Edward O'Callaghande8b7632020-09-11 14:33:57 +1000346#if CONFIG_PONY_SPI == 1
347 {
348 .name = "pony_spi",
349 .type = OTHER,
350 /* FIXME */
351 .devs.note = "Programmers compatible with SI-Prog, serbang or AJAWe\n",
352 .init = pony_spi_init,
353 .map_flash_region = fallback_map,
354 .unmap_flash_region = fallback_unmap,
355 .delay = internal_delay,
356 },
357#endif
358
hailfinger7949b652011-05-08 00:24:18 +0000359#if CONFIG_NICINTEL == 1
360 {
361 .name = "nicintel",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100362 .type = PCI,
363 .devs.dev = nics_intel,
hailfinger7949b652011-05-08 00:24:18 +0000364 .init = nicintel_init,
hailfinger7949b652011-05-08 00:24:18 +0000365 .map_flash_region = fallback_map,
366 .unmap_flash_region = fallback_unmap,
hailfinger7949b652011-05-08 00:24:18 +0000367 .delay = internal_delay,
368 },
369#endif
370
uwe6764e922010-09-03 18:21:21 +0000371#if CONFIG_NICINTEL_SPI == 1
372 {
uwe8d342eb2011-07-28 08:13:25 +0000373 .name = "nicintel_spi",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100374 .type = PCI,
375 .devs.dev = nics_intel_spi,
uwe8d342eb2011-07-28 08:13:25 +0000376 .init = nicintel_spi_init,
377 .map_flash_region = fallback_map,
378 .unmap_flash_region = fallback_unmap,
uwe8d342eb2011-07-28 08:13:25 +0000379 .delay = internal_delay,
uwe6764e922010-09-03 18:21:21 +0000380 },
381#endif
382
Edward O'Callaghande8b7632020-09-11 14:33:57 +1000383#if CONFIG_NICINTEL_EEPROM == 1
384 {
385 .name = "nicintel_eeprom",
386 .type = PCI,
387 .devs.dev = nics_intel_ee,
388 .init = nicintel_ee_init,
389 .map_flash_region = fallback_map,
390 .unmap_flash_region = fallback_unmap,
391 .delay = internal_delay,
392 },
393#endif
394
hailfingerfb1f31f2010-12-03 14:48:11 +0000395#if CONFIG_OGP_SPI == 1
396 {
uwe8d342eb2011-07-28 08:13:25 +0000397 .name = "ogp_spi",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100398 .type = PCI,
399 .devs.dev = ogp_spi,
uwe8d342eb2011-07-28 08:13:25 +0000400 .init = ogp_spi_init,
401 .map_flash_region = fallback_map,
402 .unmap_flash_region = fallback_unmap,
uwe8d342eb2011-07-28 08:13:25 +0000403 .delay = internal_delay,
hailfingerfb1f31f2010-12-03 14:48:11 +0000404 },
405#endif
406
hailfinger935365d2011-02-04 21:37:59 +0000407#if CONFIG_SATAMV == 1
408 {
409 .name = "satamv",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100410 .type = PCI,
411 .devs.dev = satas_mv,
hailfinger935365d2011-02-04 21:37:59 +0000412 .init = satamv_init,
hailfinger935365d2011-02-04 21:37:59 +0000413 .map_flash_region = fallback_map,
414 .unmap_flash_region = fallback_unmap,
hailfinger935365d2011-02-04 21:37:59 +0000415 .delay = internal_delay,
416 },
417#endif
418
David Hendrickscebee892015-05-23 20:30:30 -0700419#if CONFIG_LINUX_MTD == 1
420 {
421 .name = "linux_mtd",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100422 .type = OTHER,
423 .devs.note = "Device files /dev/mtd*\n",
David Hendrickscebee892015-05-23 20:30:30 -0700424 .init = linux_mtd_init,
425 .map_flash_region = fallback_map,
426 .unmap_flash_region = fallback_unmap,
427 .delay = internal_delay,
428 },
429#endif
430
uwe7df6dda2011-09-03 18:37:52 +0000431#if CONFIG_LINUX_SPI == 1
432 {
433 .name = "linux_spi",
Edward O'Callaghan0949b782019-11-10 23:23:20 +1100434 .type = OTHER,
435 .devs.note = "Device files /dev/spidev*.*\n",
uwe7df6dda2011-09-03 18:37:52 +0000436 .init = linux_spi_init,
437 .map_flash_region = fallback_map,
438 .unmap_flash_region = fallback_unmap,
uwe7df6dda2011-09-03 18:37:52 +0000439 .delay = internal_delay,
440 },
441#endif
442
Shiyu Sun9dde7162020-04-16 17:32:55 +1000443#if CONFIG_LSPCON_I2C_SPI == 1
444 {
445 .name = "lspcon_i2c_spi",
446 .type = OTHER,
447 .devs.note = "Device files /dev/i2c-*.\n",
448 .init = lspcon_i2c_spi_init,
449 .map_flash_region = fallback_map,
450 .unmap_flash_region = fallback_unmap,
451 .delay = internal_delay,
452 },
453#endif
454
Edward O'Callaghan97dd9262020-03-26 00:00:41 +1100455#if CONFIG_REALTEK_MST_I2C_SPI == 1
456 {
457 .name = "realtek_mst_i2c_spi",
458 .type = OTHER,
459 .devs.note = "Device files /dev/i2c-*.\n",
460 .init = realtek_mst_i2c_spi_init,
461 .map_flash_region = fallback_map,
462 .unmap_flash_region = fallback_unmap,
463 .delay = internal_delay,
464 },
465#endif
466
Edward O'Callaghande8b7632020-09-11 14:33:57 +1000467#if CONFIG_USBBLASTER_SPI == 1
468 {
469 .name = "usbblaster_spi",
470 .type = USB,
471 .devs.dev = devs_usbblasterspi,
472 .init = usbblaster_spi_init,
473 .map_flash_region = fallback_map,
474 .unmap_flash_region = fallback_unmap,
475 .delay = internal_delay,
476 },
477#endif
478
479#if CONFIG_MSTARDDC_SPI == 1
480 {
481 .name = "mstarddc_spi",
482 .type = OTHER,
483 .devs.note = "MSTAR DDC devices addressable via /dev/i2c-* on Linux.\n",
484 .init = mstarddc_spi_init,
485 .map_flash_region = fallback_map,
486 .unmap_flash_region = fallback_unmap,
487 .delay = internal_delay,
488 },
489#endif
490
491#if CONFIG_PICKIT2_SPI == 1
492 {
493 .name = "pickit2_spi",
494 .type = USB,
495 .devs.dev = devs_pickit2_spi,
496 .init = pickit2_spi_init,
497 .map_flash_region = fallback_map,
498 .unmap_flash_region = fallback_unmap,
499 .delay = internal_delay,
500 },
501#endif
502
503#if CONFIG_CH341A_SPI == 1
504 {
505 .name = "ch341a_spi",
506 .type = USB,
507 .devs.dev = devs_ch341a_spi,
508 .init = ch341a_spi_init,
509 .map_flash_region = fallback_map,
510 .unmap_flash_region = fallback_unmap,
511 .delay = ch341a_spi_delay,
512 },
513#endif
514
515#if CONFIG_DIGILENT_SPI == 1
516 {
517 .name = "digilent_spi",
518 .type = USB,
519 .devs.dev = devs_digilent_spi,
520 .init = digilent_spi_init,
521 .map_flash_region = fallback_map,
522 .unmap_flash_region = fallback_unmap,
523 .delay = internal_delay,
524 },
525#endif
526
527#if CONFIG_JLINK_SPI == 1
528 {
529 .name = "jlink_spi",
530 .type = OTHER,
531 .init = jlink_spi_init,
532 .devs.note = "SEGGER J-Link and compatible devices\n",
533 .map_flash_region = fallback_map,
534 .unmap_flash_region = fallback_unmap,
535 .delay = internal_delay,
536 },
537#endif
538
539#if CONFIG_NI845X_SPI == 1
540 {
541 .name = "ni845x_spi",
542 .type = OTHER, // choose other because NI-845x uses own USB implementation
543 .devs.note = "National Instruments USB-845x\n",
544 .init = ni845x_spi_init,
545 .map_flash_region = fallback_map,
546 .unmap_flash_region = fallback_unmap,
547 .delay = internal_delay,
548 },
549#endif
550
551#if CONFIG_STLINKV3_SPI == 1
552 {
553 .name = "stlinkv3_spi",
554 .type = USB,
555 .devs.dev = devs_stlinkv3_spi,
556 .init = stlinkv3_spi_init,
557 .map_flash_region = fallback_map,
558 .unmap_flash_region = fallback_unmap,
559 .delay = internal_delay,
560 },
561#endif
562
Edward O'Callaghand8f72232020-09-30 14:21:42 +1000563#if CONFIG_GOOGLE_EC == 1
564 {
565 .name = "google_ec",
566 .type = OTHER,
567 .devs.note = "Google EC.\n",
568 .init = cros_ec_probe_dev,
569 .map_flash_region = fallback_map,
570 .unmap_flash_region = fallback_unmap,
571 .delay = internal_delay,
572 },
573#endif
574
Edward O'Callaghanda29ca82020-10-20 00:49:47 +1100575#if CONFIG_CROS_ALIAS == 1
576 {
577 .name = "ec",
578 .type = OTHER,
579 .devs.note = "Google EC alias mechanism.\n",
580 .init = cros_ec_alias_init,
581 .map_flash_region = physmap, /* TODO(b/171934191) */
582 .unmap_flash_region = physunmap, /* TODO(b/171934191) */
583 .delay = internal_delay,
584
585 /*
586 * "ec" implies in-system programming on a live system, so
587 * handle with paranoia to catch errors early. If something goes
588 * wrong then hopefully the system will still be recoverable.
589 */
590 .paranoid = 1,
591 },
Edward O'Callaghan5b16a082020-10-20 16:30:16 +1100592
593 {
594 .name = "host",
595 .type = OTHER,
596 .devs.note = "Google host alias mechanism.\n",
597 .init = cros_host_alias_init,
598 .map_flash_region = physmap,
599 .unmap_flash_region = physunmap,
600 .delay = internal_delay,
601
602 /*
603 * "Internal" implies in-system programming on a live system, so
604 * handle with paranoia to catch errors early. If something goes
605 * wrong then hopefully the system will still be recoverable.
606 */
607 .paranoid = 1,
608 },
Edward O'Callaghanda29ca82020-10-20 00:49:47 +1100609#endif
610
Patrick Georgi8ddfee92017-03-20 14:54:28 +0100611 {0}, /* This entry corresponds to PROGRAMMER_INVALID. */
hailfingerabe249e2009-05-08 17:43:22 +0000612};
stepan927d4e22007-04-04 22:45:58 +0000613
hailfingerf31cbdc2010-11-10 15:25:18 +0000614#define SHUTDOWN_MAXFN 32
hailfingerdc6f7972010-02-14 01:20:28 +0000615static int shutdown_fn_count = 0;
Edward O'Callaghande8b7632020-09-11 14:33:57 +1000616/** @private */
Edward O'Callaghan60df9dd2019-09-03 14:28:48 +1000617static struct shutdown_func_data {
David Hendricks93784b42016-08-09 17:00:38 -0700618 int (*func) (void *data);
hailfingerdc6f7972010-02-14 01:20:28 +0000619 void *data;
Edward O'Callaghan60df9dd2019-09-03 14:28:48 +1000620} shutdown_fn[SHUTDOWN_MAXFN];
hailfinger1ff33dc2010-07-03 11:02:10 +0000621/* Initialize to 0 to make sure nobody registers a shutdown function before
622 * programmer init.
623 */
624static int may_register_shutdown = 0;
hailfingerdc6f7972010-02-14 01:20:28 +0000625
Daniel Campellofbee2142021-04-20 16:09:09 -0600626/* Did we change something or was every erase/write skipped (if any)? */
627static bool all_skipped = true;
628
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700629static int check_block_eraser(const struct flashctx *flash, int k, int log);
stefanct569dbb62011-07-01 00:19:12 +0000630
hailfingerdc6f7972010-02-14 01:20:28 +0000631/* Register a function to be executed on programmer shutdown.
632 * The advantage over atexit() is that you can supply a void pointer which will
633 * be used as parameter to the registered function upon programmer shutdown.
634 * This pointer can point to arbitrary data used by said function, e.g. undo
635 * information for GPIO settings etc. If unneeded, set data=NULL.
636 * Please note that the first (void *data) belongs to the function signature of
637 * the function passed as first parameter.
638 */
David Hendricks93784b42016-08-09 17:00:38 -0700639int register_shutdown(int (*function) (void *data), void *data)
hailfingerdc6f7972010-02-14 01:20:28 +0000640{
641 if (shutdown_fn_count >= SHUTDOWN_MAXFN) {
hailfinger63932d42010-06-04 23:20:21 +0000642 msg_perr("Tried to register more than %i shutdown functions.\n",
hailfingerdc6f7972010-02-14 01:20:28 +0000643 SHUTDOWN_MAXFN);
644 return 1;
645 }
hailfinger1ff33dc2010-07-03 11:02:10 +0000646 if (!may_register_shutdown) {
647 msg_perr("Tried to register a shutdown function before "
648 "programmer init.\n");
649 return 1;
650 }
hailfingerdc6f7972010-02-14 01:20:28 +0000651 shutdown_fn[shutdown_fn_count].func = function;
652 shutdown_fn[shutdown_fn_count].data = data;
653 shutdown_fn_count++;
654
655 return 0;
656}
657
Nikolai Artemiev55f7a332020-11-05 13:54:27 +1100658int register_chip_restore(chip_restore_fn_cb_t func,
659 struct flashctx *flash, uint8_t status)
660{
661 if (flash->chip_restore_fn_count >= MAX_CHIP_RESTORE_FUNCTIONS) {
662 msg_perr("Tried to register more than %i chip restore"
663 " functions.\n", MAX_CHIP_RESTORE_FUNCTIONS);
664 return 1;
665 }
666 flash->chip_restore_fn[flash->chip_restore_fn_count].func = func;
667 flash->chip_restore_fn[flash->chip_restore_fn_count].status = status;
668 flash->chip_restore_fn_count++;
669
670 return 0;
671}
672
673static int deregister_chip_restore(struct flashctx *flash)
674{
675 int rc = 0;
676
677 while (flash->chip_restore_fn_count > 0) {
678 int i = --flash->chip_restore_fn_count;
679 rc |= flash->chip_restore_fn[i].func(
680 flash, flash->chip_restore_fn[i].status);
681 }
682
683 return rc;
684}
685
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +1000686int programmer_init(enum programmer prog, const char *param)
uweabe92a52009-05-16 22:36:00 +0000687{
hailfinger1ef766d2010-07-06 09:55:48 +0000688 int ret;
hailfinger969e2f32011-09-08 00:00:29 +0000689
690 if (prog >= PROGRAMMER_INVALID) {
691 msg_perr("Invalid programmer specified!\n");
692 return -1;
693 }
694 programmer = prog;
hailfinger1ff33dc2010-07-03 11:02:10 +0000695 /* Initialize all programmer specific data. */
696 /* Default to unlimited decode sizes. */
697 max_rom_decode = (const struct decode_sizes) {
698 .parallel = 0xffffffff,
699 .lpc = 0xffffffff,
700 .fwh = 0xffffffff,
uwe8d342eb2011-07-28 08:13:25 +0000701 .spi = 0xffffffff,
hailfinger1ff33dc2010-07-03 11:02:10 +0000702 };
hailfinger1ff33dc2010-07-03 11:02:10 +0000703 /* Default to top aligned flash at 4 GB. */
704 flashbase = 0;
705 /* Registering shutdown functions is now allowed. */
706 may_register_shutdown = 1;
hailfinger5828baf2010-07-03 12:14:25 +0000707 /* Default to allowing writes. Broken programmers set this to 0. */
708 programmer_may_write = 1;
hailfinger1ff33dc2010-07-03 11:02:10 +0000709
710 programmer_param = param;
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +1000711 msg_pdbg("Initializing %s programmer\n", programmer_table[programmer].name);
David Hendricksac1d25c2016-08-09 17:00:58 -0700712 ret = programmer_table[programmer].init();
Nikolai Artemiev7d9c8ff2020-08-31 14:42:59 +1000713 if (programmer_param && strlen(programmer_param)) {
714 if (ret != 0) {
715 /* It is quite possible that any unhandled programmer parameter would have been valid,
716 * but an error in actual programmer init happened before the parameter was evaluated.
717 */
718 msg_pwarn("Unhandled programmer parameters (possibly due to another failure): %s\n",
719 programmer_param);
720 } else {
721 /* Actual programmer init was successful, but the user specified an invalid or unusable
722 * (for the current programmer configuration) parameter.
723 */
724 msg_perr("Unhandled programmer parameters: %s\n", programmer_param);
725 msg_perr("Aborting.\n");
726 ret = ERROR_FATAL;
727 }
728 }
hailfinger1ef766d2010-07-06 09:55:48 +0000729 return ret;
uweabe92a52009-05-16 22:36:00 +0000730}
731
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +1000732/** Calls registered shutdown functions and resets internal programmer-related variables.
733 * Calling it is safe even without previous initialization, but further interactions with programmer support
734 * require a call to programmer_init() (afterwards).
735 *
736 * @return The OR-ed result values of all shutdown functions (i.e. 0 on success). */
David Hendricks93784b42016-08-09 17:00:38 -0700737int programmer_shutdown(void)
uweabe92a52009-05-16 22:36:00 +0000738{
dhendrix0ffc2eb2011-06-14 01:35:36 +0000739 int ret = 0;
740
hailfinger1ff33dc2010-07-03 11:02:10 +0000741 /* Registering shutdown functions is no longer allowed. */
742 may_register_shutdown = 0;
743 while (shutdown_fn_count > 0) {
744 int i = --shutdown_fn_count;
David Hendricks93784b42016-08-09 17:00:38 -0700745 ret |= shutdown_fn[i].func(shutdown_fn[i].data);
hailfinger1ff33dc2010-07-03 11:02:10 +0000746 }
Edward O'Callaghancf9c40f2020-10-19 20:02:39 +1100747
748 programmer_param = NULL;
749 registered_master_count = 0;
750
dhendrix0ffc2eb2011-06-14 01:35:36 +0000751 return ret;
uweabe92a52009-05-16 22:36:00 +0000752}
753
Edward O'Callaghana5cfb4d2020-09-07 16:26:42 +1000754void *programmer_map_flash_region(const char *descr, uintptr_t phys_addr, size_t len)
uweabe92a52009-05-16 22:36:00 +0000755{
Edward O'Callaghana5cfb4d2020-09-07 16:26:42 +1000756 void *ret = programmer_table[programmer].map_flash_region(descr, phys_addr, len);
Edward O'Callaghanea9e2452020-12-18 11:01:38 +1100757 msg_gspew("%s: mapping %s from 0x%0*" PRIxPTR " to 0x%0*" PRIxPTR "\n",
758 __func__, descr, PRIxPTR_WIDTH, phys_addr, PRIxPTR_WIDTH, (uintptr_t) ret);
Edward O'Callaghana5cfb4d2020-09-07 16:26:42 +1000759 return ret;
uweabe92a52009-05-16 22:36:00 +0000760}
761
762void programmer_unmap_flash_region(void *virt_addr, size_t len)
763{
764 programmer_table[programmer].unmap_flash_region(virt_addr, len);
Edward O'Callaghan79357b32020-08-02 01:24:58 +1000765 msg_gspew("%s: unmapped 0x%0*" PRIxPTR "\n", __func__, PRIxPTR_WIDTH, (uintptr_t)virt_addr);
uweabe92a52009-05-16 22:36:00 +0000766}
767
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700768void chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr)
uweabe92a52009-05-16 22:36:00 +0000769{
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100770 flash->mst->par.chip_writeb(flash, val, addr);
uweabe92a52009-05-16 22:36:00 +0000771}
772
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700773void chip_writew(const struct flashctx *flash, uint16_t val, chipaddr addr)
uweabe92a52009-05-16 22:36:00 +0000774{
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100775 flash->mst->par.chip_writew(flash, val, addr);
uweabe92a52009-05-16 22:36:00 +0000776}
777
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700778void chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr)
uweabe92a52009-05-16 22:36:00 +0000779{
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100780 flash->mst->par.chip_writel(flash, val, addr);
uweabe92a52009-05-16 22:36:00 +0000781}
782
Stuart langleyc98e43f2020-03-26 20:27:36 +1100783void chip_writen(const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len)
hailfinger9d987ef2009-06-05 18:32:07 +0000784{
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100785 flash->mst->par.chip_writen(flash, buf, addr, len);
hailfinger9d987ef2009-06-05 18:32:07 +0000786}
787
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700788uint8_t chip_readb(const struct flashctx *flash, const chipaddr addr)
uweabe92a52009-05-16 22:36:00 +0000789{
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100790 return flash->mst->par.chip_readb(flash, addr);
uweabe92a52009-05-16 22:36:00 +0000791}
792
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700793uint16_t chip_readw(const struct flashctx *flash, const chipaddr addr)
uweabe92a52009-05-16 22:36:00 +0000794{
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100795 return flash->mst->par.chip_readw(flash, addr);
uweabe92a52009-05-16 22:36:00 +0000796}
797
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700798uint32_t chip_readl(const struct flashctx *flash, const chipaddr addr)
uweabe92a52009-05-16 22:36:00 +0000799{
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100800 return flash->mst->par.chip_readl(flash, addr);
uweabe92a52009-05-16 22:36:00 +0000801}
802
Edward O'Callaghana5cfb4d2020-09-07 16:26:42 +1000803void chip_readn(const struct flashctx *flash, uint8_t *buf, chipaddr addr,
804 size_t len)
hailfinger9d987ef2009-06-05 18:32:07 +0000805{
Edward O'Callaghanc66827e2020-10-09 12:22:04 +1100806 flash->mst->par.chip_readn(flash, buf, addr, len);
hailfinger9d987ef2009-06-05 18:32:07 +0000807}
808
Edward O'Callaghanc4d1f1c2020-04-17 13:27:23 +1000809void programmer_delay(unsigned int usecs)
hailfingere5829f62009-06-05 17:48:08 +0000810{
Urja Rannikko71cc94f2013-10-21 21:49:08 +0000811 if (usecs > 0)
812 programmer_table[programmer].delay(usecs);
hailfingere5829f62009-06-05 17:48:08 +0000813}
814
Edward O'Callaghana820b212020-09-17 22:53:26 +1000815int read_memmapped(struct flashctx *flash, uint8_t *buf, unsigned int start,
816 int unsigned len)
hailfinger23060112009-05-08 12:49:03 +0000817{
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700818 chip_readn(flash, buf, flash->virtual_memory + start, len);
uwe8d342eb2011-07-28 08:13:25 +0000819
hailfinger23060112009-05-08 12:49:03 +0000820 return 0;
821}
822
Nikolai Artemiev7d9c8ff2020-08-31 14:42:59 +1000823/* This is a somewhat hacked function similar in some ways to strtok().
824 * It will look for needle with a subsequent '=' in haystack, return a copy of
825 * needle and remove everything from the first occurrence of needle to the next
826 * delimiter from haystack.
hailfinger6e5a52a2009-11-24 18:27:10 +0000827 */
Edward O'Callaghanc4d1f1c2020-04-17 13:27:23 +1000828char *extract_param(const char *const *haystack, const char *needle, const char *delim)
hailfinger6e5a52a2009-11-24 18:27:10 +0000829{
Nikolai Artemiev7d9c8ff2020-08-31 14:42:59 +1000830 char *param_pos, *opt_pos, *rest;
hailfinger1ef766d2010-07-06 09:55:48 +0000831 char *opt = NULL;
832 int optlen;
hailfingerf4aaccc2010-04-28 15:22:14 +0000833 int needlelen;
hailfinger6e5a52a2009-11-24 18:27:10 +0000834
hailfingerf4aaccc2010-04-28 15:22:14 +0000835 needlelen = strlen(needle);
836 if (!needlelen) {
837 msg_gerr("%s: empty needle! Please report a bug at "
838 "flashrom@flashrom.org\n", __func__);
839 return NULL;
840 }
841 /* No programmer parameters given. */
842 if (*haystack == NULL)
843 return NULL;
hailfinger6e5a52a2009-11-24 18:27:10 +0000844 param_pos = strstr(*haystack, needle);
845 do {
846 if (!param_pos)
847 return NULL;
hailfinger1ef766d2010-07-06 09:55:48 +0000848 /* Needle followed by '='? */
849 if (param_pos[needlelen] == '=') {
hailfinger1ef766d2010-07-06 09:55:48 +0000850 /* Beginning of the string? */
851 if (param_pos == *haystack)
852 break;
853 /* After a delimiter? */
854 if (strchr(delim, *(param_pos - 1)))
855 break;
856 }
hailfinger6e5a52a2009-11-24 18:27:10 +0000857 /* Continue searching. */
858 param_pos++;
859 param_pos = strstr(param_pos, needle);
860 } while (1);
uwe8d342eb2011-07-28 08:13:25 +0000861
hailfinger6e5a52a2009-11-24 18:27:10 +0000862 if (param_pos) {
hailfinger1ef766d2010-07-06 09:55:48 +0000863 /* Get the string after needle and '='. */
864 opt_pos = param_pos + needlelen + 1;
865 optlen = strcspn(opt_pos, delim);
866 /* Return an empty string if the parameter was empty. */
867 opt = malloc(optlen + 1);
868 if (!opt) {
snelsone42c3802010-05-07 20:09:04 +0000869 msg_gerr("Out of memory!\n");
hailfinger6e5a52a2009-11-24 18:27:10 +0000870 exit(1);
871 }
hailfinger1ef766d2010-07-06 09:55:48 +0000872 strncpy(opt, opt_pos, optlen);
873 opt[optlen] = '\0';
Nikolai Artemiev7d9c8ff2020-08-31 14:42:59 +1000874 rest = opt_pos + optlen;
875 /* Skip all delimiters after the current parameter. */
876 rest += strspn(rest, delim);
877 memmove(param_pos, rest, strlen(rest) + 1);
878 /* We could shrink haystack, but the effort is not worth it. */
hailfinger6e5a52a2009-11-24 18:27:10 +0000879 }
hailfinger6e5a52a2009-11-24 18:27:10 +0000880
hailfinger1ef766d2010-07-06 09:55:48 +0000881 return opt;
hailfinger6e5a52a2009-11-24 18:27:10 +0000882}
883
Edward O'Callaghana5cfb4d2020-09-07 16:26:42 +1000884char *extract_programmer_param(const char *param_name)
hailfingerddeb4ac2010-07-08 10:13:37 +0000885{
886 return extract_param(&programmer_param, param_name, ",");
887}
888
stefancte1c5acf2011-07-04 07:27:17 +0000889/* Returns the number of well-defined erasers for a chip. */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700890static unsigned int count_usable_erasers(const struct flashctx *flash)
stefanct569dbb62011-07-01 00:19:12 +0000891{
892 unsigned int usable_erasefunctions = 0;
893 int k;
894 for (k = 0; k < NUM_ERASEFUNCTIONS; k++) {
895 if (!check_block_eraser(flash, k, 0))
896 usable_erasefunctions++;
897 }
898 return usable_erasefunctions;
899}
900
Edward O'Callaghan445b48b2020-08-13 12:25:17 +1000901static int compare_range(const uint8_t *wantbuf, const uint8_t *havebuf, unsigned int start, unsigned int len)
Simon Glass4e305f42015-01-08 06:29:04 -0700902{
Edward O'Callaghan445b48b2020-08-13 12:25:17 +1000903 int ret = 0, failcount = 0;
904 unsigned int i;
Simon Glass4e305f42015-01-08 06:29:04 -0700905 for (i = 0; i < len; i++) {
Edward O'Callaghan445b48b2020-08-13 12:25:17 +1000906 if (wantbuf[i] != havebuf[i]) {
907 /* Only print the first failure. */
908 if (!failcount++)
909 msg_cerr("FAILED at 0x%08x! Expected=0x%02x, Found=0x%02x,",
910 start + i, wantbuf[i], havebuf[i]);
Simon Glass4e305f42015-01-08 06:29:04 -0700911 }
912 }
Edward O'Callaghan445b48b2020-08-13 12:25:17 +1000913 if (failcount) {
914 msg_cerr(" failed byte count from 0x%08x-0x%08x: 0x%x\n",
915 start, start + len - 1, failcount);
916 ret = -1;
917 }
918 return ret;
Simon Glass4e305f42015-01-08 06:29:04 -0700919}
920
Edward O'Callaghanfcd4b412020-08-19 14:44:44 +1000921/* start is an offset to the base address of the flash chip */
922static int check_erased_range(struct flashctx *flash, unsigned int start, unsigned int len)
923{
924 int ret;
925 uint8_t *cmpbuf = malloc(len);
926 const uint8_t erased_value = ERASED_VALUE(flash);
927
928 if (!cmpbuf) {
929 msg_gerr("Could not allocate memory!\n");
930 exit(1);
931 }
932 memset(cmpbuf, erased_value, len);
933 ret = verify_range(flash, cmpbuf, start, len);
934 free(cmpbuf);
935 return ret;
936}
937
uwee15beb92010-08-08 17:01:18 +0000938/*
hailfinger7af3d192009-11-25 17:05:52 +0000939 * @cmpbuf buffer to compare against, cmpbuf[0] is expected to match the
uwe8d342eb2011-07-28 08:13:25 +0000940 * flash content at location start
hailfinger7af83692009-06-15 17:23:36 +0000941 * @start offset to the base address of the flash chip
942 * @len length of the verified area
hailfinger7af83692009-06-15 17:23:36 +0000943 * @return 0 for success, -1 for failure
944 */
Edward O'Callaghan445b48b2020-08-13 12:25:17 +1000945int verify_range(struct flashctx *flash, const uint8_t *cmpbuf, unsigned int start, unsigned int len)
hailfinger7af83692009-06-15 17:23:36 +0000946{
hailfinger7af83692009-06-15 17:23:36 +0000947 if (!len)
Edward O'Callaghan2bd87622020-08-13 13:58:45 +1000948 return -1;
hailfinger7af83692009-06-15 17:23:36 +0000949
Patrick Georgif3fa2992017-02-02 16:24:44 +0100950 if (!flash->chip->read) {
snelsone42c3802010-05-07 20:09:04 +0000951 msg_cerr("ERROR: flashrom has no read function for this flash chip.\n");
Edward O'Callaghan2bd87622020-08-13 13:58:45 +1000952 return -1;
hailfingerb0f4d122009-06-24 08:20:45 +0000953 }
Edward O'Callaghan2bd87622020-08-13 13:58:45 +1000954
955 uint8_t *readbuf = malloc(len);
hailfinger7af83692009-06-15 17:23:36 +0000956 if (!readbuf) {
snelsone42c3802010-05-07 20:09:04 +0000957 msg_gerr("Could not allocate memory!\n");
Edward O'Callaghan2bd87622020-08-13 13:58:45 +1000958 return -1;
hailfinger7af83692009-06-15 17:23:36 +0000959 }
Edward O'Callaghan2bd87622020-08-13 13:58:45 +1000960 int ret = 0, failcount = 0;
hailfinger7af83692009-06-15 17:23:36 +0000961
Patrick Georgif3fa2992017-02-02 16:24:44 +0100962 if (start + len > flash->chip->total_size * 1024) {
snelsone42c3802010-05-07 20:09:04 +0000963 msg_gerr("Error: %s called with start 0x%x + len 0x%x >"
hailfinger7af83692009-06-15 17:23:36 +0000964 " total_size 0x%x\n", __func__, start, len,
Patrick Georgif3fa2992017-02-02 16:24:44 +0100965 flash->chip->total_size * 1024);
hailfinger7af83692009-06-15 17:23:36 +0000966 ret = -1;
967 goto out_free;
968 }
Vadim Bendebury2b4dcef2018-05-21 10:47:18 -0700969 msg_gdbg("%#06x..%#06x ", start, start + len -1);
Simon Glass4e305f42015-01-08 06:29:04 -0700970 if (programmer_table[programmer].paranoid) {
971 unsigned int i, chunksize;
David Hendricks1ed1d352011-11-23 17:54:37 -0800972
Simon Glass4e305f42015-01-08 06:29:04 -0700973 /* limit chunksize in order to catch errors early */
974 for (i = 0, chunksize = 0; i < len; i += chunksize) {
975 int tmp;
Douglas Anderson81e58f12021-02-01 13:16:08 -0800976 int chk_acc = 0;
David Hendricks1ed1d352011-11-23 17:54:37 -0800977
Douglas Anderson81e58f12021-02-01 13:16:08 -0800978 /*
979 * Let's work in chunks of at least 4096 bytes at a
980 * time to balance reacting fast but still avoiding the
981 * overhead of working at a smaller size if page_size is
982 * something like 256 bytes.
983 */
984 chunksize = max(flash->chip->page_size, 4096);
985 chunksize = min(chunksize, len - i);
986
987 /*
988 * If we don't have access to some part of this chunk
989 * then bring the size back down to page_size.
990 */
991 if (flash->chip->check_access) {
992 chk_acc = flash->chip->check_access(flash, start + i, chunksize, 0);
993 if (chk_acc) {
994 chunksize = min(chunksize, flash->chip->page_size);
995 chk_acc = flash->chip->check_access(flash, start + i, chunksize, 0);
996 }
997 }
998
Patrick Georgif3fa2992017-02-02 16:24:44 +0100999 tmp = flash->chip->read(flash, readbuf + i, start + i, chunksize);
Simon Glass4e305f42015-01-08 06:29:04 -07001000 if (tmp) {
1001 ret = tmp;
1002 if (ignore_error(tmp))
1003 continue;
1004 else
1005 goto out_free;
David Hendricks1ed1d352011-11-23 17:54:37 -08001006 }
Simon Glass4e305f42015-01-08 06:29:04 -07001007
Duncan Laurie25a4ca22019-04-25 12:08:52 -07001008 /*
1009 * Check write access permission and do not compare chunks
1010 * where flashrom does not have write access to the region.
1011 */
Douglas Anderson81e58f12021-02-01 13:16:08 -08001012 if (chk_acc && ignore_error(chk_acc))
1013 continue;
Duncan Laurie25a4ca22019-04-25 12:08:52 -07001014
Edward O'Callaghan445b48b2020-08-13 12:25:17 +10001015 failcount = compare_range(cmpbuf + i, readbuf + i, start + i, chunksize);
Simon Glass4e305f42015-01-08 06:29:04 -07001016 if (failcount)
1017 break;
David Hendricks1ed1d352011-11-23 17:54:37 -08001018 }
Simon Glass4e305f42015-01-08 06:29:04 -07001019 } else {
1020 int tmp;
1021
1022 /* read as much as we can to reduce transaction overhead */
Patrick Georgif3fa2992017-02-02 16:24:44 +01001023 tmp = flash->chip->read(flash, readbuf, start, len);
Simon Glass4e305f42015-01-08 06:29:04 -07001024 if (tmp && !ignore_error(tmp)) {
1025 ret = tmp;
1026 goto out_free;
1027 }
1028
Edward O'Callaghan445b48b2020-08-13 12:25:17 +10001029 failcount = compare_range(cmpbuf, readbuf, start, len);
hailfinger8cb6ece2010-11-16 17:21:58 +00001030 }
1031
hailfinger5be6c0f2009-07-23 01:42:56 +00001032 if (failcount) {
snelsone42c3802010-05-07 20:09:04 +00001033 msg_cerr(" failed byte count from 0x%08x-0x%08x: 0x%x\n",
uwe8d342eb2011-07-28 08:13:25 +00001034 start, start + len - 1, failcount);
Daniel Campellod27f6592021-05-11 20:14:39 -06001035 ret = 3;
hailfinger5be6c0f2009-07-23 01:42:56 +00001036 }
hailfinger7af83692009-06-15 17:23:36 +00001037
1038out_free:
1039 free(readbuf);
1040 return ret;
1041}
1042
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001043/* Helper function for need_erase() that focuses on granularities of gran bytes. */
1044static int need_erase_gran_bytes(const uint8_t *have, const uint8_t *want, unsigned int len,
Edward O'Callaghan65891c82020-09-07 12:33:06 +10001045 unsigned int gran, const uint8_t erased_value)
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001046{
1047 unsigned int i, j, limit;
1048 for (j = 0; j < len / gran; j++) {
1049 limit = min (gran, len - j * gran);
1050 /* Are 'have' and 'want' identical? */
1051 if (!memcmp(have + j * gran, want + j * gran, limit))
1052 continue;
1053 /* have needs to be in erased state. */
1054 for (i = 0; i < limit; i++)
Edward O'Callaghan65891c82020-09-07 12:33:06 +10001055 if (have[j * gran + i] != erased_value)
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001056 return 1;
1057 }
1058 return 0;
1059}
1060
uwee15beb92010-08-08 17:01:18 +00001061/*
hailfingerb247c7a2010-03-08 00:42:32 +00001062 * Check if the buffer @have can be programmed to the content of @want without
1063 * erasing. This is only possible if all chunks of size @gran are either kept
1064 * as-is or changed from an all-ones state to any other state.
hailfingerb437e282010-11-04 01:04:27 +00001065 *
hailfingerb437e282010-11-04 01:04:27 +00001066 * Warning: This function assumes that @have and @want point to naturally
1067 * aligned regions.
hailfingerb247c7a2010-03-08 00:42:32 +00001068 *
1069 * @have buffer with current content
1070 * @want buffer with desired content
hailfingerb437e282010-11-04 01:04:27 +00001071 * @len length of the checked area
hailfingerb247c7a2010-03-08 00:42:32 +00001072 * @gran write granularity (enum, not count)
1073 * @return 0 if no erase is needed, 1 otherwise
1074 */
Edward O'Callaghanaccf9ff2021-01-22 01:33:03 +11001075static int need_erase(const uint8_t *have, const uint8_t *want, unsigned int len,
Edward O'Callaghan65891c82020-09-07 12:33:06 +10001076 enum write_granularity gran, const uint8_t erased_value)
hailfingerb247c7a2010-03-08 00:42:32 +00001077{
hailfingerb91c08c2011-08-15 19:54:20 +00001078 int result = 0;
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001079 unsigned int i;
William A. Kennington IIIf15c2fa2017-04-07 17:38:42 -07001080
hailfingerb247c7a2010-03-08 00:42:32 +00001081 switch (gran) {
1082 case write_gran_1bit:
1083 for (i = 0; i < len; i++)
1084 if ((have[i] & want[i]) != want[i]) {
1085 result = 1;
1086 break;
1087 }
1088 break;
1089 case write_gran_1byte:
1090 for (i = 0; i < len; i++)
Edward O'Callaghan65891c82020-09-07 12:33:06 +10001091 if ((have[i] != want[i]) && (have[i] != erased_value)) {
hailfingerb247c7a2010-03-08 00:42:32 +00001092 result = 1;
1093 break;
1094 }
1095 break;
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001096 case write_gran_128bytes:
Edward O'Callaghan65891c82020-09-07 12:33:06 +10001097 result = need_erase_gran_bytes(have, want, len, 128, erased_value);
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001098 break;
hailfingerb247c7a2010-03-08 00:42:32 +00001099 case write_gran_256bytes:
Edward O'Callaghan65891c82020-09-07 12:33:06 +10001100 result = need_erase_gran_bytes(have, want, len, 256, erased_value);
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001101 break;
1102 case write_gran_264bytes:
Edward O'Callaghan65891c82020-09-07 12:33:06 +10001103 result = need_erase_gran_bytes(have, want, len, 264, erased_value);
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001104 break;
1105 case write_gran_512bytes:
Edward O'Callaghan65891c82020-09-07 12:33:06 +10001106 result = need_erase_gran_bytes(have, want, len, 512, erased_value);
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001107 break;
1108 case write_gran_528bytes:
Edward O'Callaghan65891c82020-09-07 12:33:06 +10001109 result = need_erase_gran_bytes(have, want, len, 528, erased_value);
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001110 break;
1111 case write_gran_1024bytes:
Edward O'Callaghan65891c82020-09-07 12:33:06 +10001112 result = need_erase_gran_bytes(have, want, len, 1024, erased_value);
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001113 break;
1114 case write_gran_1056bytes:
Edward O'Callaghan65891c82020-09-07 12:33:06 +10001115 result = need_erase_gran_bytes(have, want, len, 1056, erased_value);
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001116 break;
1117 case write_gran_1byte_implicit_erase:
1118 /* Do not erase, handle content changes from anything->0xff by writing 0xff. */
1119 result = 0;
hailfingerb247c7a2010-03-08 00:42:32 +00001120 break;
hailfingerb437e282010-11-04 01:04:27 +00001121 default:
1122 msg_cerr("%s: Unsupported granularity! Please report a bug at "
1123 "flashrom@flashrom.org\n", __func__);
hailfingerb247c7a2010-03-08 00:42:32 +00001124 }
1125 return result;
1126}
1127
hailfingerb437e282010-11-04 01:04:27 +00001128/**
1129 * Check if the buffer @have needs to be programmed to get the content of @want.
1130 * If yes, return 1 and fill in first_start with the start address of the
1131 * write operation and first_len with the length of the first to-be-written
1132 * chunk. If not, return 0 and leave first_start and first_len undefined.
1133 *
1134 * Warning: This function assumes that @have and @want point to naturally
1135 * aligned regions.
1136 *
1137 * @have buffer with current content
1138 * @want buffer with desired content
1139 * @len length of the checked area
1140 * @gran write granularity (enum, not count)
hailfinger90fcf9b2010-11-05 14:51:59 +00001141 * @first_start offset of the first byte which needs to be written (passed in
1142 * value is increased by the offset of the first needed write
1143 * relative to have/want or unchanged if no write is needed)
1144 * @return length of the first contiguous area which needs to be written
1145 * 0 if no write is needed
hailfingerb437e282010-11-04 01:04:27 +00001146 *
1147 * FIXME: This function needs a parameter which tells it about coalescing
1148 * in relation to the max write length of the programmer and the max write
1149 * length of the chip.
1150 */
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10001151static unsigned int get_next_write(const uint8_t *have, const uint8_t *want, unsigned int len,
stefanctc5eb8a92011-11-23 09:13:48 +00001152 unsigned int *first_start,
1153 enum write_granularity gran)
hailfingerb437e282010-11-04 01:04:27 +00001154{
stefanctc5eb8a92011-11-23 09:13:48 +00001155 int need_write = 0;
1156 unsigned int rel_start = 0, first_len = 0;
1157 unsigned int i, limit, stride;
hailfingerb437e282010-11-04 01:04:27 +00001158
hailfingerb437e282010-11-04 01:04:27 +00001159 switch (gran) {
1160 case write_gran_1bit:
1161 case write_gran_1byte:
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001162 case write_gran_1byte_implicit_erase:
hailfinger90fcf9b2010-11-05 14:51:59 +00001163 stride = 1;
hailfingerb437e282010-11-04 01:04:27 +00001164 break;
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001165 case write_gran_128bytes:
1166 stride = 128;
1167 break;
hailfingerb437e282010-11-04 01:04:27 +00001168 case write_gran_256bytes:
hailfinger90fcf9b2010-11-05 14:51:59 +00001169 stride = 256;
hailfingerb437e282010-11-04 01:04:27 +00001170 break;
Edward O'Callaghand8eca562019-02-24 21:10:33 +11001171 case write_gran_264bytes:
1172 stride = 264;
1173 break;
1174 case write_gran_512bytes:
1175 stride = 512;
1176 break;
1177 case write_gran_528bytes:
1178 stride = 528;
1179 break;
1180 case write_gran_1024bytes:
1181 stride = 1024;
1182 break;
1183 case write_gran_1056bytes:
1184 stride = 1056;
1185 break;
hailfingerb437e282010-11-04 01:04:27 +00001186 default:
1187 msg_cerr("%s: Unsupported granularity! Please report a bug at "
1188 "flashrom@flashrom.org\n", __func__);
hailfinger90fcf9b2010-11-05 14:51:59 +00001189 /* Claim that no write was needed. A write with unknown
1190 * granularity is too dangerous to try.
1191 */
1192 return 0;
hailfingerb437e282010-11-04 01:04:27 +00001193 }
hailfinger90fcf9b2010-11-05 14:51:59 +00001194 for (i = 0; i < len / stride; i++) {
1195 limit = min(stride, len - i * stride);
1196 /* Are 'have' and 'want' identical? */
1197 if (memcmp(have + i * stride, want + i * stride, limit)) {
1198 if (!need_write) {
1199 /* First location where have and want differ. */
1200 need_write = 1;
1201 rel_start = i * stride;
1202 }
1203 } else {
1204 if (need_write) {
1205 /* First location where have and want
1206 * do not differ anymore.
1207 */
hailfinger90fcf9b2010-11-05 14:51:59 +00001208 break;
1209 }
1210 }
1211 }
hailfingerffb7f382010-12-06 13:05:44 +00001212 if (need_write)
hailfinger90fcf9b2010-11-05 14:51:59 +00001213 first_len = min(i * stride - rel_start, len);
hailfingerb437e282010-11-04 01:04:27 +00001214 *first_start += rel_start;
hailfinger90fcf9b2010-11-05 14:51:59 +00001215 return first_len;
hailfingerb437e282010-11-04 01:04:27 +00001216}
1217
Edward O'Callaghanc66827e2020-10-09 12:22:04 +11001218/* Returns the number of busses commonly supported by the current programmer and flash chip where the latter
1219 * can not be completely accessed due to size/address limits of the programmer. */
1220unsigned int count_max_decode_exceedings(const struct flashctx *flash)
hailfingeraec9c962009-10-31 01:53:09 +00001221{
Edward O'Callaghanc66827e2020-10-09 12:22:04 +11001222 unsigned int limitexceeded = 0;
1223 uint32_t size = flash->chip->total_size * 1024;
1224 enum chipbustype buses = flash->mst->buses_supported & flash->chip->bustype;
uwe8d342eb2011-07-28 08:13:25 +00001225
1226 if ((buses & BUS_PARALLEL) && (max_rom_decode.parallel < size)) {
hailfingeraec9c962009-10-31 01:53:09 +00001227 limitexceeded++;
snelsone42c3802010-05-07 20:09:04 +00001228 msg_pdbg("Chip size %u kB is bigger than supported "
uwe8d342eb2011-07-28 08:13:25 +00001229 "size %u kB of chipset/board/programmer "
1230 "for %s interface, "
1231 "probe/read/erase/write may fail. ", size / 1024,
1232 max_rom_decode.parallel / 1024, "Parallel");
hailfingeraec9c962009-10-31 01:53:09 +00001233 }
hailfingere1e41ea2011-07-27 07:13:06 +00001234 if ((buses & BUS_LPC) && (max_rom_decode.lpc < size)) {
hailfingeraec9c962009-10-31 01:53:09 +00001235 limitexceeded++;
snelsone42c3802010-05-07 20:09:04 +00001236 msg_pdbg("Chip size %u kB is bigger than supported "
uwe8d342eb2011-07-28 08:13:25 +00001237 "size %u kB of chipset/board/programmer "
1238 "for %s interface, "
1239 "probe/read/erase/write may fail. ", size / 1024,
1240 max_rom_decode.lpc / 1024, "LPC");
hailfingeraec9c962009-10-31 01:53:09 +00001241 }
hailfingere1e41ea2011-07-27 07:13:06 +00001242 if ((buses & BUS_FWH) && (max_rom_decode.fwh < size)) {
hailfingeraec9c962009-10-31 01:53:09 +00001243 limitexceeded++;
snelsone42c3802010-05-07 20:09:04 +00001244 msg_pdbg("Chip size %u kB is bigger than supported "
uwe8d342eb2011-07-28 08:13:25 +00001245 "size %u kB of chipset/board/programmer "
1246 "for %s interface, "
1247 "probe/read/erase/write may fail. ", size / 1024,
1248 max_rom_decode.fwh / 1024, "FWH");
hailfingeraec9c962009-10-31 01:53:09 +00001249 }
hailfingere1e41ea2011-07-27 07:13:06 +00001250 if ((buses & BUS_SPI) && (max_rom_decode.spi < size)) {
hailfingeraec9c962009-10-31 01:53:09 +00001251 limitexceeded++;
snelsone42c3802010-05-07 20:09:04 +00001252 msg_pdbg("Chip size %u kB is bigger than supported "
uwe8d342eb2011-07-28 08:13:25 +00001253 "size %u kB of chipset/board/programmer "
1254 "for %s interface, "
1255 "probe/read/erase/write may fail. ", size / 1024,
1256 max_rom_decode.spi / 1024, "SPI");
hailfingeraec9c962009-10-31 01:53:09 +00001257 }
Edward O'Callaghanc66827e2020-10-09 12:22:04 +11001258 return limitexceeded;
hailfingeraec9c962009-10-31 01:53:09 +00001259}
1260
Edward O'Callaghan79357b32020-08-02 01:24:58 +10001261void unmap_flash(struct flashctx *flash)
1262{
1263 if (flash->virtual_registers != (chipaddr)ERROR_PTR) {
1264 programmer_unmap_flash_region((void *)flash->virtual_registers, flash->chip->total_size * 1024);
1265 flash->physical_registers = 0;
1266 flash->virtual_registers = (chipaddr)ERROR_PTR;
1267 }
1268
1269 if (flash->virtual_memory != (chipaddr)ERROR_PTR) {
1270 programmer_unmap_flash_region((void *)flash->virtual_memory, flash->chip->total_size * 1024);
1271 flash->physical_memory = 0;
1272 flash->virtual_memory = (chipaddr)ERROR_PTR;
1273 }
1274}
1275
1276int map_flash(struct flashctx *flash)
1277{
1278 /* Init pointers to the fail-safe state to distinguish them later from legit values. */
1279 flash->virtual_memory = (chipaddr)ERROR_PTR;
1280 flash->virtual_registers = (chipaddr)ERROR_PTR;
1281
1282 /* FIXME: This avoids mapping (and unmapping) of flash chip definitions with size 0.
1283 * These are used for various probing-related hacks that would not map successfully anyway and should be
1284 * removed ASAP. */
1285 if (flash->chip->total_size == 0)
1286 return 0;
1287
1288 const chipsize_t size = flash->chip->total_size * 1024;
1289 uintptr_t base = flashbase ? flashbase : (0xffffffff - size + 1);
1290 void *addr = programmer_map_flash_region(flash->chip->name, base, size);
1291 if (addr == ERROR_PTR) {
1292 msg_perr("Could not map flash chip %s at 0x%0*" PRIxPTR ".\n",
1293 flash->chip->name, PRIxPTR_WIDTH, base);
1294 return 1;
1295 }
1296 flash->physical_memory = base;
1297 flash->virtual_memory = (chipaddr)addr;
1298
1299 /* FIXME: Special function registers normally live 4 MByte below flash space, but it might be somewhere
1300 * completely different on some chips and programmers, or not mappable at all.
1301 * Ignore these problems for now and always report success. */
1302 if (flash->chip->feature_bits & FEATURE_REGISTERMAP) {
1303 base = 0xffffffff - size - 0x400000 + 1;
1304 addr = programmer_map_flash_region("flash chip registers", base, size);
1305 if (addr == ERROR_PTR) {
1306 msg_pdbg2("Could not map flash chip registers %s at 0x%0*" PRIxPTR ".\n",
1307 flash->chip->name, PRIxPTR_WIDTH, base);
1308 return 0;
1309 }
1310 flash->physical_registers = base;
1311 flash->virtual_registers = (chipaddr)addr;
1312 }
1313 return 0;
1314}
1315
Edward O'Callaghan8488f122019-06-17 12:38:15 +10001316/*
1317 * Return a string corresponding to the bustype parameter.
1318 * Memory is obtained with malloc() and must be freed with free() by the caller.
1319 */
1320char *flashbuses_to_text(enum chipbustype bustype)
1321{
1322 char *ret = calloc(1, 1);
1323 /*
1324 * FIXME: Once all chipsets and flash chips have been updated, NONSPI
1325 * will cease to exist and should be eliminated here as well.
1326 */
1327 if (bustype == BUS_NONSPI) {
1328 ret = strcat_realloc(ret, "Non-SPI, ");
1329 } else {
1330 if (bustype & BUS_PARALLEL)
1331 ret = strcat_realloc(ret, "Parallel, ");
1332 if (bustype & BUS_LPC)
1333 ret = strcat_realloc(ret, "LPC, ");
1334 if (bustype & BUS_FWH)
1335 ret = strcat_realloc(ret, "FWH, ");
1336 if (bustype & BUS_SPI)
1337 ret = strcat_realloc(ret, "SPI, ");
1338 if (bustype & BUS_PROG)
1339 ret = strcat_realloc(ret, "Programmer-specific, ");
1340 if (bustype == BUS_NONE)
1341 ret = strcat_realloc(ret, "None, ");
1342 }
1343 /* Kill last comma. */
1344 ret[strlen(ret) - 2] = '\0';
1345 ret = realloc(ret, strlen(ret) + 1);
1346 return ret;
1347}
1348
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10001349int probe_flash(struct registered_master *mst, int startchip, struct flashctx *flash, int force)
rminnich8d3ff912003-10-25 17:01:29 +00001350{
Edward O'Callaghan723c12c2020-08-01 22:42:00 +10001351 const struct flashchip *chip;
hailfingeraec9c962009-10-31 01:53:09 +00001352 enum chipbustype buses_common;
hailfingera916b422009-06-01 02:08:58 +00001353 char *tmp;
rminnich8d3ff912003-10-25 17:01:29 +00001354
Edward O'Callaghan723c12c2020-08-01 22:42:00 +10001355 for (chip = flashchips + startchip; chip && chip->name; chip++) {
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001356 if (chip_to_probe && strcmp(chip->name, chip_to_probe) != 0)
ollie5672ac62004-03-17 22:22:08 +00001357 continue;
Edward O'Callaghanc66827e2020-10-09 12:22:04 +11001358 buses_common = mst->buses_supported & chip->bustype;
Edward O'Callaghan4b940572019-08-02 01:44:47 +10001359 if (!buses_common)
hailfinger18bd4cc2011-06-17 22:38:53 +00001360 continue;
Edward O'Callaghancc1d0c92019-02-24 15:35:07 +11001361 /* Only probe for SPI25 chips by default. */
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001362 if (chip->bustype == BUS_SPI && !chip_to_probe && chip->spi_cmd_set != SPI25)
Edward O'Callaghancc1d0c92019-02-24 15:35:07 +11001363 continue;
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10001364 msg_gdbg("Probing for %s %s, %d kB: ", chip->vendor, chip->name, chip->total_size);
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001365 if (!chip->probe && !force) {
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10001366 msg_gdbg("failed! flashrom has no probe function for this flash chip.\n");
hailfingera916b422009-06-01 02:08:58 +00001367 continue;
1368 }
stepan782fb172007-04-06 11:58:03 +00001369
hailfinger48ed3e22011-05-04 00:39:50 +00001370 /* Start filling in the dynamic data. */
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001371 flash->chip = calloc(1, sizeof(struct flashchip));
1372 if (!flash->chip) {
Patrick Georgif3fa2992017-02-02 16:24:44 +01001373 msg_gerr("Out of memory!\n");
1374 exit(1);
1375 }
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001376 memcpy(flash->chip, chip, sizeof(struct flashchip));
1377 flash->mst = mst;
hailfinger48ed3e22011-05-04 00:39:50 +00001378
Edward O'Callaghan79357b32020-08-02 01:24:58 +10001379 if (map_flash(flash) != 0)
1380 goto notfound;
rminnich8d3ff912003-10-25 17:01:29 +00001381
Edward O'Callaghana820b212020-09-17 22:53:26 +10001382 /* We handle a forced match like a real match, we just avoid probing. Note that probe_flash()
1383 * is only called with force=1 after normal probing failed.
1384 */
stugec1e55fe2008-07-02 17:15:47 +00001385 if (force)
1386 break;
stepanc98b80b2006-03-16 16:57:41 +00001387
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001388 if (flash->chip->probe(flash) != 1)
stuge56300c32008-09-03 23:10:05 +00001389 goto notfound;
1390
hailfinger48ed3e22011-05-04 00:39:50 +00001391 /* If this is the first chip found, accept it.
1392 * If this is not the first chip found, accept it only if it is
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10001393 * a non-generic match. SFDP and CFI are generic matches.
1394 * startchip==0 means this call to probe_flash() is the first
1395 * one for this programmer interface (master) and thus no other chip has
1396 * been found on this interface.
hailfinger48ed3e22011-05-04 00:39:50 +00001397 */
Edward O'Callaghaneb022ec2020-09-24 22:39:00 +10001398 if (startchip == 0 && flash->chip->model_id == SFDP_DEVICE_ID) {
1399 msg_cinfo("===\n"
1400 "SFDP has autodetected a flash chip which is "
1401 "not natively supported by flashrom yet.\n");
1402 if (count_usable_erasers(flash) == 0)
1403 msg_cinfo("The standard operations read and "
1404 "verify should work, but to support "
1405 "erase, write and all other "
1406 "possible features");
1407 else
1408 msg_cinfo("All standard operations (read, "
1409 "verify, erase and write) should "
1410 "work, but to support all possible "
1411 "features");
1412
1413 msg_cinfo(" we need to add them manually.\n"
1414 "You can help us by mailing us the output of the following command to "
1415 "flashrom@flashrom.org:\n"
1416 "'flashrom -VV [plus the -p/--programmer parameter]'\n"
1417 "Thanks for your help!\n"
1418 "===\n");
1419 }
stugec1e55fe2008-07-02 17:15:47 +00001420
Edward O'Callaghand0fdcb62020-09-24 22:38:44 +10001421 /* First flash chip detected on this bus. */
1422 if (startchip == 0)
1423 break;
1424 /* Not the first flash chip detected on this bus, but not a generic match either. */
Edward O'Callaghaneb022ec2020-09-24 22:39:00 +10001425 if ((flash->chip->model_id != GENERIC_DEVICE_ID) && (flash->chip->model_id != SFDP_DEVICE_ID))
Edward O'Callaghand0fdcb62020-09-24 22:38:44 +10001426 break;
1427 /* Not the first flash chip detected on this bus, and it's just a generic match. Ignore it. */
stuge56300c32008-09-03 23:10:05 +00001428notfound:
Edward O'Callaghan79357b32020-08-02 01:24:58 +10001429 unmap_flash(flash);
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001430 free(flash->chip);
1431 flash->chip = NULL;
rminnich8d3ff912003-10-25 17:01:29 +00001432 }
uwebe4477b2007-08-23 16:08:21 +00001433
Edward O'Callaghanea9e2452020-12-18 11:01:38 +11001434 if (!flash->chip)
hailfinger48ed3e22011-05-04 00:39:50 +00001435 return -1;
stugec1e55fe2008-07-02 17:15:47 +00001436
Edward O'Callaghan53ff4ad2020-12-16 20:36:28 +11001437 /* Fill fallback layout covering the whole chip. */
1438 struct single_layout *const fallback = &flash->fallback_layout;
1439 fallback->base.entries = &fallback->entry;
1440 fallback->base.num_entries = 1;
1441 fallback->entry.start = 0;
1442 fallback->entry.end = flash->chip->total_size * 1024 - 1;
1443 fallback->entry.included = true;
1444 fallback->entry.name = strdup("complete flash");
1445 if (!fallback->entry.name) {
1446 msg_cerr("Failed to probe chip: %s\n", strerror(errno));
1447 return -1;
1448 }
stepan3e7aeae2011-01-19 06:21:54 +00001449
Edward O'Callaghanea9e2452020-12-18 11:01:38 +11001450 tmp = flashbuses_to_text(flash->chip->bustype);
Edward O'Callaghana820b212020-09-17 22:53:26 +10001451 msg_cinfo("%s %s flash chip \"%s\" (%d kB, %s) ", force ? "Assuming" : "Found",
1452 flash->chip->vendor, flash->chip->name, flash->chip->total_size, tmp);
stefanct588b6d22011-06-26 20:45:35 +00001453 free(tmp);
Edward O'Callaghan79357b32020-08-02 01:24:58 +10001454#if CONFIG_INTERNAL == 1
1455 if (programmer_table[programmer].map_flash_region == physmap)
1456 msg_cinfo("mapped at physical address 0x%0*" PRIxPTR ".\n",
1457 PRIxPTR_WIDTH, flash->physical_memory);
1458 else
1459#endif
1460 msg_cinfo("on %s.\n", programmer_table[programmer].name);
uwe9e6811e2009-06-28 21:47:57 +00001461
Edward O'Callaghana820b212020-09-17 22:53:26 +10001462 /* Flash registers may more likely not be mapped if the chip was forced.
1463 * Lock info may be stored in registers, so avoid lock info printing. */
hailfinger0f4c3952010-12-02 21:59:42 +00001464 if (!force)
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001465 if (flash->chip->printlock)
1466 flash->chip->printlock(flash);
snelson1ee293c2010-02-19 00:52:10 +00001467
Edward O'Callaghan79357b32020-08-02 01:24:58 +10001468 /* Get out of the way for later runs. */
1469 unmap_flash(flash);
1470
hailfinger48ed3e22011-05-04 00:39:50 +00001471 /* Return position of matching chip. */
Edward O'Callaghan723c12c2020-08-01 22:42:00 +10001472 return chip - flashchips;
rminnich8d3ff912003-10-25 17:01:29 +00001473}
1474
uwe8d342eb2011-07-28 08:13:25 +00001475int read_buf_from_file(unsigned char *buf, unsigned long size,
1476 const char *filename)
hailfinger771fc182010-10-15 00:01:14 +00001477{
Edward O'Callaghan597e2972020-12-13 12:24:49 +11001478#ifdef __LIBPAYLOAD__
1479 msg_gerr("Error: No file I/O support in libpayload\n");
1480 return 1;
1481#else
Edward O'Callaghane20f1582020-12-13 11:58:37 +11001482 int ret = 0;
Edward O'Callaghan3f972992020-10-26 01:48:37 +00001483
Edward O'Callaghane20f1582020-12-13 11:58:37 +11001484 FILE *image;
Daniel Campello3adfd2d2021-04-15 10:36:04 -06001485 if (!strcmp(filename, "-"))
1486 image = fdopen(fileno(stdin), "rb");
Edward O'Callaghan3f972992020-10-26 01:48:37 +00001487 else
1488 image = fopen(filename, "rb");
1489 if (image == NULL) {
Edward O'Callaghan1c7092d2020-12-13 12:28:57 +11001490 msg_gerr("Error: opening file \"%s\" failed: %s\n", filename, strerror(errno));
hailfinger771fc182010-10-15 00:01:14 +00001491 return 1;
1492 }
Edward O'Callaghane20f1582020-12-13 11:58:37 +11001493
1494 struct stat image_stat;
hailfinger771fc182010-10-15 00:01:14 +00001495 if (fstat(fileno(image), &image_stat) != 0) {
Edward O'Callaghan1c7092d2020-12-13 12:28:57 +11001496 msg_gerr("Error: getting metadata of file \"%s\" failed: %s\n", filename, strerror(errno));
Edward O'Callaghane20f1582020-12-13 11:58:37 +11001497 ret = 1;
1498 goto out;
hailfinger771fc182010-10-15 00:01:14 +00001499 }
Daniel Campello3adfd2d2021-04-15 10:36:04 -06001500 if ((image_stat.st_size != (intmax_t)size) && strcmp(filename, "-")) {
Daniel Campellocb88c9a2021-04-13 19:23:47 -06001501 msg_gerr("Error: Image size (%jd B) doesn't match the expected size (%lu B)!\n",
Edward O'Callaghan1c7092d2020-12-13 12:28:57 +11001502 (intmax_t)image_stat.st_size, size);
Edward O'Callaghane20f1582020-12-13 11:58:37 +11001503 ret = 1;
1504 goto out;
hailfinger771fc182010-10-15 00:01:14 +00001505 }
Edward O'Callaghane20f1582020-12-13 11:58:37 +11001506
1507 unsigned long numbytes = fread(buf, 1, size, image);
hailfinger771fc182010-10-15 00:01:14 +00001508 if (numbytes != size) {
1509 msg_gerr("Error: Failed to read complete file. Got %ld bytes, "
1510 "wanted %ld!\n", numbytes, size);
Edward O'Callaghane20f1582020-12-13 11:58:37 +11001511 ret = 1;
hailfinger771fc182010-10-15 00:01:14 +00001512 }
Edward O'Callaghane20f1582020-12-13 11:58:37 +11001513out:
1514 (void)fclose(image);
1515 return ret;
Edward O'Callaghan597e2972020-12-13 12:24:49 +11001516#endif
hailfinger771fc182010-10-15 00:01:14 +00001517}
1518
Daniel Campellocb88c9a2021-04-13 19:23:47 -06001519/**
1520 * @brief Reads content to buffer from one or more files.
1521 *
1522 * Reads content to supplied buffer from files. If a filename is specified for
1523 * individual regions using the partial read syntax ('-i <region>[:<filename>]')
1524 * then this will read file data into the corresponding region in the
1525 * supplied buffer.
1526 *
1527 * @param flashctx Flash context to be used.
1528 * @param buf Chip-sized buffer to write data to
1529 * @return 0 on success
1530 */
1531static int read_buf_from_include_args(const struct flashctx *const flash,
1532 unsigned char *buf)
1533{
1534 const struct flashrom_layout *const layout = get_layout(flash);
1535 const struct romentry *entry = NULL;
1536
1537 /*
1538 * Content will be read from -i args, so they must not overlap since
1539 * we need to know exactly what content to write to the ROM.
1540 */
1541 if (included_regions_overlap(layout)) {
Daniel Campello2fdc8372021-04-16 17:52:51 -06001542 msg_gerr("Error: Included regions must not overlap when writing.\n");
Daniel Campellocb88c9a2021-04-13 19:23:47 -06001543 return 1;
1544 }
1545
1546 while ((entry = layout_next_included(layout, entry))) {
1547 if (!entry->file)
1548 continue;
1549 if (read_buf_from_file(buf + entry->start,
1550 entry->end - entry->start + 1, entry->file))
1551 return 1;
1552 }
1553 return 0;
1554}
1555
1556/**
1557 * @brief Writes passed data buffer into a file
1558 *
1559 * @param buf Buffer with data to write
1560 * @param size Size of buffer
1561 * @param filename File path to write to
1562 * @return 0 on success
1563 */
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10001564int write_buf_to_file(const unsigned char *buf, unsigned long size, const char *filename)
hailfingerd219a232009-01-28 00:27:54 +00001565{
Edward O'Callaghan597e2972020-12-13 12:24:49 +11001566#ifdef __LIBPAYLOAD__
1567 msg_gerr("Error: No file I/O support in libpayload\n");
1568 return 1;
1569#else
hailfingerd219a232009-01-28 00:27:54 +00001570 FILE *image;
Edward O'Callaghane20f1582020-12-13 11:58:37 +11001571 int ret = 0;
hailfingerde345862009-06-01 22:07:52 +00001572
1573 if (!filename) {
hailfinger42a850a2010-07-13 23:56:13 +00001574 msg_gerr("No filename specified.\n");
hailfingerde345862009-06-01 22:07:52 +00001575 return 1;
1576 }
Daniel Campello3adfd2d2021-04-15 10:36:04 -06001577 if ((image = fopen(filename, "wb")) == NULL) {
Edward O'Callaghan1c7092d2020-12-13 12:28:57 +11001578 msg_gerr("Error: opening file \"%s\" failed: %s\n", filename, strerror(errno));
hailfinger23060112009-05-08 12:49:03 +00001579 return 1;
hailfinger42a850a2010-07-13 23:56:13 +00001580 }
hailfingerd219a232009-01-28 00:27:54 +00001581
Edward O'Callaghane20f1582020-12-13 11:58:37 +11001582 unsigned long numbytes = fwrite(buf, 1, size, image);
hailfinger42a850a2010-07-13 23:56:13 +00001583 if (numbytes != size) {
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10001584 msg_gerr("Error: file %s could not be written completely.\n", filename);
Edward O'Callaghane20f1582020-12-13 11:58:37 +11001585 ret = 1;
1586 goto out;
hailfinger42a850a2010-07-13 23:56:13 +00001587 }
Edward O'Callaghane20f1582020-12-13 11:58:37 +11001588 if (fflush(image)) {
1589 msg_gerr("Error: flushing file \"%s\" failed: %s\n", filename, strerror(errno));
1590 ret = 1;
1591 }
1592 // Try to fsync() only regular files and if that function is available at all (e.g. not on MinGW).
1593#if defined(_POSIX_FSYNC) && (_POSIX_FSYNC != -1)
1594 struct stat image_stat;
1595 if (fstat(fileno(image), &image_stat) != 0) {
1596 msg_gerr("Error: getting metadata of file \"%s\" failed: %s\n", filename, strerror(errno));
1597 ret = 1;
1598 goto out;
1599 }
1600 if (S_ISREG(image_stat.st_mode)) {
1601 if (fsync(fileno(image))) {
1602 msg_gerr("Error: fsyncing file \"%s\" failed: %s\n", filename, strerror(errno));
1603 ret = 1;
1604 }
1605 }
1606#endif
1607out:
1608 if (fclose(image)) {
1609 msg_gerr("Error: closing file \"%s\" failed: %s\n", filename, strerror(errno));
1610 ret = 1;
1611 }
1612 return ret;
Edward O'Callaghan597e2972020-12-13 12:24:49 +11001613#endif
hailfingerd219a232009-01-28 00:27:54 +00001614}
1615
Daniel Campellocb88c9a2021-04-13 19:23:47 -06001616/**
1617 * @brief Writes content from buffer to one or more files.
1618 *
1619 * Writes content from supplied buffer to files. If a filename is specified for
1620 * individual regions using the partial read syntax ('-i <region>[:<filename>]')
1621 * then this will write files using data from the corresponding region in the
1622 * supplied buffer.
1623 *
1624 * @param flashctx Flash context to be used.
1625 * @param buf Chip-sized buffer to read data from
1626 * @return 0 on success
1627 */
1628static int write_buf_to_include_args(const struct flashctx *const flash,
1629 unsigned char *buf)
1630{
Daniel Campellocb88c9a2021-04-13 19:23:47 -06001631 const struct flashrom_layout *const layout = get_layout(flash);
1632 const struct romentry *entry = NULL;
1633
1634 while ((entry = layout_next_included(layout, entry))) {
1635 if (!entry->file)
1636 continue;
1637 if (write_buf_to_file(buf + entry->start,
1638 entry->end - entry->start + 1, entry->file))
1639 return 1;
1640 }
1641
1642 return 0;
Daniel Campellocb88c9a2021-04-13 19:23:47 -06001643}
1644
David Hendrickse3451942013-03-21 17:23:29 -07001645/*
1646 * read_flash - wrapper for flash->read() with additional high-level policy
1647 *
1648 * @flash flash chip
1649 * @buf buffer to store data in
1650 * @start start address
1651 * @len number of bytes to read
1652 *
1653 * This wrapper simplifies most cases when the flash chip needs to be read
1654 * since policy decisions such as non-fatal error handling is centralized.
1655 */
Daniel Campello241c6bf2021-04-19 09:58:47 -06001656static int read_flash(struct flashctx *flash, uint8_t *buf,
1657 unsigned int start, unsigned int len)
David Hendrickse3451942013-03-21 17:23:29 -07001658{
David Hendricks4e76fdc2013-05-13 16:05:36 -07001659 int ret;
David Hendrickse3451942013-03-21 17:23:29 -07001660
Patrick Georgif3fa2992017-02-02 16:24:44 +01001661 if (!flash || !flash->chip->read)
David Hendrickse3451942013-03-21 17:23:29 -07001662 return -1;
1663
Vadim Bendebury2b4dcef2018-05-21 10:47:18 -07001664 msg_cdbg("%#06x-%#06x:R ", start, start + len - 1);
1665
Patrick Georgif3fa2992017-02-02 16:24:44 +01001666 ret = flash->chip->read(flash, buf, start, len);
David Hendrickse3451942013-03-21 17:23:29 -07001667 if (ret) {
1668 if (ignore_error(ret)) {
1669 msg_gdbg("ignoring error when reading 0x%x-0x%x\n",
1670 start, start + len - 1);
1671 ret = 0;
1672 } else {
1673 msg_gdbg("failed to read 0x%x-0x%x\n",
1674 start, start + len - 1);
1675 }
1676 }
1677
1678 return ret;
1679}
1680
David Hendricks7c8a1612013-04-26 19:14:44 -07001681/*
1682 * write_flash - wrapper for flash->write() with additional high-level policy
1683 *
1684 * @flash flash chip
1685 * @buf buffer to write to flash
1686 * @start start address in flash
1687 * @len number of bytes to write
1688 *
1689 * TODO: Look up regions that are write-protected and avoid attempt to write
1690 * to them at all.
1691 */
Daniel Campellofbee2142021-04-20 16:09:09 -06001692static int write_flash(struct flashctx *flash, const uint8_t *buf,
1693 unsigned int start, unsigned int len)
David Hendricks7c8a1612013-04-26 19:14:44 -07001694{
Patrick Georgif3fa2992017-02-02 16:24:44 +01001695 if (!flash || !flash->chip->write)
David Hendricks7c8a1612013-04-26 19:14:44 -07001696 return -1;
1697
Patrick Georgif3fa2992017-02-02 16:24:44 +01001698 return flash->chip->write(flash, buf, start, len);
David Hendricks7c8a1612013-04-26 19:14:44 -07001699}
1700
Daniel Campello731d8932021-04-21 13:02:22 -06001701static int read_by_layout(struct flashctx *, uint8_t *, bool);
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001702int read_flash_to_file(struct flashctx *flash, const char *filename)
hailfinger42a850a2010-07-13 23:56:13 +00001703{
Patrick Georgif3fa2992017-02-02 16:24:44 +01001704 unsigned long size = flash->chip->total_size * 1024;
Richard Hughes74eec602018-12-19 15:30:39 +00001705 unsigned char *buf = calloc(size, sizeof(unsigned char));
hailfinger42a850a2010-07-13 23:56:13 +00001706 int ret = 0;
1707
1708 msg_cinfo("Reading flash... ");
1709 if (!buf) {
1710 msg_gerr("Memory allocation failed!\n");
1711 msg_cinfo("FAILED.\n");
1712 return 1;
1713 }
Louis Yung-Chieh Lo9c7525f2011-03-04 12:32:02 +08001714
1715 /* To support partial read, fill buffer to all 0xFF at beginning to make
1716 * debug easier. */
Edward O'Callaghanef783e32020-08-10 19:54:27 +10001717 memset(buf, ERASED_VALUE(flash), size);
Louis Yung-Chieh Lo9c7525f2011-03-04 12:32:02 +08001718
Patrick Georgif3fa2992017-02-02 16:24:44 +01001719 if (!flash->chip->read) {
hailfinger42a850a2010-07-13 23:56:13 +00001720 msg_cerr("No read function available for this flash chip.\n");
1721 ret = 1;
1722 goto out_free;
1723 }
Daniel Campello731d8932021-04-21 13:02:22 -06001724 if (read_by_layout(flash, buf, false)) {
Daniel Campello6b0f1fc2021-04-09 21:28:12 -06001725 msg_cerr("Read operation failed!\n");
Louis Yung-Chieh Lo9c7525f2011-03-04 12:32:02 +08001726 ret = 1;
1727 goto out_free;
Daniel Campello6b0f1fc2021-04-09 21:28:12 -06001728 }
Daniel Campellocb88c9a2021-04-13 19:23:47 -06001729 if (write_buf_to_include_args(flash, buf)) {
Daniel Campello6b0f1fc2021-04-09 21:28:12 -06001730 ret = 1;
1731 goto out_free;
hailfinger42a850a2010-07-13 23:56:13 +00001732 }
1733
David Hendricksdf29a832013-06-28 14:33:51 -07001734 if (filename)
1735 ret = write_buf_to_file(buf, size, filename);
hailfinger42a850a2010-07-13 23:56:13 +00001736out_free:
1737 free(buf);
Edward O'Callaghan6b2ff8a2020-12-11 14:33:23 +11001738 msg_cinfo("%s.\n", ret ? "FAILED" : "done");
hailfinger42a850a2010-07-13 23:56:13 +00001739 return ret;
1740}
1741
Edward O'Callaghan6240c852019-07-02 15:49:58 +10001742/* Even if an error is found, the function will keep going and check the rest. */
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001743static int selfcheck_eraseblocks(const struct flashchip *chip)
hailfinger45177872010-01-18 08:14:43 +00001744{
hailfingerb91c08c2011-08-15 19:54:20 +00001745 int i, j, k;
1746 int ret = 0;
hailfinger45177872010-01-18 08:14:43 +00001747
1748 for (k = 0; k < NUM_ERASEFUNCTIONS; k++) {
1749 unsigned int done = 0;
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001750 struct block_eraser eraser = chip->block_erasers[k];
hailfinger45177872010-01-18 08:14:43 +00001751
1752 for (i = 0; i < NUM_ERASEREGIONS; i++) {
1753 /* Blocks with zero size are bugs in flashchips.c. */
1754 if (eraser.eraseblocks[i].count &&
1755 !eraser.eraseblocks[i].size) {
1756 msg_gerr("ERROR: Flash chip %s erase function "
1757 "%i region %i has size 0. Please report"
1758 " a bug at flashrom@flashrom.org\n",
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001759 chip->name, k, i);
hailfinger9fed35d2010-01-19 06:42:46 +00001760 ret = 1;
hailfinger45177872010-01-18 08:14:43 +00001761 }
1762 /* Blocks with zero count are bugs in flashchips.c. */
1763 if (!eraser.eraseblocks[i].count &&
1764 eraser.eraseblocks[i].size) {
1765 msg_gerr("ERROR: Flash chip %s erase function "
1766 "%i region %i has count 0. Please report"
1767 " a bug at flashrom@flashrom.org\n",
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001768 chip->name, k, i);
hailfinger9fed35d2010-01-19 06:42:46 +00001769 ret = 1;
hailfinger45177872010-01-18 08:14:43 +00001770 }
1771 done += eraser.eraseblocks[i].count *
1772 eraser.eraseblocks[i].size;
1773 }
hailfinger9fed35d2010-01-19 06:42:46 +00001774 /* Empty eraseblock definition with erase function. */
1775 if (!done && eraser.block_erase)
snelsone42c3802010-05-07 20:09:04 +00001776 msg_gspew("Strange: Empty eraseblock definition with "
uwe8d342eb2011-07-28 08:13:25 +00001777 "non-empty erase function. Not an error.\n");
hailfinger45177872010-01-18 08:14:43 +00001778 if (!done)
1779 continue;
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001780 if (done != chip->total_size * 1024) {
hailfinger45177872010-01-18 08:14:43 +00001781 msg_gerr("ERROR: Flash chip %s erase function %i "
1782 "region walking resulted in 0x%06x bytes total,"
1783 " expected 0x%06x bytes. Please report a bug at"
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001784 " flashrom@flashrom.org\n", chip->name, k,
1785 done, chip->total_size * 1024);
hailfinger9fed35d2010-01-19 06:42:46 +00001786 ret = 1;
hailfinger45177872010-01-18 08:14:43 +00001787 }
hailfinger9fed35d2010-01-19 06:42:46 +00001788 if (!eraser.block_erase)
1789 continue;
1790 /* Check if there are identical erase functions for different
1791 * layouts. That would imply "magic" erase functions. The
1792 * easiest way to check this is with function pointers.
1793 */
uwef6f94d42010-03-13 17:28:29 +00001794 for (j = k + 1; j < NUM_ERASEFUNCTIONS; j++) {
hailfinger9fed35d2010-01-19 06:42:46 +00001795 if (eraser.block_erase ==
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001796 chip->block_erasers[j].block_erase) {
hailfinger9fed35d2010-01-19 06:42:46 +00001797 msg_gerr("ERROR: Flash chip %s erase function "
1798 "%i and %i are identical. Please report"
1799 " a bug at flashrom@flashrom.org\n",
Edward O'Callaghanf93b3742019-02-24 17:24:27 +11001800 chip->name, k, j);
hailfinger9fed35d2010-01-19 06:42:46 +00001801 ret = 1;
1802 }
uwef6f94d42010-03-13 17:28:29 +00001803 }
hailfinger45177872010-01-18 08:14:43 +00001804 }
hailfinger9fed35d2010-01-19 06:42:46 +00001805 return ret;
hailfinger45177872010-01-18 08:14:43 +00001806}
1807
Edward O'Callaghanbef74c22020-12-04 16:23:54 +11001808static int check_block_eraser(const struct flashctx *flash, int k, int log)
1809{
1810 struct block_eraser eraser = flash->chip->block_erasers[k];
1811
1812 if (!eraser.block_erase && !eraser.eraseblocks[0].count) {
1813 if (log)
1814 msg_cdbg("not defined. ");
1815 return 1;
1816 }
1817 if (!eraser.block_erase && eraser.eraseblocks[0].count) {
1818 if (log)
1819 msg_cdbg("eraseblock layout is known, but matching "
1820 "block erase function is not implemented. ");
1821 return 1;
1822 }
1823 if (eraser.block_erase && !eraser.eraseblocks[0].count) {
1824 if (log)
1825 msg_cdbg("block erase function found, but "
1826 "eraseblock layout is not defined. ");
1827 return 1;
1828 }
1829 // TODO: Once erase functions are annotated with allowed buses, check that as well.
1830 return 0;
1831}
1832
Daniel Campello488f2432021-04-28 15:00:38 -06001833/*
1834 * Gets the lowest erase granularity; it is used when
1835 * deciding if the layout map needs to be adjusted such that erase boundaries
1836 * match this granularity. Returns -1 if unsuccessful.
1837 */
1838static int get_required_erase_size(struct flashctx *flash)
1839{
1840 int i, erase_size_found = 0;
1841 unsigned int required_erase_size;
1842
1843 /*
1844 * Find eraseable block size for read alignment.
1845 * FIXME: This assumes the smallest block erase size is useable
1846 * by erase_and_write_flash().
1847 */
1848 required_erase_size = ~0;
1849 for (i = 0; i < NUM_ERASEFUNCTIONS; i++) {
1850 struct block_eraser eraser = flash->chip->block_erasers[i];
1851 int j;
1852
1853 for (j = 0; j < NUM_ERASEREGIONS; j++) {
1854 unsigned int size = eraser.eraseblocks[j].size;
1855
1856 if (size && (size < required_erase_size)) {
1857 required_erase_size = size;
1858 erase_size_found = 1;
1859 }
1860 }
1861 }
1862
1863 /* likely an error in flashchips[] */
1864 if (!erase_size_found) {
1865 msg_cerr("%s: No usable erase size found.\n", __func__);
1866 return -1;
1867 }
1868
1869 return required_erase_size;
1870}
1871
1872static int round_to_erasable_block_boundary(const int required_erase_size,
1873 const struct romentry *entry,
1874 chipoff_t *rounded_start,
1875 chipsize_t* rounded_len) {
1876 unsigned int start_align, len_align;
1877
1878 if (required_erase_size < 0)
1879 return 1;
1880
1881 /* round down to nearest eraseable block boundary */
1882 start_align = entry->start % required_erase_size;
1883 *rounded_start = entry->start - start_align;
1884
1885 /* round up to nearest eraseable block boundary */
1886 *rounded_len = entry->end - *rounded_start + 1;
1887 len_align = *rounded_len % required_erase_size;
1888 if (len_align)
1889 *rounded_len = *rounded_len + required_erase_size - len_align;
1890
1891 if (start_align || len_align) {
1892 msg_gdbg("\n%s: Re-aligned partial read due to eraseable "
1893 "block size requirement:\n\tstart: 0x%06x, "
1894 "len: 0x%06x, aligned start: 0x%06x, len: 0x%06x\n",
1895 __func__, entry->start, entry->end - entry->start + 1,
1896 *rounded_start, *rounded_len);
1897 }
1898
1899 return 0;
1900}
1901
Daniel Campello6b0f1fc2021-04-09 21:28:12 -06001902/**
1903 * @brief Reads the included layout regions into a buffer.
1904 *
1905 * If there is no layout set in the given flash context, the whole chip will
1906 * be read.
1907 *
1908 * @param flashctx Flash context to be used.
1909 * @param buffer Buffer of full chip size to read into.
1910 * @return 0 on success,
1911 * 1 if any read fails.
1912 */
Daniel Campello731d8932021-04-21 13:02:22 -06001913static int read_by_layout(struct flashctx *const flashctx, uint8_t *const buffer,
1914 bool align_to_erasable_block_boundary)
Daniel Campello6b0f1fc2021-04-09 21:28:12 -06001915{
1916 const struct flashrom_layout *const layout = get_layout(flashctx);
1917 const struct romentry *entry = NULL;
1918 int required_erase_size = get_required_erase_size(flashctx);
1919
1920 while ((entry = layout_next_included(layout, entry))) {
Daniel Campello731d8932021-04-21 13:02:22 -06001921 chipoff_t region_start = entry->start;
1922 chipsize_t region_len = entry->end - entry->start + 1;
Daniel Campello6b0f1fc2021-04-09 21:28:12 -06001923
Daniel Campello731d8932021-04-21 13:02:22 -06001924 if (align_to_erasable_block_boundary &&
1925 round_to_erasable_block_boundary(required_erase_size, entry,
1926 &region_start, &region_len))
Daniel Campello6b0f1fc2021-04-09 21:28:12 -06001927 return 1;
Daniel Campello731d8932021-04-21 13:02:22 -06001928 if (read_flash(flashctx, buffer + region_start, region_start, region_len))
Daniel Campello6b0f1fc2021-04-09 21:28:12 -06001929 return 1;
1930 }
1931 return 0;
1932}
1933
Edward O'Callaghan58c3f382020-12-04 16:26:55 +11001934typedef int (*erasefn_t)(struct flashctx *, unsigned int addr, unsigned int len);
Edward O'Callaghan2fc12e22020-12-10 10:32:26 +11001935/**
1936 * @private
1937 *
1938 * For read-erase-write, `curcontents` and `newcontents` shall point
1939 * to buffers of the chip's size. Both are supposed to be prefilled
1940 * with at least the included layout regions of the current flash
1941 * contents (`curcontents`) and the data to be written to the flash
1942 * (`newcontents`).
1943 *
1944 * For erase, `curcontents` and `newcontents` shall be NULL-pointers.
1945 *
1946 * The `chipoff_t` values are used internally by `walk_by_layout()`.
1947 */
1948struct walk_info {
1949 uint8_t *curcontents;
1950 const uint8_t *newcontents;
1951 chipoff_t erase_start;
Daniel Campello9437f712021-04-20 18:49:49 -06001952 chipoff_t erase_end;
Edward O'Callaghan2fc12e22020-12-10 10:32:26 +11001953};
Daniel Campello9437f712021-04-20 18:49:49 -06001954typedef int (*per_blockfn_t)(struct flashctx *, const struct walk_info *, erasefn_t);
Edward O'Callaghan58c3f382020-12-04 16:26:55 +11001955
Edward O'Callaghanecc0b202020-12-10 11:35:11 +11001956/*
1957 * Function to process processing units accumulated in the action descriptor.
1958 *
1959 * @flash pointer to the flash context to operate on
1960 * @per_blockfn helper function which can erase and program a section of the
1961 * flash chip. It receives the flash context, offset and length
1962 * of the area to erase/program, before and after contents (to
1963 * decide what exactly needs to be erased and or programmed)
1964 * and a pointer to the erase function which can operate on the
1965 * proper granularity.
1966 * @descriptor action descriptor including pointers to before and after
1967 * contents and an array of processing actions to take.
1968 *
1969 * Returns zero on success or an error code.
1970 */
1971static int walk_eraseregions(struct flashctx *flash,
1972 const per_blockfn_t per_blockfn,
1973 struct action_descriptor *descriptor)
1974{
1975 struct processing_unit *pu;
1976 int rc = 0;
1977 static int print_comma;
1978
1979 for (pu = descriptor->processing_units; pu->num_blocks; pu++) {
1980 unsigned base = pu->offset;
1981 unsigned top = pu->offset + pu->block_size * pu->num_blocks;
Edward O'Callaghan17361062020-12-12 17:31:59 +11001982 struct block_eraser *const eraser = &flash->chip->block_erasers[pu->block_eraser_index];
Edward O'Callaghanecc0b202020-12-10 11:35:11 +11001983
1984 while (base < top) {
1985
1986 if (print_comma)
1987 msg_cdbg(", ");
1988 else
1989 print_comma = 1;
1990
1991 msg_cdbg("0x%06x-0x%06zx", base, base + pu->block_size - 1);
1992
1993 struct walk_info info = {
Daniel Campello9437f712021-04-20 18:49:49 -06001994 .curcontents = descriptor->oldcontents + base,
1995 .newcontents = descriptor->newcontents + base,
Edward O'Callaghanecc0b202020-12-10 11:35:11 +11001996 .erase_start = base,
Daniel Campello9437f712021-04-20 18:49:49 -06001997 .erase_end = base + pu->block_size - 1,
Edward O'Callaghanecc0b202020-12-10 11:35:11 +11001998 };
Edward O'Callaghan17361062020-12-12 17:31:59 +11001999 rc = per_blockfn(flash, &info, eraser->block_erase);
Edward O'Callaghanecc0b202020-12-10 11:35:11 +11002000
2001 if (rc) {
2002 if (ignore_error(rc))
2003 rc = 0;
2004 else
2005 return rc;
2006 }
2007 base += pu->block_size;
2008 }
2009 }
2010 msg_cdbg("\n");
2011 return rc;
2012}
2013
Daniel Campello9437f712021-04-20 18:49:49 -06002014static int erase_and_write_block_helper(struct flashctx *const flash,
2015 const struct walk_info *const info,
2016 const erasefn_t erasefn)
hailfingerb437e282010-11-04 01:04:27 +00002017{
Daniel Campello9437f712021-04-20 18:49:49 -06002018 const unsigned int erase_len = info->erase_end + 1 - info->erase_start;
stefanctc5eb8a92011-11-23 09:13:48 +00002019 unsigned int starthere = 0, lenhere = 0;
Edward O'Callaghan307d1692020-12-12 00:18:22 +11002020 int ret = 0, writecount = 0;
David Hendricks048b38c2016-03-28 18:47:06 -07002021 int block_was_erased = 0;
Edward O'Callaghan10e63d92019-06-17 14:12:52 +10002022 enum write_granularity gran = flash->chip->gran;
Edward O'Callaghan307d1692020-12-12 00:18:22 +11002023 bool skipped = true;
hailfingerb437e282010-11-04 01:04:27 +00002024 msg_cdbg(":");
Daniel Campello9437f712021-04-20 18:49:49 -06002025 if (need_erase(info->curcontents, info->newcontents, erase_len, gran, 0xff)) {
Daniel Campellofbee2142021-04-20 16:09:09 -06002026 all_skipped = false;
Daisuke Nojiri446b6732018-09-07 18:32:56 -07002027 msg_cdbg(" E");
Daniel Campello9437f712021-04-20 18:49:49 -06002028 ret = erasefn(flash, info->erase_start, erase_len);
David Hendricks1ed1d352011-11-23 17:54:37 -08002029 if (ret) {
Edward O'Callaghan0a92ce22020-12-09 17:10:37 +11002030 if (ret == SPI_ACCESS_DENIED)
Daisuke Nojiri446b6732018-09-07 18:32:56 -07002031 msg_cdbg(" DENIED");
David Hendricks1ed1d352011-11-23 17:54:37 -08002032 else
Daisuke Nojiri446b6732018-09-07 18:32:56 -07002033 msg_cerr(" ERASE_FAILED\n");
hailfingerb437e282010-11-04 01:04:27 +00002034 return ret;
David Hendricks1ed1d352011-11-23 17:54:37 -08002035 }
2036
David Hendricks0954ffc2015-11-13 15:15:44 -08002037 if (programmer_table[programmer].paranoid) {
Daniel Campello9437f712021-04-20 18:49:49 -06002038 if (check_erased_range(flash, info->erase_start, erase_len)) {
Daisuke Nojiri446b6732018-09-07 18:32:56 -07002039 msg_cerr(" ERASE_FAILED\n");
David Hendricks0954ffc2015-11-13 15:15:44 -08002040 return -1;
2041 }
hailfingerac8e3182011-06-26 17:04:16 +00002042 }
David Hendricks0954ffc2015-11-13 15:15:44 -08002043
hailfinger90fcf9b2010-11-05 14:51:59 +00002044 /* Erase was successful. Adjust curcontents. */
Daniel Campello9437f712021-04-20 18:49:49 -06002045 memset(info->curcontents, ERASED_VALUE(flash), erase_len);
Edward O'Callaghan307d1692020-12-12 00:18:22 +11002046 skipped = false;
David Hendricks048b38c2016-03-28 18:47:06 -07002047 block_was_erased = 1;
hailfingerb437e282010-11-04 01:04:27 +00002048 }
hailfinger90fcf9b2010-11-05 14:51:59 +00002049 /* get_next_write() sets starthere to a new value after the call. */
Edward O'Callaghan2fc12e22020-12-10 10:32:26 +11002050 while ((lenhere = get_next_write(info->curcontents + starthere,
2051 info->newcontents + starthere,
Daniel Campello9437f712021-04-20 18:49:49 -06002052 erase_len - starthere, &starthere, gran))) {
Daniel Campellofbee2142021-04-20 16:09:09 -06002053 all_skipped = false;
hailfingerb437e282010-11-04 01:04:27 +00002054 if (!writecount++)
Daisuke Nojiri446b6732018-09-07 18:32:56 -07002055 msg_cdbg(" W");
hailfingerb437e282010-11-04 01:04:27 +00002056 /* Needs the partial write function signature. */
Edward O'Callaghan2fc12e22020-12-10 10:32:26 +11002057 ret = write_flash(flash, (uint8_t *)info->newcontents + starthere,
2058 info->erase_start + starthere, lenhere);
David Hendricks1ed1d352011-11-23 17:54:37 -08002059 if (ret) {
Edward O'Callaghan0a92ce22020-12-09 17:10:37 +11002060 if (ret == SPI_ACCESS_DENIED)
Daisuke Nojiri446b6732018-09-07 18:32:56 -07002061 msg_cdbg(" DENIED");
hailfingerb437e282010-11-04 01:04:27 +00002062 return ret;
David Hendricks1ed1d352011-11-23 17:54:37 -08002063 }
David Hendricks048b38c2016-03-28 18:47:06 -07002064
2065 /*
2066 * If the block needed to be erased and was erased successfully
2067 * then we can assume that we didn't run into any write-
2068 * protected areas. Otherwise, we need to verify each page to
2069 * ensure it was successfully written and abort if we encounter
2070 * any errors.
2071 */
2072 if (programmer_table[programmer].paranoid && !block_was_erased) {
Edward O'Callaghan2fc12e22020-12-10 10:32:26 +11002073 if (verify_range(flash, info->newcontents + starthere,
2074 info->erase_start + starthere, lenhere))
David Hendricks048b38c2016-03-28 18:47:06 -07002075 return -1;
2076 }
2077
hailfingerb437e282010-11-04 01:04:27 +00002078 starthere += lenhere;
Edward O'Callaghan307d1692020-12-12 00:18:22 +11002079 skipped = false;
hailfingerb437e282010-11-04 01:04:27 +00002080 }
Edward O'Callaghan307d1692020-12-12 00:18:22 +11002081 if (skipped)
2082 msg_cdbg("S");
hailfingerb437e282010-11-04 01:04:27 +00002083 return ret;
2084}
2085
Edward O'Callaghanaccf9ff2021-01-22 01:33:03 +11002086static int erase_and_write_flash(struct flashctx *flash,
Daniel Campello2e158342021-04-25 06:54:40 -06002087 void *const curcontents, void *const newcontents)
hailfingerd219a232009-01-28 00:27:54 +00002088{
Vadim Bendebury2b4dcef2018-05-21 10:47:18 -07002089 int ret = 1;
Daniel Campello2e158342021-04-25 06:54:40 -06002090 struct action_descriptor *descriptor =
2091 prepare_action_descriptor(flash, curcontents, newcontents,
2092 !flash->flags.do_not_diff);
hailfingercf848f12010-12-05 15:14:44 +00002093
hailfingercf848f12010-12-05 15:14:44 +00002094 msg_cinfo("Erasing and writing flash chip... ");
hailfingerb437e282010-11-04 01:04:27 +00002095
Vadim Bendebury2b4dcef2018-05-21 10:47:18 -07002096 ret = walk_eraseregions(flash, &erase_and_write_block_helper, descriptor);
hailfinger1e9ee0f2009-05-08 17:15:15 +00002097
hailfinger7df21362009-09-05 02:30:58 +00002098 if (ret) {
snelsone42c3802010-05-07 20:09:04 +00002099 msg_cerr("FAILED!\n");
hailfinger7df21362009-09-05 02:30:58 +00002100 } else {
David Hendricksc6c9f822010-11-03 15:07:01 -07002101 msg_cdbg("SUCCESS.\n");
hailfinger7df21362009-09-05 02:30:58 +00002102 }
Daniel Campello2e158342021-04-25 06:54:40 -06002103
2104 free(descriptor);
hailfinger7df21362009-09-05 02:30:58 +00002105 return ret;
hailfingerd219a232009-01-28 00:27:54 +00002106}
2107
Daniel Campelloef545b12021-04-10 10:39:26 -06002108/**
2109 * @brief Compares the included layout regions with content from a buffer.
2110 *
2111 * If there is no layout set in the given flash context, the whole chip's
2112 * contents will be compared.
2113 *
2114 * @param flashctx Flash context to be used.
2115 * @param curcontents A buffer of full chip size to read current chip contents into.
2116 * @param newcontents The new image to compare to.
2117 * @return 0 on success,
2118 * 1 if reading failed,
2119 * 3 if the contents don't match.
2120 */
2121static int verify_by_layout(struct flashctx *const flashctx,
2122 void *const curcontents, const uint8_t *const newcontents)
2123{
2124 const struct flashrom_layout *const layout = get_layout(flashctx);
2125 const struct romentry *entry = NULL;
Daniel Campello7ad0c472021-04-20 17:10:22 -06002126 int ret = 0;
Daniel Campelloef545b12021-04-10 10:39:26 -06002127
2128 while ((entry = layout_next_included(layout, entry))) {
2129 const chipoff_t region_start = entry->start;
2130 const chipsize_t region_len = entry->end - entry->start + 1;
Daniel Campelloef545b12021-04-10 10:39:26 -06002131
Daniel Campellod27f6592021-05-11 20:14:39 -06002132 if ((ret = verify_range(flashctx, newcontents + region_start,
2133 region_start, region_len)))
Daniel Campello7ad0c472021-04-20 17:10:22 -06002134 break;
Daniel Campelloef545b12021-04-10 10:39:26 -06002135 }
Daniel Campello7ad0c472021-04-20 17:10:22 -06002136
Daniel Campellod27f6592021-05-11 20:14:39 -06002137 if (ret == 3)
2138 return ret;
2139
Daniel Campello7ad0c472021-04-20 17:10:22 -06002140 if (ret) {
2141 msg_gdbg("Could not fully verify due to error, ");
2142 if (ignore_error(ret)) {
2143 msg_gdbg("ignoring\n");
2144 ret = 0;
2145 } else {
2146 msg_gdbg("aborting\n");
2147 ret = 1;
2148 }
2149 }
2150
2151 return ret;
Daniel Campelloef545b12021-04-10 10:39:26 -06002152}
2153
Edward O'Callaghan09fdc022020-09-07 15:51:53 +10002154static void nonfatal_help_message(void)
hailfinger4c47e9d2010-10-19 22:06:20 +00002155{
Edward O'Callaghan09fdc022020-09-07 15:51:53 +10002156 msg_gerr("Good, writing to the flash chip apparently didn't do anything.\n");
2157#if CONFIG_INTERNAL == 1
2158 if (programmer == PROGRAMMER_INTERNAL)
2159 msg_gerr("This means we have to add special support for your board, programmer or flash\n"
2160 "chip. Please report this on IRC at chat.freenode.net (channel #flashrom) or\n"
2161 "mail flashrom@flashrom.org, thanks!\n"
2162 "-------------------------------------------------------------------------------\n"
2163 "You may now reboot or simply leave the machine running.\n");
2164 else
2165#endif
2166 msg_gerr("Please check the connections (especially those to write protection pins) between\n"
2167 "the programmer and the flash chip. If you think the error is caused by flashrom\n"
2168 "please report this on IRC at chat.freenode.net (channel #flashrom) or\n"
2169 "mail flashrom@flashrom.org, thanks!\n");
hailfinger4c47e9d2010-10-19 22:06:20 +00002170}
2171
Edward O'Callaghan09fdc022020-09-07 15:51:53 +10002172static void emergency_help_message(void)
hailfinger0459e1c2009-08-19 13:55:34 +00002173{
Edward O'Callaghan09fdc022020-09-07 15:51:53 +10002174 msg_gerr("Your flash chip is in an unknown state.\n");
2175#if CONFIG_INTERNAL == 1
2176 if (programmer == PROGRAMMER_INTERNAL)
2177 msg_gerr("Get help on IRC at chat.freenode.net (channel #flashrom) or\n"
2178 "mail flashrom@flashrom.org with the subject \"FAILED: <your board name>\"!\n"
2179 "-------------------------------------------------------------------------------\n"
2180 "DO NOT REBOOT OR POWEROFF!\n");
2181 else
2182#endif
2183 msg_gerr("Please report this on IRC at chat.freenode.net (channel #flashrom) or\n"
2184 "mail flashrom@flashrom.org, thanks!\n");
hailfinger0459e1c2009-08-19 13:55:34 +00002185}
2186
hailfingerf79d1712010-10-06 23:48:34 +00002187void list_programmers_linebreak(int startcol, int cols, int paren)
2188{
2189 const char *pname;
hailfingerb91c08c2011-08-15 19:54:20 +00002190 int pnamelen;
2191 int remaining = 0, firstline = 1;
hailfingerf79d1712010-10-06 23:48:34 +00002192 enum programmer p;
hailfingerb91c08c2011-08-15 19:54:20 +00002193 int i;
hailfingerf79d1712010-10-06 23:48:34 +00002194
2195 for (p = 0; p < PROGRAMMER_INVALID; p++) {
2196 pname = programmer_table[p].name;
2197 pnamelen = strlen(pname);
2198 if (remaining - pnamelen - 2 < 0) {
2199 if (firstline)
2200 firstline = 0;
2201 else
Edward O'Callaghan90aaa302019-05-21 14:43:38 +10002202 msg_ginfo("\n");
hailfingerf79d1712010-10-06 23:48:34 +00002203 for (i = 0; i < startcol; i++)
Edward O'Callaghan90aaa302019-05-21 14:43:38 +10002204 msg_ginfo(" ");
hailfingerf79d1712010-10-06 23:48:34 +00002205 remaining = cols - startcol;
2206 } else {
Edward O'Callaghan90aaa302019-05-21 14:43:38 +10002207 msg_ginfo(" ");
hailfingerf79d1712010-10-06 23:48:34 +00002208 remaining--;
2209 }
2210 if (paren && (p == 0)) {
Edward O'Callaghan90aaa302019-05-21 14:43:38 +10002211 msg_ginfo("(");
hailfingerf79d1712010-10-06 23:48:34 +00002212 remaining--;
2213 }
Edward O'Callaghan90aaa302019-05-21 14:43:38 +10002214 msg_ginfo("%s", pname);
hailfingerf79d1712010-10-06 23:48:34 +00002215 remaining -= pnamelen;
2216 if (p < PROGRAMMER_INVALID - 1) {
Edward O'Callaghan90aaa302019-05-21 14:43:38 +10002217 msg_ginfo(",");
hailfingerf79d1712010-10-06 23:48:34 +00002218 remaining--;
2219 } else {
2220 if (paren)
Edward O'Callaghan90aaa302019-05-21 14:43:38 +10002221 msg_ginfo(")");
hailfingerf79d1712010-10-06 23:48:34 +00002222 }
2223 }
2224}
2225
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10002226static void print_sysinfo(void)
hailfinger3b471632010-03-27 16:36:40 +00002227{
Edward O'Callaghandfb1fa32020-09-07 16:00:36 +10002228#if IS_WINDOWS
2229 SYSTEM_INFO si;
2230 OSVERSIONINFOEX osvi;
hailfinger3b471632010-03-27 16:36:40 +00002231
Edward O'Callaghandfb1fa32020-09-07 16:00:36 +10002232 memset(&si, 0, sizeof(SYSTEM_INFO));
2233 memset(&osvi, 0, sizeof(OSVERSIONINFOEX));
2234 msg_ginfo(" on Windows");
2235 /* Tell Windows which version of the structure we want. */
2236 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
2237 if (GetVersionEx((OSVERSIONINFO*) &osvi))
2238 msg_ginfo(" %lu.%lu", osvi.dwMajorVersion, osvi.dwMinorVersion);
2239 else
2240 msg_ginfo(" unknown version");
2241 GetSystemInfo(&si);
2242 switch (si.wProcessorArchitecture) {
2243 case PROCESSOR_ARCHITECTURE_AMD64:
2244 msg_ginfo(" (x86_64)");
2245 break;
2246 case PROCESSOR_ARCHITECTURE_INTEL:
2247 msg_ginfo(" (x86)");
2248 break;
2249 default:
2250 msg_ginfo(" (unknown arch)");
2251 break;
2252 }
2253#elif HAVE_UTSNAME == 1
2254 struct utsname osinfo;
2255
2256 uname(&osinfo);
2257 msg_ginfo(" on %s %s (%s)", osinfo.sysname, osinfo.release,
hailfinger3b471632010-03-27 16:36:40 +00002258 osinfo.machine);
2259#else
Edward O'Callaghandfb1fa32020-09-07 16:00:36 +10002260 msg_ginfo(" on unknown machine");
hailfinger3b471632010-03-27 16:36:40 +00002261#endif
Souvik Ghosh3c963a42016-07-19 18:48:15 -07002262}
2263
2264void print_buildinfo(void)
2265{
2266 msg_gdbg("flashrom was built with");
hailfinger3b471632010-03-27 16:36:40 +00002267#if NEED_PCI == 1
2268#ifdef PCILIB_VERSION
Souvik Ghosh3c963a42016-07-19 18:48:15 -07002269 msg_gdbg(" libpci %s,", PCILIB_VERSION);
hailfinger3b471632010-03-27 16:36:40 +00002270#else
Souvik Ghosh3c963a42016-07-19 18:48:15 -07002271 msg_gdbg(" unknown PCI library,");
hailfinger3b471632010-03-27 16:36:40 +00002272#endif
2273#endif
2274#ifdef __clang__
Souvik Ghosh3c963a42016-07-19 18:48:15 -07002275 msg_gdbg(" LLVM Clang");
hailfinger3cc85ad2010-07-17 14:49:30 +00002276#ifdef __clang_version__
Souvik Ghosh3c963a42016-07-19 18:48:15 -07002277 msg_gdbg(" %s,", __clang_version__);
hailfinger3cc85ad2010-07-17 14:49:30 +00002278#else
Souvik Ghosh3c963a42016-07-19 18:48:15 -07002279 msg_gdbg(" unknown version (before r102686),");
hailfinger3cc85ad2010-07-17 14:49:30 +00002280#endif
hailfinger3b471632010-03-27 16:36:40 +00002281#elif defined(__GNUC__)
Souvik Ghosh3c963a42016-07-19 18:48:15 -07002282 msg_gdbg(" GCC");
hailfinger3b471632010-03-27 16:36:40 +00002283#ifdef __VERSION__
Souvik Ghosh3c963a42016-07-19 18:48:15 -07002284 msg_gdbg(" %s,", __VERSION__);
hailfinger3b471632010-03-27 16:36:40 +00002285#else
Souvik Ghosh3c963a42016-07-19 18:48:15 -07002286 msg_gdbg(" unknown version,");
hailfinger3b471632010-03-27 16:36:40 +00002287#endif
2288#else
Souvik Ghosh3c963a42016-07-19 18:48:15 -07002289 msg_gdbg(" unknown compiler,");
hailfinger324a9cc2010-05-26 01:45:41 +00002290#endif
2291#if defined (__FLASHROM_LITTLE_ENDIAN__)
Souvik Ghosh3c963a42016-07-19 18:48:15 -07002292 msg_gdbg(" little endian");
Edward O'Callaghan3c005942020-10-01 16:33:47 +10002293#elif defined (__FLASHROM_BIG_ENDIAN__)
Souvik Ghosh3c963a42016-07-19 18:48:15 -07002294 msg_gdbg(" big endian");
Edward O'Callaghan3c005942020-10-01 16:33:47 +10002295#else
2296#error Endianness could not be determined
hailfinger3b471632010-03-27 16:36:40 +00002297#endif
Souvik Ghosh3c963a42016-07-19 18:48:15 -07002298 msg_gdbg("\n");
hailfinger3b471632010-03-27 16:36:40 +00002299}
2300
uwefdeca092008-01-21 15:24:22 +00002301void print_version(void)
2302{
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10002303 msg_ginfo("flashrom %s", flashrom_version);
hailfinger3b471632010-03-27 16:36:40 +00002304 print_sysinfo();
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10002305 msg_ginfo("\n");
uwefdeca092008-01-21 15:24:22 +00002306}
2307
hailfinger74819ad2010-05-15 15:04:37 +00002308void print_banner(void)
2309{
2310 msg_ginfo("flashrom is free software, get the source code at "
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10002311 "https://flashrom.org\n");
hailfinger74819ad2010-05-15 15:04:37 +00002312 msg_ginfo("\n");
2313}
2314
hailfingerc77acb52009-12-24 02:15:55 +00002315int selfcheck(void)
2316{
Edward O'Callaghan6240c852019-07-02 15:49:58 +10002317 unsigned int i;
hailfinger45177872010-01-18 08:14:43 +00002318 int ret = 0;
hailfinger45177872010-01-18 08:14:43 +00002319
2320 /* Safety check. Instead of aborting after the first error, check
2321 * if more errors exist.
2322 */
hailfingerc77acb52009-12-24 02:15:55 +00002323 if (ARRAY_SIZE(programmer_table) - 1 != PROGRAMMER_INVALID) {
snelsone42c3802010-05-07 20:09:04 +00002324 msg_gerr("Programmer table miscompilation!\n");
hailfinger45177872010-01-18 08:14:43 +00002325 ret = 1;
hailfingerc77acb52009-12-24 02:15:55 +00002326 }
Edward O'Callaghanac1678b2020-07-27 15:55:45 +10002327 for (i = 0; i < PROGRAMMER_INVALID; i++) {
2328 const struct programmer_entry p = programmer_table[i];
2329 if (p.name == NULL) {
2330 msg_gerr("All programmers need a valid name, but the one with index %d does not!\n", i);
2331 ret = 1;
2332 /* This might hide other problems with this programmer, but allows for better error
2333 * messages below without jumping through hoops. */
2334 continue;
2335 }
2336 switch (p.type) {
2337 case USB:
2338 case PCI:
2339 case OTHER:
2340 if (p.devs.note == NULL) {
2341 if (strcmp("internal", p.name) == 0)
2342 break; /* This one has its device list stored separately. */
2343 msg_gerr("Programmer %s has neither a device list nor a textual description!\n",
2344 p.name);
2345 ret = 1;
2346 }
2347 break;
2348 default:
2349 msg_gerr("Programmer %s does not have a valid type set!\n", p.name);
2350 ret = 1;
2351 break;
2352 }
2353 if (p.init == NULL) {
2354 msg_gerr("Programmer %s does not have a valid init function!\n", p.name);
2355 ret = 1;
2356 }
2357 if (p.delay == NULL) {
2358 msg_gerr("Programmer %s does not have a valid delay function!\n", p.name);
2359 ret = 1;
2360 }
2361 if (p.map_flash_region == NULL) {
2362 msg_gerr("Programmer %s does not have a valid map_flash_region function!\n", p.name);
2363 ret = 1;
2364 }
2365 if (p.unmap_flash_region == NULL) {
2366 msg_gerr("Programmer %s does not have a valid unmap_flash_region function!\n", p.name);
2367 ret = 1;
2368 }
2369 }
2370
Edward O'Callaghan6240c852019-07-02 15:49:58 +10002371 /* It would be favorable if we could check for the correct layout (especially termination) of various
2372 * constant arrays: flashchips, chipset_enables, board_matches, boards_known, laptops_known.
2373 * They are all defined as externs in this compilation unit so we don't know their sizes which vary
2374 * depending on compiler flags, e.g. the target architecture, and can sometimes be 0.
2375 * For 'flashchips' we export the size explicitly to work around this and to be able to implement the
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10002376 * checks below. */
2377 if (flashchips_size <= 1 || flashchips[flashchips_size - 1].name != NULL) {
stefanct6d836ba2011-05-26 01:35:19 +00002378 msg_gerr("Flashchips table miscompilation!\n");
2379 ret = 1;
Edward O'Callaghan6240c852019-07-02 15:49:58 +10002380 } else {
2381 for (i = 0; i < flashchips_size - 1; i++) {
2382 const struct flashchip *chip = &flashchips[i];
2383 if (chip->vendor == NULL || chip->name == NULL || chip->bustype == BUS_NONE) {
2384 ret = 1;
2385 msg_gerr("ERROR: Some field of flash chip #%d (%s) is misconfigured.\n"
2386 "Please report a bug at flashrom@flashrom.org\n", i,
2387 chip->name == NULL ? "unnamed" : chip->name);
2388 }
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10002389 if (selfcheck_eraseblocks(chip)) {
Edward O'Callaghan6240c852019-07-02 15:49:58 +10002390 ret = 1;
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10002391 }
Edward O'Callaghan6240c852019-07-02 15:49:58 +10002392 }
stefanct6d836ba2011-05-26 01:35:19 +00002393 }
stefanct6d836ba2011-05-26 01:35:19 +00002394
Edward O'Callaghane6b85692020-12-18 11:01:55 +11002395#if CONFIG_INTERNAL == 1
2396 ret |= selfcheck_board_enables();
2397#endif
2398
Edward O'Callaghanb2257cc2020-07-25 22:19:47 +10002399 /* TODO: implement similar sanity checks for other arrays where deemed necessary. */
hailfinger45177872010-01-18 08:14:43 +00002400 return ret;
hailfingerc77acb52009-12-24 02:15:55 +00002401}
2402
Edward O'Callaghan2c8ec612021-04-15 13:44:39 +10002403/* FIXME: This function signature needs to be improved once prepare_flash_access()
2404 * has a better function signature.
hailfinger771fc182010-10-15 00:01:14 +00002405 */
Edward O'Callaghan0c310fe2020-08-10 17:02:23 +10002406static int chip_safety_check(const struct flashctx *flash, int force,
2407 int read_it, int write_it, int erase_it, int verify_it)
hailfinger771fc182010-10-15 00:01:14 +00002408{
Patrick Georgiac3423f2017-02-03 20:58:06 +01002409 const struct flashchip *chip = flash->chip;
2410
hailfinger771fc182010-10-15 00:01:14 +00002411 if (!programmer_may_write && (write_it || erase_it)) {
2412 msg_perr("Write/erase is not working yet on your programmer in "
2413 "its current configuration.\n");
2414 /* --force is the wrong approach, but it's the best we can do
2415 * until the generic programmer parameter parser is merged.
2416 */
2417 if (!force)
2418 return 1;
2419 msg_cerr("Continuing anyway.\n");
2420 }
2421
2422 if (read_it || erase_it || write_it || verify_it) {
2423 /* Everything needs read. */
Patrick Georgiac3423f2017-02-03 20:58:06 +01002424 if (chip->tested.read == BAD) {
hailfinger771fc182010-10-15 00:01:14 +00002425 msg_cerr("Read is not working on this chip. ");
2426 if (!force)
2427 return 1;
2428 msg_cerr("Continuing anyway.\n");
2429 }
Patrick Georgiac3423f2017-02-03 20:58:06 +01002430 if (!chip->read) {
hailfinger771fc182010-10-15 00:01:14 +00002431 msg_cerr("flashrom has no read function for this "
2432 "flash chip.\n");
2433 return 1;
2434 }
2435 }
2436 if (erase_it || write_it) {
2437 /* Write needs erase. */
Patrick Georgiac3423f2017-02-03 20:58:06 +01002438 if (chip->tested.erase == NA) {
2439 msg_cerr("Erase is not possible on this chip.\n");
2440 return 1;
2441 }
2442 if (chip->tested.erase == BAD) {
hailfinger771fc182010-10-15 00:01:14 +00002443 msg_cerr("Erase is not working on this chip. ");
2444 if (!force)
2445 return 1;
2446 msg_cerr("Continuing anyway.\n");
2447 }
stefancte1c5acf2011-07-04 07:27:17 +00002448 if(count_usable_erasers(flash) == 0) {
stefanct569dbb62011-07-01 00:19:12 +00002449 msg_cerr("flashrom has no erase function for this "
2450 "flash chip.\n");
2451 return 1;
2452 }
hailfinger771fc182010-10-15 00:01:14 +00002453 }
2454 if (write_it) {
Patrick Georgiac3423f2017-02-03 20:58:06 +01002455 if (chip->tested.write == NA) {
2456 msg_cerr("Write is not possible on this chip.\n");
2457 return 1;
2458 }
2459 if (chip->tested.write == BAD) {
hailfinger771fc182010-10-15 00:01:14 +00002460 msg_cerr("Write is not working on this chip. ");
2461 if (!force)
2462 return 1;
2463 msg_cerr("Continuing anyway.\n");
2464 }
Patrick Georgiac3423f2017-02-03 20:58:06 +01002465 if (!chip->write) {
hailfinger771fc182010-10-15 00:01:14 +00002466 msg_cerr("flashrom has no write function for this "
2467 "flash chip.\n");
2468 return 1;
2469 }
2470 }
2471 return 0;
2472}
2473
Edward O'Callaghana0176ff2020-08-18 15:49:23 +10002474int prepare_flash_access(struct flashctx *const flash,
Edward O'Callaghan27362b42020-08-10 17:58:03 +10002475 const bool read_it, const bool write_it,
2476 const bool erase_it, const bool verify_it)
2477{
Edward O'Callaghan2c679272020-09-23 22:41:01 +10002478 if (chip_safety_check(flash, flash->flags.force, read_it, write_it, erase_it, verify_it)) {
Edward O'Callaghan27362b42020-08-10 17:58:03 +10002479 msg_cerr("Aborting.\n");
2480 return 1;
2481 }
2482
Daniel Campellodf477722021-04-05 16:53:33 -06002483 if (flash->layout == get_global_layout() && normalize_romentries(flash)) {
Edward O'Callaghan27362b42020-08-10 17:58:03 +10002484 msg_cerr("Requested regions can not be handled. Aborting.\n");
2485 return 1;
2486 }
2487
Edward O'Callaghan40092972020-10-20 11:50:48 +11002488 /*
2489 * FIXME(b/171093672): Failures to map_flash() on some DUT's due to unknown cause,
2490 * can be repro'ed with upstream on Volteer.
2491 *
2492 * map_flash() can fail on opaque spi drv such as linux_mtd and even ichspi.
2493 * The issue is that 'internal' [alias 'host'] has the cb 'map_flash_region = physmap'
2494 * hooked and this can fail on some board topologies. Checking the return value can
2495 * cause board rw failures by bailing early. Avoid the early bail for now until a
2496 * full investigation can reveal the proper fix. This restores previous behaviour of
2497 * assuming a map went fine.
2498 */
2499#if 0
Edward O'Callaghan12d8f832020-10-13 13:45:31 +11002500 if (map_flash(flash) != 0)
2501 return 1;
Edward O'Callaghan40092972020-10-20 11:50:48 +11002502#endif
2503 map_flash(flash);
Edward O'Callaghan12d8f832020-10-13 13:45:31 +11002504
Edward O'Callaghan27362b42020-08-10 17:58:03 +10002505 /* Given the existence of read locks, we want to unlock for read,
2506 erase and write. */
2507 if (flash->chip->unlock)
2508 flash->chip->unlock(flash);
2509
2510 flash->address_high_byte = -1;
2511 flash->in_4ba_mode = false;
Nikolai Artemiev55f7a332020-11-05 13:54:27 +11002512 flash->chip_restore_fn_count = 0;
Edward O'Callaghan27362b42020-08-10 17:58:03 +10002513
Edward O'Callaghan99974452020-10-13 13:28:33 +11002514 /* Be careful about 4BA chips and broken masters */
2515 if (flash->chip->total_size > 16 * 1024 && spi_master_no_4ba_modes(flash)) {
2516 /* If we can't use native instructions, bail out */
2517 if ((flash->chip->feature_bits & FEATURE_4BA_NATIVE) != FEATURE_4BA_NATIVE
2518 || !spi_master_4ba(flash)) {
2519 msg_cerr("Programmer doesn't support this chip. Aborting.\n");
2520 return 1;
2521 }
2522 }
2523
Edward O'Callaghanecb10662020-11-11 20:23:44 +11002524 /* Enable/disable 4-byte addressing mode if flash chip supports it */
2525 if ((flash->chip->bustype == BUS_SPI) &&
2526 (flash->chip->feature_bits & (FEATURE_4BA_ENTER | FEATURE_4BA_ENTER_WREN | FEATURE_4BA_ENTER_EAR7))) {
2527 int ret;
2528 if (spi_master_4ba(flash))
2529 ret = spi_enter_4ba(flash);
2530 else
2531 ret = spi_exit_4ba(flash);
2532 if (ret) {
2533 msg_cerr("Failed to set correct 4BA mode! Aborting.\n");
2534 return 1;
2535 }
2536 }
2537
Edward O'Callaghan27362b42020-08-10 17:58:03 +10002538 return 0;
2539}
2540
Edward O'Callaghana820b212020-09-17 22:53:26 +10002541void finalize_flash_access(struct flashctx *const flash)
2542{
Nikolai Artemiev55f7a332020-11-05 13:54:27 +11002543 deregister_chip_restore(flash);
Edward O'Callaghana820b212020-09-17 22:53:26 +10002544 unmap_flash(flash);
2545}
2546
Daniel Campello3171d742021-04-21 06:32:06 -06002547static int setup_curcontents(struct flashctx *flashctx, void *curcontents,
Daniel Campelloee45dc12021-04-10 10:13:51 -06002548 int erase_it, const void *const refcontents)
Daniel Campello98eed1a2021-03-22 07:28:34 -06002549{
Daniel Campelloee45dc12021-04-10 10:13:51 -06002550 const size_t flash_size = flashctx->chip->total_size * 1024;
Daniel Campello6b0f1fc2021-04-09 21:28:12 -06002551 const bool verify_all = flashctx->flags.verify_whole_chip;
Daniel Campello98eed1a2021-03-22 07:28:34 -06002552
Daniel Campello3171d742021-04-21 06:32:06 -06002553 memset(curcontents, UNERASED_VALUE(flashctx), flash_size);
Daniel Campelloee45dc12021-04-10 10:13:51 -06002554 if (!flashctx->flags.do_not_diff) {
Daniel Campello65bfe2c2021-04-23 08:57:47 -06002555 /* If given, assume flash chip contains same data as `refcontents`. */
Daniel Campelloee45dc12021-04-10 10:13:51 -06002556 if (refcontents) {
2557 msg_cinfo("Assuming old flash chip contents as ref-file...\n");
Daniel Campello3171d742021-04-21 06:32:06 -06002558 memcpy(curcontents, refcontents, flash_size);
Daniel Campello98eed1a2021-03-22 07:28:34 -06002559 } else {
Daniel Campello65bfe2c2021-04-23 08:57:47 -06002560 /*
2561 * Read the whole chip to be able to check whether regions need to be
2562 * erased and to give better diagnostics in case write fails.
2563 * The alternative is to read only the regions which are to be
2564 * preserved, but in that case we might perform unneeded erase which
2565 * takes time as well.
2566 */
Daniel Campelloee45dc12021-04-10 10:13:51 -06002567 msg_cinfo("Reading old flash chip contents... ");
Daniel Campello65bfe2c2021-04-23 08:57:47 -06002568 if (verify_all) {
Daniel Campello3171d742021-04-21 06:32:06 -06002569 if (read_flash(flashctx, curcontents, 0, flash_size)) {
Daniel Campello6b0f1fc2021-04-09 21:28:12 -06002570 msg_cinfo("FAILED.\n");
2571 return 1;
2572 }
2573 } else {
Daniel Campello731d8932021-04-21 13:02:22 -06002574 /* WARNING: See FIXME on get_required_erase_size() */
2575 if (read_by_layout(flashctx, curcontents, true)) {
Daniel Campello6b0f1fc2021-04-09 21:28:12 -06002576 msg_cinfo("FAILED.\n");
2577 return 1;
2578 }
Daniel Campello98eed1a2021-03-22 07:28:34 -06002579 }
Daniel Campelloee45dc12021-04-10 10:13:51 -06002580 msg_cinfo("done.\n");
Daniel Campello98eed1a2021-03-22 07:28:34 -06002581 }
Daniel Campello98eed1a2021-03-22 07:28:34 -06002582 } else if (!erase_it) {
2583 msg_pinfo("No diff performed, considering the chip erased.\n");
Daniel Campello3171d742021-04-21 06:32:06 -06002584 memset(curcontents, ERASED_VALUE(flashctx), flash_size);
Daniel Campello98eed1a2021-03-22 07:28:34 -06002585 }
Daniel Campelloee45dc12021-04-10 10:13:51 -06002586 return 0;
Daniel Campello98eed1a2021-03-22 07:28:34 -06002587}
2588
Edward O'Callaghanf1436012020-12-07 17:58:23 +11002589/**
2590 * @addtogroup flashrom-flash
2591 * @{
Vadim Bendebury2b4dcef2018-05-21 10:47:18 -07002592 */
Edward O'Callaghanf1436012020-12-07 17:58:23 +11002593
Daniel Campellocb88c9a2021-04-13 19:23:47 -06002594static void combine_image_by_layout(const struct flashctx *const flashctx,
2595 uint8_t *const newcontents, const uint8_t *const oldcontents);
Edward O'Callaghanf1436012020-12-07 17:58:23 +11002596/**
2597 * @brief Erase the specified ROM chip.
2598 *
2599 * If a layout is set in the given flash context, only included regions
2600 * will be erased.
2601 *
2602 * @param flashctx The context of the flash chip to erase.
2603 * @return 0 on success.
2604 */
Daniel Campello26765322021-03-22 14:53:27 -06002605int flashrom_flash_erase(struct flashctx *const flashctx)
Vadim Bendebury2b4dcef2018-05-21 10:47:18 -07002606{
Daniel Campello26765322021-03-22 14:53:27 -06002607 const size_t flash_size = flashctx->chip->total_size * 1024;
Vadim Bendebury2b4dcef2018-05-21 10:47:18 -07002608
Daniel Campello26765322021-03-22 14:53:27 -06002609 int ret = 1;
2610
Daniel Campello3171d742021-04-21 06:32:06 -06002611 uint8_t *curcontents = malloc(flash_size);
Daniel Campello26765322021-03-22 14:53:27 -06002612 uint8_t *newcontents = malloc(flash_size);
Daniel Campello3171d742021-04-21 06:32:06 -06002613 if (!curcontents || !newcontents) {
Daniel Campello26765322021-03-22 14:53:27 -06002614 msg_gerr("Out of memory!\n");
2615 goto _free_ret;
Vadim Bendebury2b4dcef2018-05-21 10:47:18 -07002616 }
2617
Daniel Campello26765322021-03-22 14:53:27 -06002618 if (prepare_flash_access(flashctx, false, false, true, false))
2619 goto _free_ret;
Vadim Bendebury2b4dcef2018-05-21 10:47:18 -07002620
Daniel Campello3171d742021-04-21 06:32:06 -06002621 if (setup_curcontents(flashctx, curcontents, true, NULL))
Daniel Campelloee45dc12021-04-10 10:13:51 -06002622 goto _finalize_ret;
2623
2624 memset(newcontents, ERASED_VALUE(flashctx), flash_size);
Daniel Campello3171d742021-04-21 06:32:06 -06002625 combine_image_by_layout(flashctx, newcontents, curcontents);
Daniel Campello26765322021-03-22 14:53:27 -06002626
Daniel Campello2e158342021-04-25 06:54:40 -06002627 ret = erase_and_write_flash(flashctx, curcontents, newcontents);
Daniel Campello26765322021-03-22 14:53:27 -06002628
2629_finalize_ret:
2630 finalize_flash_access(flashctx);
2631_free_ret:
Daniel Campello3171d742021-04-21 06:32:06 -06002632 free(curcontents);
Daniel Campello26765322021-03-22 14:53:27 -06002633 free(newcontents);
Vadim Bendebury2b4dcef2018-05-21 10:47:18 -07002634 return ret;
2635}
2636
Edward O'Callaghanf1436012020-12-07 17:58:23 +11002637/** @} */ /* end flashrom-flash */
2638
Edward O'Callaghan8c2a3402020-12-09 12:23:01 +11002639/**
2640 * @defgroup flashrom-ops Operations
2641 * @{
2642 */
2643
Edward O'Callaghan84c89182020-12-09 12:33:37 +11002644/**
2645 * @brief Read the current image from the specified ROM chip.
2646 *
2647 * If a layout is set in the specified flash context, only included regions
2648 * will be read.
2649 *
2650 * @param flashctx The context of the flash chip.
2651 * @param buffer Target buffer to write image to.
2652 * @param buffer_len Size of target buffer in bytes.
2653 * @return 0 on success,
2654 * 2 if buffer_len is too short for the flash chip's contents,
2655 * or 1 on any other failure.
2656 */
Daniel Campello6b0f1fc2021-04-09 21:28:12 -06002657int flashrom_image_read(struct flashctx *const flashctx, void *const buffer, const size_t buffer_len)
Daisuke Nojiri6d2cb212018-09-07 19:02:02 -07002658{
Daniel Campello039cd2b2021-03-24 20:12:15 -06002659 const size_t flash_size = flashctx->chip->total_size * 1024;
2660
2661 if (flash_size > buffer_len)
2662 return 2;
2663
2664 if (prepare_flash_access(flashctx, true, false, false, false))
2665 return 1;
2666
2667 msg_cinfo("Reading flash... ");
2668
2669 int ret = 1;
Daniel Campello731d8932021-04-21 13:02:22 -06002670 if (read_by_layout(flashctx, buffer, false)) {
Daniel Campello039cd2b2021-03-24 20:12:15 -06002671 msg_cerr("Read operation failed!\n");
2672 msg_cinfo("FAILED.\n");
2673 goto _finalize_ret;
2674 }
2675 msg_cinfo("done.\n");
2676 ret = 0;
2677
2678_finalize_ret:
2679 finalize_flash_access(flashctx);
2680 return ret;
Daisuke Nojiri6d2cb212018-09-07 19:02:02 -07002681}
2682
Daniel Campellocb88c9a2021-04-13 19:23:47 -06002683static void combine_image_by_layout(const struct flashctx *const flashctx,
2684 uint8_t *const newcontents, const uint8_t *const oldcontents)
2685{
2686 const struct flashrom_layout *const layout = get_layout(flashctx);
2687 const struct romentry *included;
2688 chipoff_t start = 0;
2689
2690 while ((included = layout_next_included_region(layout, start))) {
2691 if (included->start > start) {
2692 /* copy everything up to the start of this included region */
2693 memcpy(newcontents + start, oldcontents + start, included->start - start);
2694 }
2695 /* skip this included region */
2696 start = included->end + 1;
2697 if (start == 0)
2698 return;
2699 }
2700
2701 /* copy the rest of the chip */
2702 const chipsize_t copy_len = flashctx->chip->total_size * 1024 - start;
2703 memcpy(newcontents + start, oldcontents + start, copy_len);
2704}
2705
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002706/**
2707 * @brief Write the specified image to the ROM chip.
Edward O'Callaghan020dfa12020-09-23 23:12:55 +10002708 *
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002709 * If a layout is set in the specified flash context, only erase blocks
2710 * containing included regions will be touched.
Edward O'Callaghan020dfa12020-09-23 23:12:55 +10002711 *
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002712 * @param flashctx The context of the flash chip.
2713 * @param buffer Source buffer to read image from (may be altered for full verification).
2714 * @param buffer_len Size of source buffer in bytes.
2715 * @param refbuffer If given, assume flash chip contains same data as `refbuffer`.
2716 * @return 0 on success,
2717 * 4 if buffer_len doesn't match the size of the flash chip,
Daniel Campello7ad0c472021-04-20 17:10:22 -06002718 * 3 if write was tried but nothing has changed,
Daniel Campello1663cc82021-04-20 19:10:03 -06002719 * 2 if write failed and flash contents changed,
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002720 * or 1 on any other failure.
hailfingerc77acb52009-12-24 02:15:55 +00002721 */
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002722int flashrom_image_write(struct flashctx *const flashctx, void *const buffer, const size_t buffer_len,
Daniel Campellofbee2142021-04-20 16:09:09 -06002723 const void *const refbuffer)
hailfingerc77acb52009-12-24 02:15:55 +00002724{
Daniel Campello57eb4882021-03-25 08:45:10 -06002725 const size_t flash_size = flashctx->chip->total_size * 1024;
Daniel Campello57eb4882021-03-25 08:45:10 -06002726 const bool verify_all = flashctx->flags.verify_whole_chip;
2727 const bool verify = flashctx->flags.verify_after_write;
Edward O'Callaghan4eb85102020-12-18 13:17:08 +11002728
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002729 if (buffer_len != flash_size)
2730 return 4;
2731
2732 int ret = 1;
Daniel Campello1663cc82021-04-20 19:10:03 -06002733 int tmp = 0;
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002734
Daniel Campello3171d742021-04-21 06:32:06 -06002735 uint8_t *curcontents = malloc(flash_size);
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002736 uint8_t *newcontents = malloc(flash_size);
Daniel Campello592296d2021-04-22 12:24:45 -06002737 uint8_t *oldcontents = NULL;
2738 if (verify_all)
2739 oldcontents = malloc(flash_size);
2740 if (!curcontents || !newcontents || (verify_all && !oldcontents)) {
stefanctd611e8f2011-07-12 22:35:21 +00002741 msg_gerr("Out of memory!\n");
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002742 goto _free_ret;
stefanctd611e8f2011-07-12 22:35:21 +00002743 }
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002744
Edward O'Callaghanb902dd02021-04-23 13:33:25 +10002745#if CONFIG_INTERNAL == 1
2746 if (programmer == PROGRAMMER_INTERNAL && cb_check_image(newcontents, flash_size) < 0) {
2747 if (flashctx->flags.force_boardmismatch) {
2748 msg_pinfo("Proceeding anyway because user forced us to.\n");
2749 } else {
2750 msg_perr("Aborting. You can override this with "
2751 "-p internal:boardmismatch=force.\n");
2752 goto _free_ret;
2753 }
2754 }
2755#endif
2756
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002757 if (prepare_flash_access(flashctx, false, true, false, verify))
2758 goto _free_ret;
hailfingerb437e282010-11-04 01:04:27 +00002759
Daniel Campello3171d742021-04-21 06:32:06 -06002760 if (setup_curcontents(flashctx, curcontents, false, refbuffer))
Daniel Campelloee45dc12021-04-10 10:13:51 -06002761 goto _finalize_ret;
Daniel Campello592296d2021-04-22 12:24:45 -06002762 if (oldcontents)
2763 memcpy(oldcontents, curcontents, flash_size);
Daniel Campelloee45dc12021-04-10 10:13:51 -06002764
Daniel Campellocb88c9a2021-04-13 19:23:47 -06002765 memcpy(newcontents, buffer, flash_size);
Daniel Campello3171d742021-04-21 06:32:06 -06002766 combine_image_by_layout(flashctx, newcontents, curcontents);
uwef6641642007-05-09 10:17:44 +00002767
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002768 // parse the new fmap and disable soft WP if necessary
Daniel Campello1663cc82021-04-20 19:10:03 -06002769 if ((tmp = cros_ec_prepare(newcontents, flash_size))) {
2770 msg_cerr("CROS_EC prepare failed, ret=%d.\n", tmp);
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002771 goto _finalize_ret;
2772 }
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +08002773
Daniel Campello2e158342021-04-25 06:54:40 -06002774 if (erase_and_write_flash(flashctx, curcontents, newcontents)) {
Daniel Campello1663cc82021-04-20 19:10:03 -06002775 msg_cerr("Uh oh. Erase/write failed. ");
2776 ret = 2;
2777 if (verify_all) {
2778 msg_cerr("Checking if anything has changed.\n");
2779 msg_cinfo("Reading current flash chip contents... ");
Daniel Campello592296d2021-04-22 12:24:45 -06002780 if (!read_flash(flashctx, curcontents, 0, flash_size)) {
Daniel Campello1663cc82021-04-20 19:10:03 -06002781 msg_cinfo("done.\n");
Daniel Campello592296d2021-04-22 12:24:45 -06002782 if (!memcmp(oldcontents, curcontents, flash_size)) {
Daniel Campello1663cc82021-04-20 19:10:03 -06002783 nonfatal_help_message();
2784 goto _finalize_ret;
2785 }
2786 msg_cerr("Apparently at least some data has changed.\n");
2787 } else
2788 msg_cerr("Can't even read anymore!\n");
2789 } else {
2790 msg_cerr("\n");
2791 }
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002792 emergency_help_message();
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002793 goto _finalize_ret;
2794 }
2795
Daniel Campello1663cc82021-04-20 19:10:03 -06002796 tmp = cros_ec_need_2nd_pass();
2797 if (tmp < 0) {
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002798 // Jump failed
2799 msg_cerr("cros_ec_need_2nd_pass() failed. Stop.\n");
2800 emergency_help_message();
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002801 goto _finalize_ret;
Daniel Campello1663cc82021-04-20 19:10:03 -06002802 } else if (tmp > 0) {
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002803 // Need 2nd pass. Get the just written content.
2804 msg_pdbg("CROS_EC needs 2nd pass.\n");
Daniel Campello3171d742021-04-21 06:32:06 -06002805 if (setup_curcontents(flashctx, curcontents, false, NULL)) {
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002806 emergency_help_message();
2807 goto _finalize_ret;
Louis Yung-Chieh Lo8d0971e2012-03-23 00:07:38 +08002808 }
Louis Yung-Chieh Lodeefd822012-07-09 17:07:43 +08002809
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002810 // write 2nd pass
Daniel Campello2e158342021-04-25 06:54:40 -06002811 if (erase_and_write_flash(flashctx, curcontents, newcontents)) {
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002812 msg_cerr("Uh oh. CROS_EC 2nd pass failed.\n");
Daniel Campello1663cc82021-04-20 19:10:03 -06002813 ret = 2;
Louis Yung-Chieh Lodeefd822012-07-09 17:07:43 +08002814 emergency_help_message();
Daniel Campello57eb4882021-03-25 08:45:10 -06002815 goto _finalize_ret;
Louis Yung-Chieh Lodeefd822012-07-09 17:07:43 +08002816 }
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002817 }
2818
2819 if (cros_ec_finish() < 0) {
2820 msg_cerr("cros_ec_finish() failed. Stop.\n");
2821 emergency_help_message();
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002822 goto _finalize_ret;
stuge8ce3a3c2008-04-28 14:47:30 +00002823 }
ollie6a600992005-11-26 21:55:36 +00002824
Daniel Campellocd387fd2021-04-20 17:54:35 -06002825 /* Verify only if we actually changed something. */
Daniel Campellofbee2142021-04-20 16:09:09 -06002826 if (verify && !all_skipped) {
Daniel Campello7ad0c472021-04-20 17:10:22 -06002827 const struct flashrom_layout *const layout_bak = flashctx->layout;
2828
Daniel Campellocd387fd2021-04-20 17:54:35 -06002829 msg_cinfo("Verifying flash... ");
Louis Yung-Chieh Lo5d95f042011-09-01 17:33:06 +08002830
Daniel Campellocd387fd2021-04-20 17:54:35 -06002831 /* Work around chips which need some time to calm down. */
2832 programmer_delay(1000*1000);
Louis Yung-Chieh Lo5d95f042011-09-01 17:33:06 +08002833
Daniel Campello7ad0c472021-04-20 17:10:22 -06002834 if (verify_all) {
2835 flashctx->layout = NULL;
2836 }
Daniel Campello3171d742021-04-21 06:32:06 -06002837 ret = verify_by_layout(flashctx, curcontents, newcontents);
Daniel Campello7ad0c472021-04-20 17:10:22 -06002838 flashctx->layout = layout_bak;
Daniel Campellocd387fd2021-04-20 17:54:35 -06002839 /* If we tried to write, and verification now fails, we
2840 might have an emergency situation. */
2841 if (ret)
2842 emergency_help_message();
2843 else
2844 msg_cinfo("VERIFIED.\n");
Daniel Campello1663cc82021-04-20 19:10:03 -06002845 } else {
2846 ret = 0;
hailfinger0459e1c2009-08-19 13:55:34 +00002847 }
ollie6a600992005-11-26 21:55:36 +00002848
Daniel Campello57eb4882021-03-25 08:45:10 -06002849_finalize_ret:
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002850 finalize_flash_access(flashctx);
2851_free_ret:
Daniel Campello592296d2021-04-22 12:24:45 -06002852 free(oldcontents);
Daniel Campello3171d742021-04-21 06:32:06 -06002853 free(curcontents);
hailfinger90fcf9b2010-11-05 14:51:59 +00002854 free(newcontents);
stepan83eca252006-01-04 16:42:57 +00002855 return ret;
rminnich8d3ff912003-10-25 17:01:29 +00002856}
Edward O'Callaghan020dfa12020-09-23 23:12:55 +10002857
Daniel Campellof758a8b2021-03-22 14:47:13 -06002858/**
2859 * @brief Verify the ROM chip's contents with the specified image.
2860 *
2861 * If a layout is set in the specified flash context, only included regions
2862 * will be verified.
2863 *
2864 * @param flashctx The context of the flash chip.
2865 * @param buffer Source buffer to verify with.
2866 * @param buffer_len Size of source buffer in bytes.
2867 * @return 0 on success,
Daniel Campelloef545b12021-04-10 10:39:26 -06002868 * 3 if the chip's contents don't match,
Daniel Campellof758a8b2021-03-22 14:47:13 -06002869 * 2 if buffer_len doesn't match the size of the flash chip,
2870 * or 1 on any other failure.
2871 */
2872int flashrom_image_verify(struct flashctx *const flashctx, const void *const buffer, const size_t buffer_len)
2873{
2874 const size_t flash_size = flashctx->chip->total_size * 1024;
2875
2876 if (buffer_len != flash_size)
2877 return 2;
2878
Daniel Campellocb88c9a2021-04-13 19:23:47 -06002879 const uint8_t *const newcontents = buffer;
Daniel Campelloef545b12021-04-10 10:39:26 -06002880 uint8_t *const curcontents = malloc(flash_size);
Daniel Campellocb88c9a2021-04-13 19:23:47 -06002881 if (!curcontents) {
Daniel Campellof758a8b2021-03-22 14:47:13 -06002882 msg_gerr("Out of memory!\n");
Daniel Campellocb88c9a2021-04-13 19:23:47 -06002883 return 1;
Daniel Campellof758a8b2021-03-22 14:47:13 -06002884 }
2885
Daniel Campellocb88c9a2021-04-13 19:23:47 -06002886 int ret = 1;
2887
Daniel Campellof758a8b2021-03-22 14:47:13 -06002888 if (prepare_flash_access(flashctx, false, false, false, true))
2889 goto _free_ret;
2890
Daniel Campellof758a8b2021-03-22 14:47:13 -06002891 msg_cinfo("Verifying flash... ");
Daniel Campelloef545b12021-04-10 10:39:26 -06002892 ret = verify_by_layout(flashctx, curcontents, newcontents);
Daniel Campellof758a8b2021-03-22 14:47:13 -06002893 if (!ret)
2894 msg_cinfo("VERIFIED.\n");
2895
Daniel Campellof758a8b2021-03-22 14:47:13 -06002896 finalize_flash_access(flashctx);
2897_free_ret:
Daniel Campelloef545b12021-04-10 10:39:26 -06002898 free(curcontents);
Daniel Campellof758a8b2021-03-22 14:47:13 -06002899 return ret;
2900}
2901
Edward O'Callaghan020dfa12020-09-23 23:12:55 +10002902/** @} */ /* end flashrom-ops */
2903
2904int do_read(struct flashctx *const flash, const char *const filename)
2905{
Edward O'Callaghan8e3e18f2020-12-03 13:12:06 +11002906 if (prepare_flash_access(flash, true, false, false, false))
2907 return 1;
2908
Edward O'Callaghan471958e2020-12-09 12:40:12 +11002909 const int ret = read_flash_to_file(flash, filename);
2910
Edward O'Callaghan919ddbd2020-12-03 13:17:30 +11002911 finalize_flash_access(flash);
2912
Edward O'Callaghan020dfa12020-09-23 23:12:55 +10002913 return ret;
2914}
2915
Daniel Campello83752f82021-04-16 14:54:27 -06002916int do_extract(struct flashctx *const flash)
2917{
2918 prepare_layout_for_extraction(flash);
2919 return do_read(flash, NULL);
2920}
2921
Edward O'Callaghan6e573be2020-12-18 10:38:06 +11002922int do_erase(struct flashctx *const flash)
Edward O'Callaghan020dfa12020-09-23 23:12:55 +10002923{
Daniel Campello26765322021-03-22 14:53:27 -06002924 const int ret = flashrom_flash_erase(flash);
Edward O'Callaghan020dfa12020-09-23 23:12:55 +10002925
2926 /*
2927 * FIXME: Do we really want the scary warning if erase failed?
2928 * After all, after erase the chip is either blank or partially
2929 * blank or it has the old contents. A blank chip won't boot,
2930 * so if the user wanted erase and reboots afterwards, the user
2931 * knows very well that booting won't work.
2932 */
2933 if (ret)
2934 emergency_help_message();
2935
2936 return ret;
2937}
2938
Edward O'Callaghan6e573be2020-12-18 10:38:06 +11002939int do_write(struct flashctx *const flash, const char *const filename, const char *const referencefile)
Edward O'Callaghan020dfa12020-09-23 23:12:55 +10002940{
Daniel Campellofb0ee9c2021-03-19 12:51:25 -06002941 const size_t flash_size = flash->chip->total_size * 1024;
2942 int ret = 1;
Edward O'Callaghan8e3e18f2020-12-03 13:12:06 +11002943
Daniel Campellocb88c9a2021-04-13 19:23:47 -06002944 uint8_t *const newcontents = malloc(flash_size);
Daniel Campellofb0ee9c2021-03-19 12:51:25 -06002945 uint8_t *const refcontents = referencefile ? malloc(flash_size) : NULL;
2946
Daniel Campellocb88c9a2021-04-13 19:23:47 -06002947 if (!newcontents || (referencefile && !refcontents)) {
Daniel Campellofb0ee9c2021-03-19 12:51:25 -06002948 msg_gerr("Out of memory!\n");
2949 goto _free_ret;
2950 }
2951
Daniel Campellocb88c9a2021-04-13 19:23:47 -06002952 /* Read '-w' argument first... */
Daniel Campellofb0ee9c2021-03-19 12:51:25 -06002953 if (filename) {
2954 if (read_buf_from_file(newcontents, flash_size, filename))
2955 goto _free_ret;
Daniel Campellofb0ee9c2021-03-19 12:51:25 -06002956 }
Daniel Campellocb88c9a2021-04-13 19:23:47 -06002957 /*
2958 * ... then update newcontents with contents from files provided to '-i'
2959 * args if needed.
2960 */
2961 if (read_buf_from_include_args(flash, newcontents))
2962 goto _free_ret;
Daniel Campellofb0ee9c2021-03-19 12:51:25 -06002963
2964 if (referencefile) {
2965 if (read_buf_from_file(refcontents, flash_size, referencefile))
2966 goto _free_ret;
2967 }
2968
Daniel Campelloc1c1f7b2021-03-19 13:09:27 -06002969 ret = flashrom_image_write(flash, newcontents, flash_size, refcontents);
Edward O'Callaghan919ddbd2020-12-03 13:17:30 +11002970
Daniel Campellofb0ee9c2021-03-19 12:51:25 -06002971_free_ret:
2972 free(refcontents);
2973 free(newcontents);
Edward O'Callaghan020dfa12020-09-23 23:12:55 +10002974 return ret;
2975}
2976
Edward O'Callaghan6e573be2020-12-18 10:38:06 +11002977int do_verify(struct flashctx *const flash, const char *const filename)
Edward O'Callaghan020dfa12020-09-23 23:12:55 +10002978{
Daniel Campellofb0ee9c2021-03-19 12:51:25 -06002979 const size_t flash_size = flash->chip->total_size * 1024;
2980 int ret = 1;
Edward O'Callaghan8e3e18f2020-12-03 13:12:06 +11002981
Daniel Campellocb88c9a2021-04-13 19:23:47 -06002982 uint8_t *const newcontents = malloc(flash_size);
2983 if (!newcontents) {
Daniel Campellofb0ee9c2021-03-19 12:51:25 -06002984 msg_gerr("Out of memory!\n");
2985 goto _free_ret;
2986 }
2987
Daniel Campellocb88c9a2021-04-13 19:23:47 -06002988 /* Read '-v' argument first... */
Daniel Campellofb0ee9c2021-03-19 12:51:25 -06002989 if (filename) {
2990 if (read_buf_from_file(newcontents, flash_size, filename))
2991 goto _free_ret;
Daniel Campellofb0ee9c2021-03-19 12:51:25 -06002992 }
Daniel Campellocb88c9a2021-04-13 19:23:47 -06002993 /*
2994 * ... then update newcontents with contents from files provided to '-i'
2995 * args if needed.
2996 */
2997 if (read_buf_from_include_args(flash, newcontents))
2998 goto _free_ret;
Daniel Campellofb0ee9c2021-03-19 12:51:25 -06002999
Daniel Campellof758a8b2021-03-22 14:47:13 -06003000 ret = flashrom_image_verify(flash, newcontents, flash_size);
Edward O'Callaghan919ddbd2020-12-03 13:17:30 +11003001
Daniel Campellofb0ee9c2021-03-19 12:51:25 -06003002_free_ret:
3003 free(newcontents);
Edward O'Callaghan020dfa12020-09-23 23:12:55 +10003004 return ret;
3005}