1 /*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009,2010 Carl-Daniel Hailfinger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16 #include <assert.h>
17 #include <string.h>
18 #include <stdbool.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <ctype.h>
22 #include <errno.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include "flash.h"
26 #include "chipdrivers.h"
27 #include "programmer.h"
28 #include "flashchips.h"
29 #include "spi.h"
30 #include "writeprotect.h"
31
32 enum emu_chip {
33 EMULATE_NONE,
34 EMULATE_ST_M25P10_RES,
35 EMULATE_SST_SST25VF040_REMS,
36 EMULATE_SST_SST25VF032B,
37 EMULATE_MACRONIX_MX25L6436,
38 EMULATE_WINBOND_W25Q128FV,
39 EMULATE_SPANSION_S25FL128L,
40 EMULATE_VARIABLE_SIZE,
41 };
42
43 struct emu_data {
44 enum emu_chip emu_chip;
45 char *emu_persistent_image;
46 unsigned int emu_chip_size;
47 /* Note: W25Q128FV doesn't change value of SR2 if it's not provided, but
48 * even its previous generations do, so don't forget to update
49 * WRSR code on enabling WRSR_EXT2 for more chips. */
50 bool emu_wrsr_ext2;
51 bool emu_wrsr_ext3;
52 bool erase_to_zero;
53 bool emu_modified; /* is the image modified since reading it? */
54 uint8_t emu_status[3];
55 uint8_t emu_status_len; /* number of emulated status registers */
56 /* If "freq" parameter is passed in from command line, commands will delay
57 * for this period before returning. */
58 unsigned long long delay_ns;
59 unsigned int emu_max_byteprogram_size;
60 unsigned int emu_max_aai_size;
61 unsigned int emu_jedec_se_size;
62 unsigned int emu_jedec_be_52_size;
63 unsigned int emu_jedec_be_d8_size;
64 unsigned int emu_jedec_ce_60_size;
65 unsigned int emu_jedec_ce_c7_size;
66 unsigned char spi_blacklist[256];
67 unsigned char spi_ignorelist[256];
68 unsigned int spi_blacklist_size;
69 unsigned int spi_ignorelist_size;
70
71 bool hwwp; /* state of hardware write protection */
72 /* wp_start == wp_end when write-protection is disabled */
73 uint32_t wp_start;
74 uint32_t wp_end;
75
76 unsigned int spi_write_256_chunksize;
77 uint8_t *flashchip_contents;
78
79 /* An instance of this structure is shared between multiple masters, so
80 * store the number of references to clean up only once at shutdown time. */
81 uint8_t refs_cnt;
82 };
83
84 /* A legit complete SFDP table based on the MX25L6436E (rev. 1.8) datasheet. */
85 static const uint8_t sfdp_table[] = {
86 0x53, 0x46, 0x44, 0x50, // @0x00: SFDP signature
87 0x00, 0x01, 0x01, 0xFF, // @0x04: revision 1.0, 2 headers
88 0x00, 0x00, 0x01, 0x09, // @0x08: JEDEC SFDP header rev. 1.0, 9 DW long
89 0x1C, 0x00, 0x00, 0xFF, // @0x0C: PTP0 = 0x1C (instead of 0x30)
90 0xC2, 0x00, 0x01, 0x04, // @0x10: Macronix header rev. 1.0, 4 DW long
91 0x48, 0x00, 0x00, 0xFF, // @0x14: PTP1 = 0x48 (instead of 0x60)
92 0xFF, 0xFF, 0xFF, 0xFF, // @0x18: hole.
93 0xE5, 0x20, 0xC9, 0xFF, // @0x1C: SFDP parameter table start
94 0xFF, 0xFF, 0xFF, 0x03, // @0x20
95 0x00, 0xFF, 0x08, 0x6B, // @0x24
96 0x08, 0x3B, 0x00, 0xFF, // @0x28
97 0xEE, 0xFF, 0xFF, 0xFF, // @0x2C
98 0xFF, 0xFF, 0x00, 0x00, // @0x30
99 0xFF, 0xFF, 0x00, 0xFF, // @0x34
100 0x0C, 0x20, 0x0F, 0x52, // @0x38
101 0x10, 0xD8, 0x00, 0xFF, // @0x3C: SFDP parameter table end
102 0xFF, 0xFF, 0xFF, 0xFF, // @0x40: hole.
103 0xFF, 0xFF, 0xFF, 0xFF, // @0x44: hole.
104 0x00, 0x36, 0x00, 0x27, // @0x48: Macronix parameter table start
105 0xF4, 0x4F, 0xFF, 0xFF, // @0x4C
106 0xD9, 0xC8, 0xFF, 0xFF, // @0x50
107 0xFF, 0xFF, 0xFF, 0xFF, // @0x54: Macronix parameter table end
108 };
109
dummy_map(const char * descr,uintptr_t phys_addr,size_t len)110 static void *dummy_map(const char *descr, uintptr_t phys_addr, size_t len)
111 {
112 msg_pspew("%s: Mapping %s, 0x%zx bytes at 0x%0*" PRIxPTR "\n",
113 __func__, descr, len, PRIxPTR_WIDTH, phys_addr);
114 return (void *)phys_addr;
115 }
116
dummy_unmap(void * virt_addr,size_t len)117 static void dummy_unmap(void *virt_addr, size_t len)
118 {
119 msg_pspew("%s: Unmapping 0x%zx bytes at %p\n", __func__, len, virt_addr);
120 }
121
dummy_spi_write_256(struct flashctx * flash,const uint8_t * buf,unsigned int start,unsigned int len)122 static int dummy_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
123 {
124 struct emu_data *emu_data = flash->mst->spi.data;
125 return spi_write_chunked(flash, buf, start, len,
126 emu_data->spi_write_256_chunksize);
127 }
128
dummy_spi_probe_opcode(const struct flashctx * flash,uint8_t opcode)129 static bool dummy_spi_probe_opcode(const struct flashctx *flash, uint8_t opcode)
130 {
131 size_t i;
132 const struct emu_data *emu_data = flash->mst->spi.data;
133 for (i = 0; i < emu_data->spi_blacklist_size; i++) {
134 if (emu_data->spi_blacklist[i] == opcode)
135 return false;
136 }
137 return true;
138 }
139
probe_variable_size(struct flashctx * flash)140 static int probe_variable_size(struct flashctx *flash)
141 {
142 const struct emu_data *emu_data = flash->mst->opaque.data;
143
144 /* Skip the probing if we don't emulate "variable size" chip. */
145 if (!emu_data || emu_data->emu_chip != EMULATE_VARIABLE_SIZE)
146 return 0;
147
148 flash->chip->total_size = emu_data->emu_chip_size / 1024;
149 msg_cdbg("%s: set flash->total_size to %dK bytes.\n", __func__,
150 flash->chip->total_size);
151
152 flash->chip->tested = TEST_OK_PREWB;
153
154 if (emu_data->erase_to_zero)
155 flash->chip->feature_bits |= FEATURE_ERASED_ZERO;
156
157 /*
158 * Update the first count of the block_eraser.
159 * Opaque flash chip entry in flashchips.c has only one block eraser.
160 *
161 * If this changes in future, the code below needs to be adjusted
162 * to update all block erasers.
163 */
164 struct block_eraser *eraser = &flash->chip->block_erasers[0];
165 if (!eraser->block_erase)
166 return 1;
167
168 eraser->eraseblocks[0].count = 1;
169 eraser->eraseblocks[0].size = emu_data->emu_chip_size;
170 msg_cdbg("%s: eraser.size=%d, .count=%d\n",
171 __func__, eraser->eraseblocks[0].size,
172 eraser->eraseblocks[0].count);
173
174 return 1;
175 }
176
dummy_opaque_read(struct flashctx * flash,uint8_t * buf,unsigned int start,unsigned int len)177 static int dummy_opaque_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
178 {
179 const struct emu_data *emu_data = flash->mst->opaque.data;
180
181 memcpy(buf, emu_data->flashchip_contents + start, len);
182
183 return 0;
184 }
185
dummy_opaque_write(struct flashctx * flash,const uint8_t * buf,unsigned int start,unsigned int len)186 static int dummy_opaque_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
187 {
188 struct emu_data *emu_data = flash->mst->opaque.data;
189
190 memcpy(emu_data->flashchip_contents + start, buf, len);
191 emu_data->emu_modified = true;
192
193 return 0;
194 }
195
dummy_opaque_erase(struct flashctx * flash,unsigned int blockaddr,unsigned int blocklen)196 static int dummy_opaque_erase(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen)
197 {
198 struct emu_data *emu_data = flash->mst->opaque.data;
199
200 memset(emu_data->flashchip_contents + blockaddr, emu_data->erase_to_zero ? 0x00 : 0xff, blocklen);
201 emu_data->emu_modified = true;
202
203 return 0;
204 }
205
dummy_chip_writeb(const struct flashctx * flash,uint8_t val,chipaddr addr)206 static void dummy_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr)
207 {
208 msg_pspew("%s: addr=0x%" PRIxPTR ", val=0x%02x\n", __func__, addr, val);
209 }
210
dummy_chip_writew(const struct flashctx * flash,uint16_t val,chipaddr addr)211 static void dummy_chip_writew(const struct flashctx *flash, uint16_t val, chipaddr addr)
212 {
213 msg_pspew("%s: addr=0x%" PRIxPTR ", val=0x%04x\n", __func__, addr, val);
214 }
215
dummy_chip_writel(const struct flashctx * flash,uint32_t val,chipaddr addr)216 static void dummy_chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr)
217 {
218 msg_pspew("%s: addr=0x%" PRIxPTR ", val=0x%08"PRIx32"\n", __func__, addr, val);
219 }
220
dummy_chip_writen(const struct flashctx * flash,const uint8_t * buf,chipaddr addr,size_t len)221 static void dummy_chip_writen(const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len)
222 {
223 size_t i;
224 msg_pspew("%s: addr=0x%" PRIxPTR ", len=0x%zx, writing data (hex):", __func__, addr, len);
225 for (i = 0; i < len; i++) {
226 if ((i % 16) == 0)
227 msg_pspew("\n");
228 msg_pspew("%02x ", buf[i]);
229 }
230 }
231
dummy_chip_readb(const struct flashctx * flash,const chipaddr addr)232 static uint8_t dummy_chip_readb(const struct flashctx *flash, const chipaddr addr)
233 {
234 msg_pspew("%s: addr=0x%" PRIxPTR ", returning 0xff\n", __func__, addr);
235 return 0xff;
236 }
237
dummy_chip_readw(const struct flashctx * flash,const chipaddr addr)238 static uint16_t dummy_chip_readw(const struct flashctx *flash, const chipaddr addr)
239 {
240 msg_pspew("%s: addr=0x%" PRIxPTR ", returning 0xffff\n", __func__, addr);
241 return 0xffff;
242 }
243
dummy_chip_readl(const struct flashctx * flash,const chipaddr addr)244 static uint32_t dummy_chip_readl(const struct flashctx *flash, const chipaddr addr)
245 {
246 msg_pspew("%s: addr=0x%" PRIxPTR ", returning 0xffffffff\n", __func__, addr);
247 return 0xffffffff;
248 }
249
dummy_chip_readn(const struct flashctx * flash,uint8_t * buf,const chipaddr addr,size_t len)250 static void dummy_chip_readn(const struct flashctx *flash, uint8_t *buf, const chipaddr addr, size_t len)
251 {
252 msg_pspew("%s: addr=0x%" PRIxPTR ", len=0x%zx, returning array of 0xff\n", __func__, addr, len);
253 memset(buf, 0xff, len);
254 return;
255 }
256
get_reg_ro_bit_mask(const struct emu_data * data,enum flash_reg reg)257 static uint8_t get_reg_ro_bit_mask(const struct emu_data *data, enum flash_reg reg)
258 {
259 /* Whoever adds a new register must not forget to update this function
260 or at least shouldn't use it incorrectly. */
261 assert(reg == STATUS1 || reg == STATUS2 || reg == STATUS3);
262
263 uint8_t ro_bits = reg == STATUS1 ? SPI_SR_WIP : 0;
264
265 if (data->emu_chip == EMULATE_WINBOND_W25Q128FV) {
266 const bool srp0 = (data->emu_status[0] >> 7);
267 const bool srp1 = (data->emu_status[1] & 1);
268
269 const bool wp_active = (srp1 || (srp0 && data->hwwp));
270
271 if (wp_active) {
272 ro_bits = 0xff;
273 } else if (reg == STATUS2) {
274 /* SUS (bit_7) and (R) (bit_2). */
275 ro_bits = 0x84;
276 /* Once any of the lock bits (LB[1..3]) are set, they
277 can't be unset. */
278 ro_bits |= data->emu_status[1] & (1 << 3);
279 ro_bits |= data->emu_status[1] & (1 << 4);
280 ro_bits |= data->emu_status[1] & (1 << 5);
281 } else if (reg == STATUS3) {
282 /* Four reserved bits. */
283 ro_bits = 0x1b;
284 }
285 }
286
287 if (data->emu_chip == EMULATE_SPANSION_S25FL128L) {
288 const bool srp0 = (data->emu_status[0] >> 7);
289 const bool srp1 = (data->emu_status[1] & 1);
290
291 const bool wp_active = (srp1 || (srp0 && data->hwwp));
292
293 if (wp_active) {
294 ro_bits = 0xff;
295 } else if (reg == STATUS2) {
296 /* SUS (bit_7) */
297 ro_bits = 0x80;
298 /* Once any of the lock bits (LB[0..3]) are set, they
299 can't be unset. */
300 ro_bits |= data->emu_status[1] & (1 << 2);
301 ro_bits |= data->emu_status[1] & (1 << 3);
302 ro_bits |= data->emu_status[1] & (1 << 4);
303 ro_bits |= data->emu_status[1] & (1 << 5);
304 } else if (reg == STATUS3) {
305 /* Two reserved bits. */
306 ro_bits = 0x11;
307 }
308 }
309
310 return ro_bits;
311 }
312
update_write_protection(struct emu_data * data)313 static void update_write_protection(struct emu_data *data)
314 {
315 if (data->emu_chip != EMULATE_WINBOND_W25Q128FV &&
316 data->emu_chip != EMULATE_SPANSION_S25FL128L)
317 return;
318
319 const struct wp_bits bits = {
320 .srp = data->emu_status[0] >> 7,
321 .srl = data->emu_status[1] & 1,
322
323 .bp_bit_count = 3,
324 .bp =
325 {
326 (data->emu_status[0] >> 2) & 1,
327 (data->emu_status[0] >> 3) & 1,
328 (data->emu_status[0] >> 4) & 1
329 },
330
331 .tb_bit_present = true,
332 .tb = (data->emu_status[0] >> 5) & 1,
333
334 .sec_bit_present = true,
335 .sec = (data->emu_status[0] >> 6) & 1,
336
337 .cmp_bit_present = true,
338 .cmp = (data->emu_status[1] >> 6) & 1,
339 };
340
341 size_t start;
342 size_t len;
343 decode_range_spi25(&start, &len, &bits, data->emu_chip_size);
344
345 data->wp_start = start;
346 data->wp_end = start + len;
347 }
348
349 /* Checks whether range intersects a write-protected area of the flash if one is
350 * defined. */
is_write_protected(const struct emu_data * data,uint32_t start,uint32_t len)351 static bool is_write_protected(const struct emu_data *data, uint32_t start, uint32_t len)
352 {
353 if (len == 0)
354 return false;
355
356 const uint32_t last = start + len - 1;
357 return (start < data->wp_end && last >= data->wp_start);
358 }
359
360 /* Returns non-zero on error. */
write_flash_data(struct emu_data * data,uint32_t start,uint32_t len,const uint8_t * buf)361 static int write_flash_data(struct emu_data *data, uint32_t start, uint32_t len, const uint8_t *buf)
362 {
363 if (is_write_protected(data, start, len)) {
364 msg_perr("At least part of the write range is write protected!\n");
365 return 1;
366 }
367
368 memcpy(data->flashchip_contents + start, buf, len);
369 data->emu_modified = true;
370 return 0;
371 }
372
373 /* Returns non-zero on error. */
erase_flash_data(struct emu_data * data,uint32_t start,uint32_t len)374 static int erase_flash_data(struct emu_data *data, uint32_t start, uint32_t len)
375 {
376 if (is_write_protected(data, start, len)) {
377 msg_perr("At least part of the erase range is write protected!\n");
378 return 1;
379 }
380
381 /* FIXME: Maybe use ERASED_VALUE(flash) instead of 0xff ? */
382 memset(data->flashchip_contents + start, 0xff, len);
383 data->emu_modified = true;
384 return 0;
385 }
386
emulate_spi_chip_response(unsigned int writecnt,unsigned int readcnt,const unsigned char * writearr,unsigned char * readarr,struct emu_data * data)387 static int emulate_spi_chip_response(unsigned int writecnt,
388 unsigned int readcnt,
389 const unsigned char *writearr,
390 unsigned char *readarr,
391 struct emu_data *data)
392 {
393 unsigned int offs, i, toread;
394 uint8_t ro_bits;
395 bool wrsr_ext2, wrsr_ext3;
396 static int unsigned aai_offs;
397 const unsigned char sst25vf040_rems_response[2] = {0xbf, 0x44};
398 const unsigned char sst25vf032b_rems_response[2] = {0xbf, 0x4a};
399 const unsigned char mx25l6436_rems_response[2] = {0xc2, 0x16};
400 const unsigned char w25q128fv_rems_response[2] = {0xef, 0x17};
401
402 if (writecnt == 0) {
403 msg_perr("No command sent to the chip!\n");
404 return 1;
405 }
406 /* spi_blacklist has precedence over spi_ignorelist. */
407 for (i = 0; i < data->spi_blacklist_size; i++) {
408 if (writearr[0] == data->spi_blacklist[i]) {
409 msg_pdbg("Refusing blacklisted SPI command 0x%02x\n",
410 data->spi_blacklist[i]);
411 return SPI_INVALID_OPCODE;
412 }
413 }
414 for (i = 0; i < data->spi_ignorelist_size; i++) {
415 if (writearr[0] == data->spi_ignorelist[i]) {
416 msg_cdbg("Ignoring ignorelisted SPI command 0x%02x\n",
417 data->spi_ignorelist[i]);
418 /* Return success because the command does not fail,
419 * it is simply ignored.
420 */
421 return 0;
422 }
423 }
424
425 if (data->emu_max_aai_size && (data->emu_status[0] & SPI_SR_AAI)) {
426 if (writearr[0] != JEDEC_AAI_WORD_PROGRAM &&
427 writearr[0] != JEDEC_WRDI &&
428 writearr[0] != JEDEC_RDSR) {
429 msg_perr("Forbidden opcode (0x%02x) attempted during "
430 "AAI sequence!\n", writearr[0]);
431 return 0;
432 }
433 }
434
435 switch (writearr[0]) {
436 case JEDEC_RES:
437 if (writecnt < JEDEC_RES_OUTSIZE)
438 break;
439 /* offs calculation is only needed for SST chips which treat RES like REMS. */
440 offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3];
441 offs += writecnt - JEDEC_REMS_OUTSIZE;
442 switch (data->emu_chip) {
443 case EMULATE_ST_M25P10_RES:
444 if (readcnt > 0)
445 memset(readarr, 0x10, readcnt);
446 break;
447 case EMULATE_SST_SST25VF040_REMS:
448 for (i = 0; i < readcnt; i++)
449 readarr[i] = sst25vf040_rems_response[(offs + i) % 2];
450 break;
451 case EMULATE_SST_SST25VF032B:
452 for (i = 0; i < readcnt; i++)
453 readarr[i] = sst25vf032b_rems_response[(offs + i) % 2];
454 break;
455 case EMULATE_MACRONIX_MX25L6436:
456 if (readcnt > 0)
457 memset(readarr, 0x16, readcnt);
458 break;
459 case EMULATE_WINBOND_W25Q128FV:
460 if (readcnt > 0)
461 memset(readarr, 0x17, readcnt);
462 break;
463 case EMULATE_SPANSION_S25FL128L:
464 if (readcnt > 0)
465 readarr[0] = 0x60;
466 if (readcnt > 1)
467 readarr[1] = 0x18;
468 break;
469 default: /* ignore */
470 break;
471 }
472 break;
473 case JEDEC_REMS:
474 /* REMS response has wraparound and uses an address parameter. */
475 if (writecnt < JEDEC_REMS_OUTSIZE)
476 break;
477 offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3];
478 offs += writecnt - JEDEC_REMS_OUTSIZE;
479 switch (data->emu_chip) {
480 case EMULATE_SST_SST25VF040_REMS:
481 for (i = 0; i < readcnt; i++)
482 readarr[i] = sst25vf040_rems_response[(offs + i) % 2];
483 break;
484 case EMULATE_SST_SST25VF032B:
485 for (i = 0; i < readcnt; i++)
486 readarr[i] = sst25vf032b_rems_response[(offs + i) % 2];
487 break;
488 case EMULATE_MACRONIX_MX25L6436:
489 for (i = 0; i < readcnt; i++)
490 readarr[i] = mx25l6436_rems_response[(offs + i) % 2];
491 break;
492 case EMULATE_WINBOND_W25Q128FV:
493 for (i = 0; i < readcnt; i++)
494 readarr[i] = w25q128fv_rems_response[(offs + i) % 2];
495 break;
496 default: /* ignore */
497 break;
498 }
499 break;
500 case JEDEC_RDID:
501 switch (data->emu_chip) {
502 case EMULATE_SST_SST25VF032B:
503 if (readcnt > 0)
504 readarr[0] = 0xbf;
505 if (readcnt > 1)
506 readarr[1] = 0x25;
507 if (readcnt > 2)
508 readarr[2] = 0x4a;
509 break;
510 case EMULATE_MACRONIX_MX25L6436:
511 if (readcnt > 0)
512 readarr[0] = 0xc2;
513 if (readcnt > 1)
514 readarr[1] = 0x20;
515 if (readcnt > 2)
516 readarr[2] = 0x17;
517 break;
518 case EMULATE_WINBOND_W25Q128FV:
519 if (readcnt > 0)
520 readarr[0] = 0xef;
521 if (readcnt > 1)
522 readarr[1] = 0x40;
523 if (readcnt > 2)
524 readarr[2] = 0x18;
525 break;
526 case EMULATE_SPANSION_S25FL128L:
527 if (readcnt > 0)
528 readarr[0] = 0x01;
529 if (readcnt > 1)
530 readarr[1] = 0x60;
531 if (readcnt > 2)
532 readarr[2] = 0x18;
533 break;
534 case EMULATE_VARIABLE_SIZE:
535 if (readcnt > 0)
536 readarr[0] = (PROGMANUF_ID >> 8) & 0xff;
537 if (readcnt > 1)
538 readarr[1] = PROGMANUF_ID & 0xff;
539 if (readcnt > 2)
540 readarr[2] = (PROGDEV_ID >> 8) & 0xff;
541 if (readcnt > 3)
542 readarr[3] = PROGDEV_ID & 0xff;
543 break;
544 default: /* ignore */
545 break;
546 }
547 break;
548 case JEDEC_RDSR:
549 memset(readarr, data->emu_status[0], readcnt);
550 break;
551 case JEDEC_RDSR2:
552 if (data->emu_status_len >= 2)
553 memset(readarr, data->emu_status[1], readcnt);
554 break;
555 case JEDEC_RDSR3:
556 if (data->emu_status_len >= 3)
557 memset(readarr, data->emu_status[2], readcnt);
558 break;
559 /* FIXME: this should be chip-specific. */
560 case JEDEC_EWSR:
561 case JEDEC_WREN:
562 data->emu_status[0] |= SPI_SR_WEL;
563 break;
564 case JEDEC_WRSR:
565 if (!(data->emu_status[0] & SPI_SR_WEL)) {
566 msg_perr("WRSR attempted, but WEL is 0!\n");
567 break;
568 }
569
570 wrsr_ext2 = (writecnt == 3 && data->emu_wrsr_ext2);
571 wrsr_ext3 = (writecnt == 4 && data->emu_wrsr_ext3);
572
573 /* FIXME: add some reasonable simulation of the busy flag */
574
575 ro_bits = get_reg_ro_bit_mask(data, STATUS1);
576 data->emu_status[0] &= ro_bits;
577 data->emu_status[0] |= writearr[1] & ~ro_bits;
578 if (wrsr_ext2 || wrsr_ext3) {
579 ro_bits = get_reg_ro_bit_mask(data, STATUS2);
580 data->emu_status[1] &= ro_bits;
581 data->emu_status[1] |= writearr[2] & ~ro_bits;
582 }
583 if (wrsr_ext3) {
584 ro_bits = get_reg_ro_bit_mask(data, STATUS3);
585 data->emu_status[2] &= ro_bits;
586 data->emu_status[2] |= writearr[3] & ~ro_bits;
587 }
588
589 if (wrsr_ext3)
590 msg_pdbg2("WRSR wrote 0x%02x%02x%02x.\n", data->emu_status[2], data->emu_status[1], data->emu_status[0]);
591 else if (wrsr_ext2)
592 msg_pdbg2("WRSR wrote 0x%02x%02x.\n", data->emu_status[1], data->emu_status[0]);
593 else
594 msg_pdbg2("WRSR wrote 0x%02x.\n", data->emu_status[0]);
595
596 update_write_protection(data);
597 break;
598 case JEDEC_WRSR2:
599 if (data->emu_status_len < 2)
600 break;
601 if (!(data->emu_status[0] & SPI_SR_WEL)) {
602 msg_perr("WRSR2 attempted, but WEL is 0!\n");
603 break;
604 }
605
606 ro_bits = get_reg_ro_bit_mask(data, STATUS2);
607 data->emu_status[1] &= ro_bits;
608 data->emu_status[1] |= (writearr[1] & ~ro_bits);
609
610 msg_pdbg2("WRSR2 wrote 0x%02x.\n", data->emu_status[1]);
611
612 update_write_protection(data);
613 break;
614 case JEDEC_WRSR3:
615 if (data->emu_status_len < 3)
616 break;
617 if (!(data->emu_status[0] & SPI_SR_WEL)) {
618 msg_perr("WRSR3 attempted, but WEL is 0!\n");
619 break;
620 }
621
622 ro_bits = get_reg_ro_bit_mask(data, STATUS3);
623 data->emu_status[2] &= ro_bits;
624 data->emu_status[2] |= (writearr[1] & ~ro_bits);
625
626 msg_pdbg2("WRSR3 wrote 0x%02x.\n", data->emu_status[2]);
627 break;
628 case JEDEC_READ:
629 offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3];
630 /* Truncate to emu_chip_size. */
631 offs %= data->emu_chip_size;
632 if (readcnt > 0)
633 memcpy(readarr, data->flashchip_contents + offs, readcnt);
634 break;
635 case JEDEC_READ_4BA:
636 offs = writearr[1] << 24 | writearr[2] << 16 | writearr[3] << 8 | writearr[4];
637 /* Truncate to emu_chip_size. */
638 offs %= data->emu_chip_size;
639 if (readcnt > 0)
640 memcpy(readarr, data->flashchip_contents + offs, readcnt);
641 break;
642 case JEDEC_BYTE_PROGRAM:
643 offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3];
644 /* Truncate to emu_chip_size. */
645 offs %= data->emu_chip_size;
646 if (writecnt < 5) {
647 msg_perr("BYTE PROGRAM size too short!\n");
648 return 1;
649 }
650 if (writecnt - 4 > data->emu_max_byteprogram_size) {
651 msg_perr("Max BYTE PROGRAM size exceeded!\n");
652 return 1;
653 }
654 if (write_flash_data(data, offs, writecnt - 4, writearr + 4)) {
655 msg_perr("Failed to program flash!\n");
656 return 1;
657 }
658 break;
659 case JEDEC_BYTE_PROGRAM_4BA:
660 offs = writearr[1] << 24 | writearr[2] << 16 | writearr[3] << 8 | writearr[4];
661 /* Truncate to emu_chip_size. */
662 offs %= data->emu_chip_size;
663 if (writecnt < 6) {
664 msg_perr("BYTE PROGRAM size too short!\n");
665 return 1;
666 }
667 if (writecnt - 5 > data->emu_max_byteprogram_size) {
668 msg_perr("Max BYTE PROGRAM size exceeded!\n");
669 return 1;
670 }
671 if (write_flash_data(data, offs, writecnt - 5, writearr + 5)) {
672 msg_perr("Failed to program flash!\n");
673 return 1;
674 }
675 break;
676 case JEDEC_AAI_WORD_PROGRAM:
677 if (!data->emu_max_aai_size)
678 break;
679 if (!(data->emu_status[0] & SPI_SR_AAI)) {
680 if (writecnt < JEDEC_AAI_WORD_PROGRAM_OUTSIZE) {
681 msg_perr("Initial AAI WORD PROGRAM size too "
682 "short!\n");
683 return 1;
684 }
685 if (writecnt > JEDEC_AAI_WORD_PROGRAM_OUTSIZE) {
686 msg_perr("Initial AAI WORD PROGRAM size too "
687 "long!\n");
688 return 1;
689 }
690 data->emu_status[0] |= SPI_SR_AAI;
691 aai_offs = writearr[1] << 16 | writearr[2] << 8 |
692 writearr[3];
693 /* Truncate to emu_chip_size. */
694 aai_offs %= data->emu_chip_size;
695 if (write_flash_data(data, aai_offs, 2, writearr + 4)) {
696 msg_perr("Failed to program flash!\n");
697 return 1;
698 }
699 aai_offs += 2;
700 } else {
701 if (writecnt < JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE) {
702 msg_perr("Continuation AAI WORD PROGRAM size "
703 "too short!\n");
704 return 1;
705 }
706 if (writecnt > JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE) {
707 msg_perr("Continuation AAI WORD PROGRAM size "
708 "too long!\n");
709 return 1;
710 }
711 if (write_flash_data(data, aai_offs, 2, writearr + 1)) {
712 msg_perr("Failed to program flash!\n");
713 return 1;
714 }
715 aai_offs += 2;
716 }
717 break;
718 case JEDEC_WRDI:
719 if (data->emu_max_aai_size)
720 data->emu_status[0] &= ~SPI_SR_AAI;
721 break;
722 case JEDEC_SE:
723 if (!data->emu_jedec_se_size)
724 break;
725 if (writecnt != JEDEC_SE_OUTSIZE) {
726 msg_perr("SECTOR ERASE 0x20 outsize invalid!\n");
727 return 1;
728 }
729 if (readcnt != JEDEC_SE_INSIZE) {
730 msg_perr("SECTOR ERASE 0x20 insize invalid!\n");
731 return 1;
732 }
733 offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3];
734 if (offs & (data->emu_jedec_se_size - 1))
735 msg_pdbg("Unaligned SECTOR ERASE 0x20: 0x%x\n", offs);
736 offs &= ~(data->emu_jedec_se_size - 1);
737 if (erase_flash_data(data, offs, data->emu_jedec_se_size)) {
738 msg_perr("Failed to erase flash!\n");
739 return 1;
740 }
741 break;
742 case JEDEC_BE_52:
743 if (!data->emu_jedec_be_52_size)
744 break;
745 if (writecnt != JEDEC_BE_52_OUTSIZE) {
746 msg_perr("BLOCK ERASE 0x52 outsize invalid!\n");
747 return 1;
748 }
749 if (readcnt != JEDEC_BE_52_INSIZE) {
750 msg_perr("BLOCK ERASE 0x52 insize invalid!\n");
751 return 1;
752 }
753 offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3];
754 if (offs & (data->emu_jedec_be_52_size - 1))
755 msg_pdbg("Unaligned BLOCK ERASE 0x52: 0x%x\n", offs);
756 offs &= ~(data->emu_jedec_be_52_size - 1);
757 if (erase_flash_data(data, offs, data->emu_jedec_be_52_size)) {
758 msg_perr("Failed to erase flash!\n");
759 return 1;
760 }
761 break;
762 case JEDEC_BE_D8:
763 if (!data->emu_jedec_be_d8_size)
764 break;
765 if (writecnt != JEDEC_BE_D8_OUTSIZE) {
766 msg_perr("BLOCK ERASE 0xd8 outsize invalid!\n");
767 return 1;
768 }
769 if (readcnt != JEDEC_BE_D8_INSIZE) {
770 msg_perr("BLOCK ERASE 0xd8 insize invalid!\n");
771 return 1;
772 }
773 offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3];
774 if (offs & (data->emu_jedec_be_d8_size - 1))
775 msg_pdbg("Unaligned BLOCK ERASE 0xd8: 0x%x\n", offs);
776 offs &= ~(data->emu_jedec_be_d8_size - 1);
777 if (erase_flash_data(data, offs, data->emu_jedec_be_d8_size)) {
778 msg_perr("Failed to erase flash!\n");
779 return 1;
780 }
781 break;
782 case JEDEC_CE_60:
783 if (!data->emu_jedec_ce_60_size)
784 break;
785 if (writecnt != JEDEC_CE_60_OUTSIZE) {
786 msg_perr("CHIP ERASE 0x60 outsize invalid!\n");
787 return 1;
788 }
789 if (readcnt != JEDEC_CE_60_INSIZE) {
790 msg_perr("CHIP ERASE 0x60 insize invalid!\n");
791 return 1;
792 }
793 /* JEDEC_CE_60_OUTSIZE is 1 (no address) -> no offset. */
794 /* emu_jedec_ce_60_size is emu_chip_size. */
795 if (erase_flash_data(data, 0, data->emu_jedec_ce_60_size)) {
796 msg_perr("Failed to erase flash!\n");
797 return 1;
798 }
799 break;
800 case JEDEC_CE_C7:
801 if (!data->emu_jedec_ce_c7_size)
802 break;
803 if (writecnt != JEDEC_CE_C7_OUTSIZE) {
804 msg_perr("CHIP ERASE 0xc7 outsize invalid!\n");
805 return 1;
806 }
807 if (readcnt != JEDEC_CE_C7_INSIZE) {
808 msg_perr("CHIP ERASE 0xc7 insize invalid!\n");
809 return 1;
810 }
811 /* JEDEC_CE_C7_OUTSIZE is 1 (no address) -> no offset. */
812 /* emu_jedec_ce_c7_size is emu_chip_size. */
813 if (erase_flash_data(data, 0, data->emu_jedec_ce_c7_size)) {
814 msg_perr("Failed to erase flash!\n");
815 return 1;
816 }
817 break;
818 case JEDEC_SFDP:
819 if (data->emu_chip != EMULATE_MACRONIX_MX25L6436)
820 break;
821 if (writecnt < 4)
822 break;
823 offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3];
824
825 /* SFDP expects one dummy byte after the address. */
826 if (writecnt == 4) {
827 /* The dummy byte was not written, make sure it is read instead.
828 * Shifting and shortening the read array does achieve this goal.
829 */
830 readarr++;
831 readcnt--;
832 } else {
833 /* The response is shifted if more than 5 bytes are written, because SFDP data is
834 * already shifted out by the chip while those superfluous bytes are written. */
835 offs += writecnt - 5;
836 }
837
838 /* The SFDP spec implies that the start address of an SFDP read may be truncated to fit in the
839 * SFDP table address space, i.e. the start address may be wrapped around at SFDP table size.
840 * This is a reasonable implementation choice in hardware because it saves a few gates. */
841 if (offs >= sizeof(sfdp_table)) {
842 msg_pdbg("Wrapping the start address around the SFDP table boundary (using 0x%x "
843 "instead of 0x%x).\n", (unsigned int)(offs % sizeof(sfdp_table)), offs);
844 offs %= sizeof(sfdp_table);
845 }
846 toread = min(sizeof(sfdp_table) - offs, readcnt);
847 memcpy(readarr, sfdp_table + offs, toread);
848 if (toread < readcnt)
849 msg_pdbg("Crossing the SFDP table boundary in a single "
850 "continuous chunk produces undefined results "
851 "after that point.\n");
852 break;
853 default:
854 /* No special response. */
855 break;
856 }
857 if (writearr[0] != JEDEC_WREN && writearr[0] != JEDEC_EWSR)
858 data->emu_status[0] &= ~SPI_SR_WEL;
859 return 0;
860 }
861
dummy_spi_send_command(const struct flashctx * flash,unsigned int writecnt,unsigned int readcnt,const unsigned char * writearr,unsigned char * readarr)862 static int dummy_spi_send_command(const struct flashctx *flash, unsigned int writecnt,
863 unsigned int readcnt,
864 const unsigned char *writearr,
865 unsigned char *readarr)
866 {
867 unsigned int i;
868 struct emu_data *emu_data = flash->mst->spi.data;
869 if (!emu_data) {
870 msg_perr("No data in flash context!\n");
871 return 1;
872 }
873
874 msg_pspew("%s:", __func__);
875
876 msg_pspew(" writing %u bytes:", writecnt);
877 for (i = 0; i < writecnt; i++)
878 msg_pspew(" 0x%02x", writearr[i]);
879
880 /* Response for unknown commands and missing chip is 0xff. */
881 memset(readarr, 0xff, readcnt);
882 switch (emu_data->emu_chip) {
883 case EMULATE_ST_M25P10_RES:
884 case EMULATE_SST_SST25VF040_REMS:
885 case EMULATE_SST_SST25VF032B:
886 case EMULATE_MACRONIX_MX25L6436:
887 case EMULATE_WINBOND_W25Q128FV:
888 case EMULATE_SPANSION_S25FL128L:
889 case EMULATE_VARIABLE_SIZE:
890 if (emulate_spi_chip_response(writecnt, readcnt, writearr,
891 readarr, emu_data)) {
892 msg_pdbg("Invalid command sent to flash chip!\n");
893 return 1;
894 }
895 break;
896 default:
897 break;
898 }
899 msg_pspew(" reading %u bytes:", readcnt);
900 for (i = 0; i < readcnt; i++)
901 msg_pspew(" 0x%02x", readarr[i]);
902 msg_pspew("\n");
903
904 default_delay(((writecnt + readcnt) * emu_data->delay_ns) / 1000);
905 return 0;
906 }
907
dummy_shutdown(void * data)908 static int dummy_shutdown(void *data)
909 {
910 msg_pspew("%s\n", __func__);
911 struct emu_data *emu_data = (struct emu_data *)data;
912
913 emu_data->refs_cnt--;
914 if (emu_data->refs_cnt != 0)
915 return 0;
916
917 if (emu_data->emu_chip != EMULATE_NONE) {
918 if (emu_data->emu_persistent_image && emu_data->emu_modified) {
919 msg_pdbg("Writing %s\n", emu_data->emu_persistent_image);
920 write_buf_to_file(emu_data->flashchip_contents,
921 emu_data->emu_chip_size,
922 emu_data->emu_persistent_image);
923 }
924 free(emu_data->emu_persistent_image);
925 free(emu_data->flashchip_contents);
926 }
927 free(data);
928 return 0;
929 }
930
dummy_nop_delay(const struct flashctx * flash,unsigned int usecs)931 static void dummy_nop_delay(const struct flashctx *flash, unsigned int usecs)
932 {
933 }
934
dummy_wp_read_cfg(struct flashrom_wp_cfg * cfg,struct flashctx * flash)935 static enum flashrom_wp_result dummy_wp_read_cfg(struct flashrom_wp_cfg *cfg, struct flashctx *flash)
936 {
937 cfg->mode = FLASHROM_WP_MODE_DISABLED;
938 cfg->range.start = 0;
939 cfg->range.len = 0;
940
941 return FLASHROM_WP_OK;
942 }
943
dummy_wp_write_cfg(struct flashctx * flash,const struct flashrom_wp_cfg * cfg)944 static enum flashrom_wp_result dummy_wp_write_cfg(struct flashctx *flash, const struct flashrom_wp_cfg *cfg)
945 {
946 if (cfg->mode != FLASHROM_WP_MODE_DISABLED)
947 return FLASHROM_WP_ERR_MODE_UNSUPPORTED;
948
949 if (cfg->range.start != 0 || cfg->range.len != 0)
950 return FLASHROM_WP_ERR_RANGE_UNSUPPORTED;
951
952 return FLASHROM_WP_OK;
953 }
954
dummy_wp_get_available_ranges(struct flashrom_wp_ranges ** list,struct flashctx * flash)955 static enum flashrom_wp_result dummy_wp_get_available_ranges(struct flashrom_wp_ranges **list, struct flashctx *flash)
956 {
957 /* Not supported */
958 return FLASHROM_WP_ERR_RANGE_LIST_UNAVAILABLE;
959 }
960
961
962 static const struct spi_master spi_master_dummyflasher = {
963 .map_flash_region = dummy_map,
964 .unmap_flash_region = dummy_unmap,
965 .features = SPI_MASTER_4BA,
966 .max_data_read = MAX_DATA_READ_UNLIMITED,
967 .max_data_write = MAX_DATA_UNSPECIFIED,
968 .command = dummy_spi_send_command,
969 .read = default_spi_read,
970 .write_256 = dummy_spi_write_256,
971 .shutdown = dummy_shutdown,
972 .probe_opcode = dummy_spi_probe_opcode,
973 .delay = dummy_nop_delay,
974 };
975
976 static const struct par_master par_master_dummyflasher = {
977 .map_flash_region = dummy_map,
978 .unmap_flash_region = dummy_unmap,
979 .chip_readb = dummy_chip_readb,
980 .chip_readw = dummy_chip_readw,
981 .chip_readl = dummy_chip_readl,
982 .chip_readn = dummy_chip_readn,
983 .chip_writeb = dummy_chip_writeb,
984 .chip_writew = dummy_chip_writew,
985 .chip_writel = dummy_chip_writel,
986 .chip_writen = dummy_chip_writen,
987 .shutdown = dummy_shutdown,
988 .delay = dummy_nop_delay,
989 };
990
991 static const struct opaque_master opaque_master_dummyflasher = {
992 .probe = probe_variable_size,
993 .read = dummy_opaque_read,
994 .write = dummy_opaque_write,
995 .erase = dummy_opaque_erase,
996 .shutdown = dummy_shutdown,
997 .delay = dummy_nop_delay,
998 .wp_read_cfg = dummy_wp_read_cfg,
999 .wp_write_cfg = dummy_wp_write_cfg,
1000 .wp_get_ranges = dummy_wp_get_available_ranges,
1001 };
1002
init_data(const struct programmer_cfg * cfg,struct emu_data * data,enum chipbustype * dummy_buses_supported)1003 static int init_data(const struct programmer_cfg *cfg,
1004 struct emu_data *data, enum chipbustype *dummy_buses_supported)
1005 {
1006 char *bustext = NULL;
1007 char *tmp = NULL;
1008 unsigned int i;
1009 char *endptr;
1010 char *status = NULL;
1011 int size = -1; /* size for VARIABLE_SIZE chip device */
1012
1013 bustext = extract_programmer_param_str(cfg, "bus");
1014 msg_pdbg("Requested buses are: %s\n", bustext ? bustext : "default");
1015 if (!bustext)
1016 bustext = strdup("parallel+lpc+fwh+spi+prog");
1017 /* Convert the parameters to lowercase. */
1018 tolower_string(bustext);
1019
1020 *dummy_buses_supported = BUS_NONE;
1021 if (strstr(bustext, "parallel")) {
1022 *dummy_buses_supported |= BUS_PARALLEL;
1023 msg_pdbg("Enabling support for %s flash.\n", "parallel");
1024 }
1025 if (strstr(bustext, "lpc")) {
1026 *dummy_buses_supported |= BUS_LPC;
1027 msg_pdbg("Enabling support for %s flash.\n", "LPC");
1028 }
1029 if (strstr(bustext, "fwh")) {
1030 *dummy_buses_supported |= BUS_FWH;
1031 msg_pdbg("Enabling support for %s flash.\n", "FWH");
1032 }
1033 if (strstr(bustext, "spi")) {
1034 *dummy_buses_supported |= BUS_SPI;
1035 msg_pdbg("Enabling support for %s flash.\n", "SPI");
1036 }
1037 if (strstr(bustext, "prog")) {
1038 *dummy_buses_supported |= BUS_PROG;
1039 msg_pdbg("Enabling support for %s flash.\n", "PROG");
1040 }
1041 if (*dummy_buses_supported == BUS_NONE)
1042 msg_pdbg("Support for all flash bus types disabled.\n");
1043 free(bustext);
1044
1045 tmp = extract_programmer_param_str(cfg, "spi_write_256_chunksize");
1046 if (tmp) {
1047 data->spi_write_256_chunksize = strtoul(tmp, &endptr, 0);
1048 if (*endptr != '\0' || data->spi_write_256_chunksize < 1) {
1049 msg_perr("invalid spi_write_256_chunksize\n");
1050 free(tmp);
1051 return 1;
1052 }
1053 }
1054 free(tmp);
1055
1056 tmp = extract_programmer_param_str(cfg, "spi_blacklist");
1057 if (tmp) {
1058 i = strlen(tmp);
1059 if (!strncmp(tmp, "0x", 2)) {
1060 i -= 2;
1061 memmove(tmp, tmp + 2, i + 1);
1062 }
1063 if ((i > 512) || (i % 2)) {
1064 msg_perr("Invalid SPI command blacklist length\n");
1065 free(tmp);
1066 return 1;
1067 }
1068 data->spi_blacklist_size = i / 2;
1069 for (i = 0; i < data->spi_blacklist_size * 2; i++) {
1070 if (!isxdigit((unsigned char)tmp[i])) {
1071 msg_perr("Invalid char \"%c\" in SPI command "
1072 "blacklist\n", tmp[i]);
1073 free(tmp);
1074 return 1;
1075 }
1076 }
1077 for (i = 0; i < data->spi_blacklist_size; i++) {
1078 unsigned int tmp2;
1079 /* SCNx8 is apparently not supported by MSVC (and thus
1080 * MinGW), so work around it with an extra variable
1081 */
1082 sscanf(tmp + i * 2, "%2x", &tmp2);
1083 data->spi_blacklist[i] = (uint8_t)tmp2;
1084 }
1085 msg_pdbg("SPI blacklist is ");
1086 for (i = 0; i < data->spi_blacklist_size; i++)
1087 msg_pdbg("%02x ", data->spi_blacklist[i]);
1088 msg_pdbg(", size %u\n", data->spi_blacklist_size);
1089 }
1090 free(tmp);
1091
1092 tmp = extract_programmer_param_str(cfg, "spi_ignorelist");
1093 if (tmp) {
1094 i = strlen(tmp);
1095 if (!strncmp(tmp, "0x", 2)) {
1096 i -= 2;
1097 memmove(tmp, tmp + 2, i + 1);
1098 }
1099 if ((i > 512) || (i % 2)) {
1100 msg_perr("Invalid SPI command ignorelist length\n");
1101 free(tmp);
1102 return 1;
1103 }
1104 data->spi_ignorelist_size = i / 2;
1105 for (i = 0; i < data->spi_ignorelist_size * 2; i++) {
1106 if (!isxdigit((unsigned char)tmp[i])) {
1107 msg_perr("Invalid char \"%c\" in SPI command "
1108 "ignorelist\n", tmp[i]);
1109 free(tmp);
1110 return 1;
1111 }
1112 }
1113 for (i = 0; i < data->spi_ignorelist_size; i++) {
1114 unsigned int tmp2;
1115 /* SCNx8 is apparently not supported by MSVC (and thus
1116 * MinGW), so work around it with an extra variable
1117 */
1118 sscanf(tmp + i * 2, "%2x", &tmp2);
1119 data->spi_ignorelist[i] = (uint8_t)tmp2;
1120 }
1121 msg_pdbg("SPI ignorelist is ");
1122 for (i = 0; i < data->spi_ignorelist_size; i++)
1123 msg_pdbg("%02x ", data->spi_ignorelist[i]);
1124 msg_pdbg(", size %u\n", data->spi_ignorelist_size);
1125 }
1126 free(tmp);
1127
1128 /* frequency to emulate in Hz (default), KHz, or MHz */
1129 tmp = extract_programmer_param_str(cfg, "freq");
1130 if (tmp) {
1131 unsigned long long freq;
1132 char *units = tmp;
1133 char *end = tmp + strlen(tmp);
1134
1135 errno = 0;
1136 freq = strtoul(tmp, &units, 0);
1137 if (errno) {
1138 msg_perr("Invalid frequency \"%s\", %s\n",
1139 tmp, strerror(errno));
1140 free(tmp);
1141 return 1;
1142 }
1143
1144 if ((units > tmp) && (units < end)) {
1145 bool units_valid = false;
1146
1147 if (units < end - 3) {
1148 ;
1149 } else if (units == end - 2) {
1150 if (!strcasecmp(units, "hz"))
1151 units_valid = true;
1152 } else if (units == end - 3) {
1153 if (!strcasecmp(units, "khz")) {
1154 freq *= 1000;
1155 units_valid = true;
1156 } else if (!strcasecmp(units, "mhz")) {
1157 freq *= 1000000;
1158 units_valid = true;
1159 }
1160 }
1161
1162 if (!units_valid) {
1163 msg_perr("Invalid units: %s\n", units);
1164 free(tmp);
1165 return 1;
1166 }
1167 }
1168
1169 if (freq == 0 || freq > 8000000000) {
1170 msg_perr("%s: invalid value %llu for freq parameter\n", __func__, freq);
1171 free(tmp);
1172 return 1;
1173 }
1174 /* Assume we only work with bytes and transfer at 1 bit/Hz */
1175 data->delay_ns = (1000000000ull * 8) / freq;
1176 }
1177 free(tmp);
1178
1179 tmp = extract_programmer_param_str(cfg, "size");
1180 if (tmp) {
1181 size = strtol(tmp, NULL, 10);
1182 if (size <= 0 || (size % 1024 != 0)) {
1183 msg_perr("%s: Chip size is not a multiple of 1024: %s\n",
1184 __func__, tmp);
1185 free(tmp);
1186 return 1;
1187 }
1188 free(tmp);
1189 }
1190
1191 tmp = extract_programmer_param_str(cfg, "hwwp");
1192 if (tmp) {
1193 if (!strcmp(tmp, "yes")) {
1194 msg_pdbg("Emulated chip will have hardware WP enabled\n");
1195 data->hwwp = true;
1196 } else if (!strcmp(tmp, "no")) {
1197 msg_pdbg("Emulated chip will have hardware WP disabled\n");
1198 } else {
1199 msg_perr("hwwp can be \"yes\" or \"no\"\n");
1200 free(tmp);
1201 return 1;
1202 }
1203 free(tmp);
1204 }
1205
1206 tmp = extract_programmer_param_str(cfg, "emulate");
1207 if (!tmp) {
1208 if (size != -1) {
1209 msg_perr("%s: size parameter is only valid for VARIABLE_SIZE chip.\n", __func__);
1210 return 1;
1211 }
1212 msg_pdbg("Not emulating any flash chip.\n");
1213 /* Nothing else to do. */
1214 return 0;
1215 }
1216
1217 if (!strcmp(tmp, "M25P10.RES")) {
1218 data->emu_chip = EMULATE_ST_M25P10_RES;
1219 data->emu_chip_size = 128 * 1024;
1220 data->emu_max_byteprogram_size = 128;
1221 data->emu_max_aai_size = 0;
1222 data->emu_status_len = 1;
1223 data->emu_jedec_se_size = 0;
1224 data->emu_jedec_be_52_size = 0;
1225 data->emu_jedec_be_d8_size = 32 * 1024;
1226 data->emu_jedec_ce_60_size = 0;
1227 data->emu_jedec_ce_c7_size = data->emu_chip_size;
1228 msg_pdbg("Emulating ST M25P10.RES SPI flash chip (RES, page "
1229 "write)\n");
1230 }
1231 if (!strcmp(tmp, "SST25VF040.REMS")) {
1232 data->emu_chip = EMULATE_SST_SST25VF040_REMS;
1233 data->emu_chip_size = 512 * 1024;
1234 data->emu_max_byteprogram_size = 1;
1235 data->emu_max_aai_size = 0;
1236 data->emu_status_len = 1;
1237 data->emu_jedec_se_size = 4 * 1024;
1238 data->emu_jedec_be_52_size = 32 * 1024;
1239 data->emu_jedec_be_d8_size = 0;
1240 data->emu_jedec_ce_60_size = data->emu_chip_size;
1241 data->emu_jedec_ce_c7_size = 0;
1242 msg_pdbg("Emulating SST SST25VF040.REMS SPI flash chip (REMS, "
1243 "byte write)\n");
1244 }
1245 if (!strcmp(tmp, "SST25VF032B")) {
1246 data->emu_chip = EMULATE_SST_SST25VF032B;
1247 data->emu_chip_size = 4 * 1024 * 1024;
1248 data->emu_max_byteprogram_size = 1;
1249 data->emu_max_aai_size = 2;
1250 data->emu_status_len = 1;
1251 data->emu_jedec_se_size = 4 * 1024;
1252 data->emu_jedec_be_52_size = 32 * 1024;
1253 data->emu_jedec_be_d8_size = 64 * 1024;
1254 data->emu_jedec_ce_60_size = data->emu_chip_size;
1255 data->emu_jedec_ce_c7_size = data->emu_chip_size;
1256 msg_pdbg("Emulating SST SST25VF032B SPI flash chip (RDID, AAI "
1257 "write)\n");
1258 }
1259 if (!strcmp(tmp, "MX25L6436")) {
1260 data->emu_chip = EMULATE_MACRONIX_MX25L6436;
1261 data->emu_chip_size = 8 * 1024 * 1024;
1262 data->emu_max_byteprogram_size = 256;
1263 data->emu_max_aai_size = 0;
1264 data->emu_status_len = 1;
1265 data->emu_jedec_se_size = 4 * 1024;
1266 data->emu_jedec_be_52_size = 32 * 1024;
1267 data->emu_jedec_be_d8_size = 64 * 1024;
1268 data->emu_jedec_ce_60_size = data->emu_chip_size;
1269 data->emu_jedec_ce_c7_size = data->emu_chip_size;
1270 msg_pdbg("Emulating Macronix MX25L6436 SPI flash chip (RDID, "
1271 "SFDP)\n");
1272 }
1273 if (!strcmp(tmp, "W25Q128FV")) {
1274 data->emu_chip = EMULATE_WINBOND_W25Q128FV;
1275 data->emu_wrsr_ext2 = true;
1276 data->emu_chip_size = 16 * 1024 * 1024;
1277 data->emu_max_byteprogram_size = 256;
1278 data->emu_max_aai_size = 0;
1279 data->emu_status_len = 3;
1280 data->emu_jedec_se_size = 4 * 1024;
1281 data->emu_jedec_be_52_size = 32 * 1024;
1282 data->emu_jedec_be_d8_size = 64 * 1024;
1283 data->emu_jedec_ce_60_size = data->emu_chip_size;
1284 data->emu_jedec_ce_c7_size = data->emu_chip_size;
1285 msg_pdbg("Emulating Winbond W25Q128FV SPI flash chip (RDID)\n");
1286 }
1287 if (!strcmp(tmp, "S25FL128L")) {
1288 data->emu_chip = EMULATE_SPANSION_S25FL128L;
1289 data->emu_wrsr_ext2 = true;
1290 data->emu_wrsr_ext3 = true;
1291 data->emu_chip_size = 16 * 1024 * 1024;
1292 data->emu_max_byteprogram_size = 256;
1293 data->emu_max_aai_size = 0;
1294 data->emu_status_len = 3;
1295 data->emu_jedec_se_size = 4 * 1024;
1296 data->emu_jedec_be_52_size = 32 * 1024;
1297 data->emu_jedec_be_d8_size = 64 * 1024;
1298 data->emu_jedec_ce_60_size = data->emu_chip_size;
1299 data->emu_jedec_ce_c7_size = data->emu_chip_size;
1300 msg_pdbg("Emulating Spansion S25FL128L SPI flash chip (RES, RDID, WP)\n");
1301 }
1302
1303 /* The name of variable-size virtual chip. A 4 MiB flash example:
1304 * flashrom -p dummy:emulate=VARIABLE_SIZE,size=4194304
1305 */
1306 if (!strcmp(tmp, "VARIABLE_SIZE")) {
1307 if (size == -1) {
1308 msg_perr("%s: the size parameter is not given.\n", __func__);
1309 free(tmp);
1310 return 1;
1311 }
1312 data->emu_chip = EMULATE_VARIABLE_SIZE;
1313 data->emu_chip_size = size;
1314 msg_pdbg("Emulating generic SPI flash chip (size=%d bytes)\n",
1315 data->emu_chip_size);
1316 } else if (size != -1) {
1317 msg_perr("%s: size parameter is only valid for VARIABLE_SIZE chip.\n", __func__);
1318 free(tmp);
1319 return 1;
1320 }
1321
1322 if (data->emu_chip == EMULATE_NONE) {
1323 msg_perr("Invalid chip specified for emulation: %s\n", tmp);
1324 free(tmp);
1325 return 1;
1326 }
1327 free(tmp);
1328
1329 /* Should emulated flash erase to zero (yes/no)? */
1330 tmp = extract_programmer_param_str(cfg, "erase_to_zero");
1331 if (tmp) {
1332 if (data->emu_chip != EMULATE_VARIABLE_SIZE) {
1333 msg_perr("%s: erase_to_zero parameter is not valid for real chip.\n", __func__);
1334 free(tmp);
1335 return 1;
1336 }
1337 if (!strcmp(tmp, "yes")) {
1338 msg_pdbg("Emulated chip will erase to 0x00\n");
1339 data->erase_to_zero = true;
1340 } else if (!strcmp(tmp, "no")) {
1341 msg_pdbg("Emulated chip will erase to 0xff\n");
1342 } else {
1343 msg_perr("erase_to_zero can be \"yes\" or \"no\"\n");
1344 free(tmp);
1345 return 1;
1346 }
1347 }
1348 free(tmp);
1349
1350 status = extract_programmer_param_str(cfg, "spi_status");
1351 if (status) {
1352 unsigned int emu_status;
1353
1354 errno = 0;
1355 emu_status = strtoul(status, &endptr, 0);
1356 if (errno != 0 || status == endptr) {
1357 free(status);
1358 msg_perr("Error: initial status register specified, "
1359 "but the value could not be converted.\n");
1360 return 1;
1361 }
1362 free(status);
1363
1364 data->emu_status[0] = emu_status;
1365 data->emu_status[1] = emu_status >> 8;
1366 data->emu_status[2] = emu_status >> 16;
1367
1368 if (data->emu_status_len == 3) {
1369 msg_pdbg("Initial status registers:\n"
1370 "\tSR1 is set to 0x%02x\n"
1371 "\tSR2 is set to 0x%02x\n"
1372 "\tSR3 is set to 0x%02x\n",
1373 data->emu_status[0], data->emu_status[1], data->emu_status[2]);
1374 } else if (data->emu_status_len == 2) {
1375 msg_pdbg("Initial status registers:\n"
1376 "\tSR1 is set to 0x%02x\n"
1377 "\tSR2 is set to 0x%02x\n",
1378 data->emu_status[0], data->emu_status[1]);
1379 } else {
1380 msg_pdbg("Initial status register is set to 0x%02x.\n",
1381 data->emu_status[0]);
1382 }
1383 }
1384
1385 data->flashchip_contents = malloc(data->emu_chip_size);
1386 if (!data->flashchip_contents) {
1387 msg_perr("Out of memory!\n");
1388 return 1;
1389 }
1390
1391 return 0;
1392 }
1393
dummy_init(const struct programmer_cfg * cfg)1394 static int dummy_init(const struct programmer_cfg *cfg)
1395 {
1396 int ret = 0;
1397 struct stat image_stat;
1398
1399 struct emu_data *data = calloc(1, sizeof(*data));
1400 if (!data) {
1401 msg_perr("Out of memory!\n");
1402 return 1;
1403 }
1404 data->emu_chip = EMULATE_NONE;
1405 data->delay_ns = 0;
1406 data->spi_write_256_chunksize = 256;
1407
1408 msg_pspew("%s\n", __func__);
1409
1410 enum chipbustype dummy_buses_supported;
1411 if (init_data(cfg, data, &dummy_buses_supported)) {
1412 free(data);
1413 return 1;
1414 }
1415
1416 if (data->emu_chip == EMULATE_NONE) {
1417 msg_pdbg("Not emulating any flash chip.\n");
1418 /* Nothing else to do. */
1419 goto dummy_init_out;
1420 }
1421
1422 msg_pdbg("Filling fake flash chip with 0x%02x, size %i\n",
1423 data->erase_to_zero ? 0x00 : 0xff, data->emu_chip_size);
1424 memset(data->flashchip_contents, data->erase_to_zero ? 0x00 : 0xff, data->emu_chip_size);
1425
1426 /* Will be freed by shutdown function if necessary. */
1427 data->emu_persistent_image = extract_programmer_param_str(cfg, "image");
1428 if (!data->emu_persistent_image) {
1429 /* Nothing else to do. */
1430 goto dummy_init_out;
1431 }
1432 /* We will silently (in default verbosity) ignore the file if it does not exist (yet) or the size does
1433 * not match the emulated chip. */
1434 if (!stat(data->emu_persistent_image, &image_stat)) {
1435 msg_pdbg("Found persistent image %s, %jd B ",
1436 data->emu_persistent_image, (intmax_t)image_stat.st_size);
1437 if ((uintmax_t)image_stat.st_size == data->emu_chip_size) {
1438 msg_pdbg("matches.\n");
1439 msg_pdbg("Reading %s\n", data->emu_persistent_image);
1440 if (read_buf_from_file(data->flashchip_contents, data->emu_chip_size,
1441 data->emu_persistent_image)) {
1442 msg_perr("Unable to read %s\n", data->emu_persistent_image);
1443 free(data->emu_persistent_image);
1444 free(data->flashchip_contents);
1445 free(data);
1446 return 1;
1447 }
1448 } else {
1449 msg_pdbg("doesn't match.\n");
1450 }
1451 }
1452
1453 dummy_init_out:
1454 if (dummy_buses_supported & BUS_PROG) {
1455 data->refs_cnt++;
1456 ret |= register_opaque_master(&opaque_master_dummyflasher, data);
1457 }
1458 if ((dummy_buses_supported & BUS_NONSPI) && !ret) {
1459 data->refs_cnt++;
1460 ret |= register_par_master(&par_master_dummyflasher,
1461 dummy_buses_supported & BUS_NONSPI,
1462 data);
1463 }
1464 if ((dummy_buses_supported & BUS_SPI) && !ret) {
1465 data->refs_cnt++;
1466 ret |= register_spi_master(&spi_master_dummyflasher, data);
1467 }
1468
1469 return ret;
1470 }
1471
1472 const struct programmer_entry programmer_dummy = {
1473 .name = "dummy",
1474 .type = OTHER,
1475 /* FIXME */
1476 .devs.note = "Dummy device, does nothing and logs all accesses\n",
1477 .init = dummy_init,
1478 };
1479