Chromium Code Reviews| 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> |
| 37 #endif | 38 #endif |
| 38 | 39 |
| 39 #if EMULATE_CHIP | 40 #if EMULATE_CHIP |
| 41 /* The name of variable-size virtual chip. A 4MB flash example: | |
| 42 * flashrom -p dummy:emulate=VIRTUAL-4194304 | |
| 43 */ | |
| 44 #define VIRTUAL_CHIP_NAME "VIRTUAL" | |
| 45 #endif | |
| 46 | |
| 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_VIRTUAL, | |
|
Stefan Reinauer
2011/04/01 17:47:06
Since this emulates a Winbond, should it be called
Louis
2011/04/02 01:48:52
My initial attempt is to emulate any size of flash
dhendrix
2011/04/02 23:43:32
SGTM.
Louis
2011/04/07 02:28:14
Done.
| |
| 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; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 149 emu_max_byteprogram_size = 1; | 158 emu_max_byteprogram_size = 1; |
| 150 emu_max_aai_size = 2; | 159 emu_max_aai_size = 2; |
| 151 emu_jedec_se_size = 4 * 1024; | 160 emu_jedec_se_size = 4 * 1024; |
| 152 emu_jedec_be_52_size = 32 * 1024; | 161 emu_jedec_be_52_size = 32 * 1024; |
| 153 emu_jedec_be_d8_size = 64 * 1024; | 162 emu_jedec_be_d8_size = 64 * 1024; |
| 154 emu_jedec_ce_60_size = emu_chip_size; | 163 emu_jedec_ce_60_size = emu_chip_size; |
| 155 emu_jedec_ce_c7_size = emu_chip_size; | 164 emu_jedec_ce_c7_size = emu_chip_size; |
| 156 msg_pdbg("Emulating SST SST25VF032B SPI flash chip (RDID, AAI " | 165 msg_pdbg("Emulating SST SST25VF032B SPI flash chip (RDID, AAI " |
| 157 "write)\n"); | 166 "write)\n"); |
| 158 } | 167 } |
| 168 if (!strncmp(tmp, VIRTUAL_CHIP_NAME, strlen(VIRTUAL_CHIP_NAME))) { | |
| 169 char *size_str; | |
| 170 emu_chip = EMULATE_VIRTUAL; | |
| 171 strtok(tmp, "-"); // prefix is discarded. | |
| 172 if (NULL == (size_str = strtok(NULL, "-")) || !*size_str) { | |
| 173 msg_perr("Please specify flash size, " | |
| 174 "example: %s-65536\n", VIRTUAL_CHIP_NAME); | |
|
Stefan Reinauer
2011/04/01 17:47:06
Can we use KB instead of bytes here? 64, 128, 256,
Louis
2011/04/02 01:48:52
This is intentional for
-p dummy:VIRTUAL-`stat
dhendrix
2011/04/02 23:43:32
Good point... if desired, maybe we can add somethi
dhendrix
2011/04/02 23:43:32
I think it would be better to treat size (and pote
Louis
2011/04/07 02:28:14
Done.
Louis
2011/04/07 02:28:14
Done.
| |
| 175 free(tmp); | |
| 176 return 1; | |
| 177 } | |
| 178 emu_chip_size = atoi(size_str); | |
| 179 if (emu_chip_size & (emu_chip_size - 1)) { | |
| 180 msg_perr("Specified flash size is not power of 2.\n"); | |
| 181 free(tmp); | |
| 182 return 1; | |
| 183 } | |
| 184 emu_max_byteprogram_size = 256; | |
| 185 emu_max_aai_size = 0; | |
| 186 emu_jedec_se_size = 4 * 1024; | |
| 187 emu_jedec_be_52_size = 32 * 1024; | |
| 188 emu_jedec_be_d8_size = 64 * 1024; | |
| 189 emu_jedec_ce_60_size = emu_chip_size; | |
| 190 emu_jedec_ce_c7_size = emu_chip_size; | |
| 191 msg_pdbg("Emulating virtual SPI flash chip (size=%d bytes)\n", | |
| 192 emu_chip_size); | |
| 193 } | |
| 159 #endif | 194 #endif |
| 160 if (emu_chip == EMULATE_NONE) { | 195 if (emu_chip == EMULATE_NONE) { |
| 161 msg_perr("Invalid chip specified for emulation: %s\n", tmp); | 196 msg_perr("Invalid chip specified for emulation: %s\n", tmp); |
| 162 free(tmp); | 197 free(tmp); |
| 163 return 1; | 198 return 1; |
| 164 } | 199 } |
| 165 free(tmp); | 200 free(tmp); |
| 166 flashchip_contents = malloc(emu_chip_size); | 201 flashchip_contents = malloc(emu_chip_size); |
| 167 if (!flashchip_contents) { | 202 if (!flashchip_contents) { |
| 168 msg_perr("Out of memory!\n"); | 203 msg_perr("Out of memory!\n"); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 298 case JEDEC_REMS: | 333 case JEDEC_REMS: |
| 299 if (emu_chip != EMULATE_SST_SST25VF040_REMS) | 334 if (emu_chip != EMULATE_SST_SST25VF040_REMS) |
| 300 break; | 335 break; |
| 301 /* Respond with SST_SST25VF040_REMS. */ | 336 /* Respond with SST_SST25VF040_REMS. */ |
| 302 if (readcnt > 0) | 337 if (readcnt > 0) |
| 303 readarr[0] = 0xbf; | 338 readarr[0] = 0xbf; |
| 304 if (readcnt > 1) | 339 if (readcnt > 1) |
| 305 readarr[1] = 0x44; | 340 readarr[1] = 0x44; |
| 306 break; | 341 break; |
| 307 case JEDEC_RDID: | 342 case JEDEC_RDID: |
| 308 » » if (emu_chip != EMULATE_SST_SST25VF032B) | 343 » » if (emu_chip == EMULATE_SST_SST25VF032B) { |
| 309 » » » break; | 344 » » » /* Respond with SST_SST25VF032B. */ |
| 310 » » /* Respond with SST_SST25VF032B. */ | 345 » » » if (readcnt > 0) |
| 311 » » if (readcnt > 0) | 346 » » » » readarr[0] = 0xbf; |
| 312 » » » readarr[0] = 0xbf; | 347 » » » if (readcnt > 1) |
| 313 » » if (readcnt > 1) | 348 » » » » readarr[1] = 0x25; |
| 314 » » » readarr[1] = 0x25; | 349 » » » if (readcnt > 2) |
| 315 » » if (readcnt > 2) | 350 » » » » readarr[2] = 0x4a; |
| 316 » » » readarr[2] = 0x4a; | 351 » » } else if (emu_chip == EMULATE_VIRTUAL) { |
| 352 » » » /* Winbond W25X series flashes are easy to map. | |
| 353 » » » * 128KB -- ID: 0x3011 | |
| 354 » » » * 256KB -- ID: 0x3012 | |
| 355 » » » * : : | |
| 356 » » » * 8192KB -- ID: 0x3017 | |
| 357 » » » * TODO: map more chips in future for other sizes. | |
|
Stefan Reinauer
2011/04/01 17:47:06
Should we make sure we only pass sizes supported b
Louis
2011/04/02 01:48:52
Will refine this to support any size.
On 2011/04/
| |
| 358 » » » */ | |
| 359 » » » uint16_t dev_id = WINBOND_NEX_W25X10; | |
| 360 » » » int size = emu_chip_size >> 17; | |
| 361 » » » for (; size >>= 1; dev_id++); | |
| 362 » » » if (readcnt > 0) readarr[0] = WINBOND_NEX_ID; | |
| 363 » » » if (readcnt > 1) readarr[1] = dev_id >> 8; | |
| 364 » » » if (readcnt > 2) readarr[2] = dev_id & 0xff; | |
| 365 » » } | |
| 317 break; | 366 break; |
| 318 case JEDEC_RDSR: | 367 case JEDEC_RDSR: |
| 319 memset(readarr, 0, readcnt); | 368 memset(readarr, 0, readcnt); |
| 320 if (aai_active) | 369 if (aai_active) |
| 321 memset(readarr, 1 << 6, readcnt); | 370 memset(readarr, 1 << 6, readcnt); |
| 322 break; | 371 break; |
| 323 case JEDEC_READ: | 372 case JEDEC_READ: |
| 324 offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; | 373 offs = writearr[1] << 16 | writearr[2] << 8 | writearr[3]; |
| 325 /* Truncate to emu_chip_size. */ | 374 /* Truncate to emu_chip_size. */ |
| 326 offs %= emu_chip_size; | 375 offs %= emu_chip_size; |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 488 for (i = 0; i < writecnt; i++) | 537 for (i = 0; i < writecnt; i++) |
| 489 msg_pspew(" 0x%02x", writearr[i]); | 538 msg_pspew(" 0x%02x", writearr[i]); |
| 490 | 539 |
| 491 /* Response for unknown commands and missing chip is 0xff. */ | 540 /* Response for unknown commands and missing chip is 0xff. */ |
| 492 memset(readarr, 0xff, readcnt); | 541 memset(readarr, 0xff, readcnt); |
| 493 #if EMULATE_SPI_CHIP | 542 #if EMULATE_SPI_CHIP |
| 494 switch (emu_chip) { | 543 switch (emu_chip) { |
| 495 case EMULATE_ST_M25P10_RES: | 544 case EMULATE_ST_M25P10_RES: |
| 496 case EMULATE_SST_SST25VF040_REMS: | 545 case EMULATE_SST_SST25VF040_REMS: |
| 497 case EMULATE_SST_SST25VF032B: | 546 case EMULATE_SST_SST25VF032B: |
| 547 case EMULATE_VIRTUAL: | |
| 498 if (emulate_spi_chip_response(writecnt, readcnt, writearr, | 548 if (emulate_spi_chip_response(writecnt, readcnt, writearr, |
| 499 readarr)) { | 549 readarr)) { |
| 500 msg_perr("Invalid command sent to flash chip!\n"); | 550 msg_perr("Invalid command sent to flash chip!\n"); |
| 501 return 1; | 551 return 1; |
| 502 } | 552 } |
| 503 break; | 553 break; |
| 504 default: | 554 default: |
| 505 break; | 555 break; |
| 506 } | 556 } |
| 507 #endif | 557 #endif |
| 508 msg_pspew(" reading %u bytes:", readcnt); | 558 msg_pspew(" reading %u bytes:", readcnt); |
| 509 for (i = 0; i < readcnt; i++) { | 559 for (i = 0; i < readcnt; i++) { |
| 510 msg_pspew(" 0x%02x", readarr[i]); | 560 msg_pspew(" 0x%02x", readarr[i]); |
| 511 } | 561 } |
| 512 msg_pspew("\n"); | 562 msg_pspew("\n"); |
| 513 return 0; | 563 return 0; |
| 514 } | 564 } |
| 515 | 565 |
| 516 int dummy_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len) | 566 int dummy_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len) |
| 517 { | 567 { |
| 518 /* Maximum read length is unlimited, use 64kB. */ | 568 /* Maximum read length is unlimited, use 64kB. */ |
| 519 return spi_read_chunked(flash, buf, start, len, 64 * 1024); | 569 return spi_read_chunked(flash, buf, start, len, 64 * 1024); |
| 520 } | 570 } |
| 521 | 571 |
| 522 int dummy_spi_write_256(struct flashchip *flash, uint8_t *buf, int start, int le n) | 572 int dummy_spi_write_256(struct flashchip *flash, uint8_t *buf, int start, int le n) |
| 523 { | 573 { |
| 524 return spi_write_chunked(flash, buf, start, len, | 574 return spi_write_chunked(flash, buf, start, len, |
| 525 spi_write_256_chunksize); | 575 spi_write_256_chunksize); |
| 526 } | 576 } |
| OLD | NEW |