OLD | NEW |
1 /* | 1 /* |
2 * This file is part of the flashrom project. | 2 * This file is part of the flashrom project. |
3 * | 3 * |
4 * Copyright (C) 2009,2010 Carl-Daniel Hailfinger | 4 * Copyright (C) 2009,2010 Carl-Daniel Hailfinger |
5 * | 5 * |
6 * This program is free software; you can redistribute it and/or modify | 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 | 7 * it under the terms of the GNU General Public License as published by |
8 * the Free Software Foundation; version 2 of the License. | 8 * the Free Software Foundation; version 2 of the License. |
9 * | 9 * |
10 * This program is distributed in the hope that it will be useful, | 10 * This program is distributed in the hope that it will be useful, |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 * GNU General Public License for more details. | 13 * GNU General Public License for more details. |
14 * | 14 * |
15 * You should have received a copy of the GNU General Public License | 15 * You should have received a copy of the GNU General Public License |
16 * along with this program; if not, write to the Free Software | 16 * along with this program; if not, write to the Free Software |
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
18 */ | 18 */ |
19 | 19 |
20 #include <string.h> | 20 #include <string.h> |
21 #include <stdlib.h> | 21 #include <stdlib.h> |
22 #include "flash.h" | 22 #include "flash.h" |
23 #include "chipdrivers.h" | 23 #include "chipdrivers.h" |
24 #include "programmer.h" | 24 #include "programmer.h" |
| 25 #include "flashchips.h" |
25 | 26 |
26 /* Remove the #define below if you don't want SPI flash chip emulation. */ | 27 /* Remove the #define below if you don't want SPI flash chip emulation. */ |
27 #define EMULATE_SPI_CHIP 1 | 28 #define EMULATE_SPI_CHIP 1 |
28 | 29 |
29 #if EMULATE_SPI_CHIP | 30 #if EMULATE_SPI_CHIP |
30 #define EMULATE_CHIP 1 | 31 #define EMULATE_CHIP 1 |
31 #include "spi.h" | 32 #include "spi.h" |
32 #endif | 33 #endif |
33 | 34 |
34 #if EMULATE_CHIP | 35 #if EMULATE_CHIP |
35 #include <sys/types.h> | 36 #include <sys/types.h> |
36 #include <sys/stat.h> | 37 #include <sys/stat.h> |
| 38 |
| 39 #if EMULATE_SPI_CHIP |
| 40 /* The name of variable-size virtual chip. A 4MB flash example: |
| 41 * flashrom -p dummy:emulate=VARIABLE_SIZE,size=4194304 |
| 42 */ |
| 43 #define VARIABLE_SIZE_CHIP_NAME "VARIABLE_SIZE" |
| 44 #endif |
37 #endif | 45 #endif |
38 | 46 |
39 #if EMULATE_CHIP | 47 #if EMULATE_CHIP |
40 static uint8_t *flashchip_contents = NULL; | 48 static uint8_t *flashchip_contents = NULL; |
41 enum emu_chip { | 49 enum emu_chip { |
42 EMULATE_NONE, | 50 EMULATE_NONE, |
43 EMULATE_ST_M25P10_RES, | 51 EMULATE_ST_M25P10_RES, |
44 EMULATE_SST_SST25VF040_REMS, | 52 EMULATE_SST_SST25VF040_REMS, |
45 EMULATE_SST_SST25VF032B, | 53 EMULATE_SST_SST25VF032B, |
| 54 EMULATE_VARIABLE_SIZE, |
46 }; | 55 }; |
47 static enum emu_chip emu_chip = EMULATE_NONE; | 56 static enum emu_chip emu_chip = EMULATE_NONE; |
48 static char *emu_persistent_image = NULL; | 57 static char *emu_persistent_image = NULL; |
49 static int emu_chip_size = 0; | 58 static int emu_chip_size = 0; |
50 #if EMULATE_SPI_CHIP | 59 #if EMULATE_SPI_CHIP |
51 static int emu_max_byteprogram_size = 0; | 60 static int emu_max_byteprogram_size = 0; |
52 static int emu_max_aai_size = 0; | 61 static int emu_max_aai_size = 0; |
53 static int emu_jedec_se_size = 0; | 62 static int emu_jedec_se_size = 0; |
54 static int emu_jedec_be_52_size = 0; | 63 static int emu_jedec_be_52_size = 0; |
55 static int emu_jedec_be_d8_size = 0; | 64 static int emu_jedec_be_d8_size = 0; |
56 static int emu_jedec_ce_60_size = 0; | 65 static int emu_jedec_ce_60_size = 0; |
57 static int emu_jedec_ce_c7_size = 0; | 66 static int emu_jedec_ce_c7_size = 0; |
58 #endif | 67 #endif |
59 #endif | 68 #endif |
60 | 69 |
61 static int spi_write_256_chunksize = 256; | 70 static int spi_write_256_chunksize = 256; |
62 | 71 |
63 int dummy_init(void) | 72 int dummy_init(void) |
64 { | 73 { |
65 char *bustext = NULL; | 74 char *bustext = NULL; |
66 char *tmp = NULL; | 75 char *tmp = NULL; |
67 #if EMULATE_CHIP | 76 #if EMULATE_CHIP |
68 struct stat image_stat; | 77 struct stat image_stat; |
| 78 #if EMULATE_SPI_CHIP |
| 79 int size = -1; /* size for generic chip */ |
| 80 #endif |
69 #endif | 81 #endif |
70 | 82 |
71 msg_pspew("%s\n", __func__); | 83 msg_pspew("%s\n", __func__); |
72 | 84 |
73 bustext = extract_programmer_param("bus"); | 85 bustext = extract_programmer_param("bus"); |
74 msg_pdbg("Requested buses are: %s\n", bustext ? bustext : "default"); | 86 msg_pdbg("Requested buses are: %s\n", bustext ? bustext : "default"); |
75 if (!bustext) | 87 if (!bustext) |
76 bustext = strdup("parallel+lpc+fwh+spi"); | 88 bustext = strdup("parallel+lpc+fwh+spi"); |
77 /* Convert the parameters to lowercase. */ | 89 /* Convert the parameters to lowercase. */ |
78 tolower_string(bustext); | 90 tolower_string(bustext); |
(...skipping 24 matching lines...) Expand all Loading... |
103 if (tmp) { | 115 if (tmp) { |
104 spi_write_256_chunksize = atoi(tmp); | 116 spi_write_256_chunksize = atoi(tmp); |
105 free(tmp); | 117 free(tmp); |
106 if (spi_write_256_chunksize < 1) { | 118 if (spi_write_256_chunksize < 1) { |
107 msg_perr("invalid spi_write_256_chunksize\n"); | 119 msg_perr("invalid spi_write_256_chunksize\n"); |
108 return 1; | 120 return 1; |
109 } | 121 } |
110 } | 122 } |
111 | 123 |
112 #if EMULATE_CHIP | 124 #if EMULATE_CHIP |
| 125 #if EMULATE_SPI_CHIP |
| 126 tmp = extract_programmer_param("size"); |
| 127 if (tmp) { |
| 128 int multiplier = 1; |
| 129 if (strlen(tmp)) { |
| 130 int remove_last_char = 1; |
| 131 switch (tmp[strlen(tmp) - 1]) { |
| 132 case 'k': case 'K': |
| 133 multiplier = 1024; |
| 134 break; |
| 135 case 'm': case 'M': |
| 136 multiplier = 1024 * 1024; |
| 137 break; |
| 138 default: |
| 139 remove_last_char = 0; |
| 140 break; |
| 141 } |
| 142 if (remove_last_char) tmp[strlen(tmp) - 1] = '\0'; |
| 143 } |
| 144 size = atoi(tmp) * multiplier; |
| 145 } |
| 146 #endif |
| 147 |
113 tmp = extract_programmer_param("emulate"); | 148 tmp = extract_programmer_param("emulate"); |
114 if (!tmp) { | 149 if (!tmp) { |
115 msg_pdbg("Not emulating any flash chip.\n"); | 150 msg_pdbg("Not emulating any flash chip.\n"); |
116 /* Nothing else to do. */ | 151 /* Nothing else to do. */ |
117 return 0; | 152 return 0; |
118 } | 153 } |
119 #if EMULATE_SPI_CHIP | 154 #if EMULATE_SPI_CHIP |
120 if (!strcmp(tmp, "M25P10.RES")) { | 155 if (!strcmp(tmp, "M25P10.RES")) { |
121 emu_chip = EMULATE_ST_M25P10_RES; | 156 emu_chip = EMULATE_ST_M25P10_RES; |
122 emu_chip_size = 128 * 1024; | 157 emu_chip_size = 128 * 1024; |
(...skipping 26 matching lines...) Expand all Loading... |
149 emu_max_byteprogram_size = 1; | 184 emu_max_byteprogram_size = 1; |
150 emu_max_aai_size = 2; | 185 emu_max_aai_size = 2; |
151 emu_jedec_se_size = 4 * 1024; | 186 emu_jedec_se_size = 4 * 1024; |
152 emu_jedec_be_52_size = 32 * 1024; | 187 emu_jedec_be_52_size = 32 * 1024; |
153 emu_jedec_be_d8_size = 64 * 1024; | 188 emu_jedec_be_d8_size = 64 * 1024; |
154 emu_jedec_ce_60_size = emu_chip_size; | 189 emu_jedec_ce_60_size = emu_chip_size; |
155 emu_jedec_ce_c7_size = emu_chip_size; | 190 emu_jedec_ce_c7_size = emu_chip_size; |
156 msg_pdbg("Emulating SST SST25VF032B SPI flash chip (RDID, AAI " | 191 msg_pdbg("Emulating SST SST25VF032B SPI flash chip (RDID, AAI " |
157 "write)\n"); | 192 "write)\n"); |
158 } | 193 } |
| 194 if (!strncmp(tmp, VARIABLE_SIZE_CHIP_NAME, |
| 195 strlen(VARIABLE_SIZE_CHIP_NAME))) { |
| 196 if (size == -1) { |
| 197 msg_perr("%s: the size parameter is not given.\n", |
| 198 __func__); |
| 199 free(tmp); |
| 200 return 1; |
| 201 } |
| 202 emu_chip = EMULATE_VARIABLE_SIZE; |
| 203 emu_chip_size = size; |
| 204 emu_max_byteprogram_size = 256; |
| 205 emu_max_aai_size = 0; |
| 206 emu_jedec_se_size = 4 * 1024; |
| 207 emu_jedec_be_52_size = 32 * 1024; |
| 208 emu_jedec_be_d8_size = 64 * 1024; |
| 209 emu_jedec_ce_60_size = emu_chip_size; |
| 210 emu_jedec_ce_c7_size = emu_chip_size; |
| 211 msg_pdbg("Emulating generic SPI flash chip (size=%d bytes)\n", |
| 212 emu_chip_size); |
| 213 } |
159 #endif | 214 #endif |
160 if (emu_chip == EMULATE_NONE) { | 215 if (emu_chip == EMULATE_NONE) { |
161 msg_perr("Invalid chip specified for emulation: %s\n", tmp); | 216 msg_perr("Invalid chip specified for emulation: %s\n", tmp); |
162 free(tmp); | 217 free(tmp); |
163 return 1; | 218 return 1; |
164 } | 219 } |
165 free(tmp); | 220 free(tmp); |
166 flashchip_contents = malloc(emu_chip_size); | 221 flashchip_contents = malloc(emu_chip_size); |
167 if (!flashchip_contents) { | 222 if (!flashchip_contents) { |
168 msg_perr("Out of memory!\n"); | 223 msg_perr("Out of memory!\n"); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 case JEDEC_REMS: | 353 case JEDEC_REMS: |
299 if (emu_chip != EMULATE_SST_SST25VF040_REMS) | 354 if (emu_chip != EMULATE_SST_SST25VF040_REMS) |
300 break; | 355 break; |
301 /* Respond with SST_SST25VF040_REMS. */ | 356 /* Respond with SST_SST25VF040_REMS. */ |
302 if (readcnt > 0) | 357 if (readcnt > 0) |
303 readarr[0] = 0xbf; | 358 readarr[0] = 0xbf; |
304 if (readcnt > 1) | 359 if (readcnt > 1) |
305 readarr[1] = 0x44; | 360 readarr[1] = 0x44; |
306 break; | 361 break; |
307 case JEDEC_RDID: | 362 case JEDEC_RDID: |
308 » » if (emu_chip != EMULATE_SST_SST25VF032B) | 363 » » if (emu_chip == EMULATE_SST_SST25VF032B) { |
309 » » » break; | 364 » » » /* Respond with SST_SST25VF032B. */ |
310 » » /* Respond with SST_SST25VF032B. */ | 365 » » » if (readcnt > 0) |
311 » » if (readcnt > 0) | 366 » » » » readarr[0] = 0xbf; |
312 » » » readarr[0] = 0xbf; | 367 » » » if (readcnt > 1) |
313 » » if (readcnt > 1) | 368 » » » » readarr[1] = 0x25; |
314 » » » readarr[1] = 0x25; | 369 » » » if (readcnt > 2) |
315 » » if (readcnt > 2) | 370 » » » » readarr[2] = 0x4a; |
316 » » » readarr[2] = 0x4a; | 371 » » } else if (emu_chip == EMULATE_VARIABLE_SIZE) { |
| 372 » » » const uint16_t man_id = VARIABLE_SIZE_MANUF_ID; |
| 373 » » » const uint16_t dev_id = VARIABLE_SIZE_DEVICE_ID; |
| 374 » » » if (readcnt > 0) readarr[0] = man_id >> 8; |
| 375 » » » if (readcnt > 1) readarr[1] = man_id & 0xff; |
| 376 » » » if (readcnt > 2) readarr[2] = dev_id >> 8; |
| 377 » » » if (readcnt > 3) readarr[3] = dev_id & 0xff; |
| 378 » » } |
317 break; | 379 break; |
318 case JEDEC_RDSR: | 380 case JEDEC_RDSR: |
319 memset(readarr, 0, readcnt); | 381 memset(readarr, 0, readcnt); |
320 if (aai_active) | 382 if (aai_active) |
321 memset(readarr, 1 << 6, readcnt); | 383 memset(readarr, 1 << 6, readcnt); |
322 break; | 384 break; |
323 case JEDEC_READ: | 385 case JEDEC_READ: |
324 offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; | 386 offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; |
325 /* Truncate to emu_chip_size. */ | 387 /* Truncate to emu_chip_size. */ |
326 offs %= emu_chip_size; | 388 offs %= emu_chip_size; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 for (i = 0; i < writecnt; i++) | 550 for (i = 0; i < writecnt; i++) |
489 msg_pspew(" 0x%02x", writearr[i]); | 551 msg_pspew(" 0x%02x", writearr[i]); |
490 | 552 |
491 /* Response for unknown commands and missing chip is 0xff. */ | 553 /* Response for unknown commands and missing chip is 0xff. */ |
492 memset(readarr, 0xff, readcnt); | 554 memset(readarr, 0xff, readcnt); |
493 #if EMULATE_SPI_CHIP | 555 #if EMULATE_SPI_CHIP |
494 switch (emu_chip) { | 556 switch (emu_chip) { |
495 case EMULATE_ST_M25P10_RES: | 557 case EMULATE_ST_M25P10_RES: |
496 case EMULATE_SST_SST25VF040_REMS: | 558 case EMULATE_SST_SST25VF040_REMS: |
497 case EMULATE_SST_SST25VF032B: | 559 case EMULATE_SST_SST25VF032B: |
| 560 case EMULATE_VARIABLE_SIZE: |
498 if (emulate_spi_chip_response(writecnt, readcnt, writearr, | 561 if (emulate_spi_chip_response(writecnt, readcnt, writearr, |
499 readarr)) { | 562 readarr)) { |
500 msg_perr("Invalid command sent to flash chip!\n"); | 563 msg_perr("Invalid command sent to flash chip!\n"); |
501 return 1; | 564 return 1; |
502 } | 565 } |
503 break; | 566 break; |
504 default: | 567 default: |
505 break; | 568 break; |
506 } | 569 } |
507 #endif | 570 #endif |
508 msg_pspew(" reading %u bytes:", readcnt); | 571 msg_pspew(" reading %u bytes:", readcnt); |
509 for (i = 0; i < readcnt; i++) { | 572 for (i = 0; i < readcnt; i++) { |
510 msg_pspew(" 0x%02x", readarr[i]); | 573 msg_pspew(" 0x%02x", readarr[i]); |
511 } | 574 } |
512 msg_pspew("\n"); | 575 msg_pspew("\n"); |
513 return 0; | 576 return 0; |
514 } | 577 } |
515 | 578 |
516 int dummy_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len) | 579 int dummy_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len) |
517 { | 580 { |
518 /* Maximum read length is unlimited, use 64kB. */ | 581 /* Maximum read length is unlimited, use 64kB. */ |
519 return spi_read_chunked(flash, buf, start, len, 64 * 1024); | 582 return spi_read_chunked(flash, buf, start, len, 64 * 1024); |
520 } | 583 } |
521 | 584 |
522 int dummy_spi_write_256(struct flashchip *flash, uint8_t *buf, int start, int le
n) | 585 int dummy_spi_write_256(struct flashchip *flash, uint8_t *buf, int start, int le
n) |
523 { | 586 { |
524 return spi_write_chunked(flash, buf, start, len, | 587 return spi_write_chunked(flash, buf, start, len, |
525 spi_write_256_chunksize); | 588 spi_write_256_chunksize); |
526 } | 589 } |
| 590 |
| 591 #if EMULATE_CHIP && EMULATE_SPI_CHIP |
| 592 int probe_variable_size(struct flashchip *flash) |
| 593 { |
| 594 int i; |
| 595 |
| 596 /* Skip the probing if we don't emulate this chip. */ |
| 597 if (emu_chip != EMULATE_VARIABLE_SIZE) |
| 598 return 0; |
| 599 |
| 600 /* |
| 601 * This will break if one day flashchip becomes read-only. |
| 602 * Once that happens, we need to have special hacks in functions: |
| 603 * |
| 604 * erase_and_write_flash() in flashrom.c |
| 605 * read_flash_to_file() |
| 606 * handle_romentries() |
| 607 * ... |
| 608 * |
| 609 * Search "total_size * 1024" in code. |
| 610 */ |
| 611 if (emu_chip_size % 1024) |
| 612 msg_perr("%s: emu_chip_size is not multipler of 1024.\n", |
| 613 __func__); |
| 614 flash->total_size = emu_chip_size / 1024; |
| 615 msg_cdbg("%s: set flash->total_size to %dK bytes.\n", __func__, |
| 616 flash->total_size); |
| 617 |
| 618 /* Update eraser count */ |
| 619 for (i = 0; i < NUM_ERASEFUNCTIONS; i++) { |
| 620 struct block_eraser *eraser = &flash->block_erasers[i]; |
| 621 if (eraser->block_erase == NULL) |
| 622 break; |
| 623 |
| 624 eraser->eraseblocks[0].count = emu_chip_size / |
| 625 eraser->eraseblocks[0].size; |
| 626 msg_cdbg("%s: eraser.size=%d, .count=%d\n", |
| 627 __func__, eraser->eraseblocks[0].size, |
| 628 eraser->eraseblocks[0].count); |
| 629 } |
| 630 |
| 631 return 1; |
| 632 } |
| 633 #endif |
OLD | NEW |