fwhtool.c
(plain)
1 /* 2 * Copyright (c) 2024 Amelia Zabardast Ziabari 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <string.h> 33 #include <fcntl.h> 34 #include <time.h> 35 #include <sys/time.h> 36 37 extern char *optarg; 38 extern int optind; 39 40 /* BOARD SELECTION --------------------------------------------------------- */ 41 42 43 #define MOD_OUT 0 44 #define MOD_IN 1 45 #if defined(BOARD_RASPI) 46 #include <wiringPi.h> 47 /* 48 * These pin definitions are BCM-logical (the "BCM" column in wiringPi's 49 * "gpio readall" command). They have been chosen to maintain compatibility 50 * with previous attempts to solve this problem, in order to reduce infuriating 51 * experiences with re-wiring breadboards for the user. 52 * 53 * They also have the nice property of being compatible with boards that use a 54 * reduced GPIO connector, as well as avoiding the SPI-related GPIO pins (which 55 * you may want to keep untouched if you also use your Raspberry Pi as an SPI 56 * programmer). 57 */ 58 #define PIN_RSET 17 59 #define PIN_LAD0 22 60 #define PIN_LAD1 23 61 #define PIN_LAD2 24 62 #define PIN_LAD3 25 63 #define PIN_LFRM 27 64 #define PIN_LCLK 18 65 #define PIN_WREN 4 66 #define PSETUP wiringPiSetupGpio 67 #define OUTP(p, s) digitalWrite(p, (s) ? HIGH : LOW) 68 #define INP(p) digitalRead(p) 69 #define MODEP(p, m) pinMode(p, (m) ? INPUT : OUTPUT) 70 #elif defined(BOARD_DUMMY) 71 /* Only useful with the dummy programmer. */ 72 static void dummySetup() {} 73 #define PSETUP dummySetup 74 #define OUTP(p, s) 75 #define INP(p) 1 76 #define MODEP(p, m) 77 #else 78 #error "no SBC board specification selected!" 79 #endif 80 81 /* CHIP AND FUNCTIONAL DECLARATION ----------------------------------------- */ 82 83 84 typedef unsigned long long ndelay_t; 85 86 #define TMMIX(a, t) (ndelay_t)((a) * (double)(t)) 87 #define USEC(t) TMMIX(1000.0, t) 88 #define MSEC(t) TMMIX(1000000.0, t) 89 #define SEC(t) TMMIX(1000000000.0, t) 90 #define STABILIZE USEC(1) 91 #define DEFAULT_LAD .lad = STABILIZE 92 93 typedef struct dself { 94 char *name; 95 enum { 96 BUS_FWH, /* Firmware Hub Transfers */ 97 BUS_LPC, /* LPC Transfers */ 98 BUS_LPC_ISA /* LPC Transfers with ISA Compatibility */ 99 } type; 100 enum { 101 NEEDS_MISC_BLOCK_UNLOCK = 0x0001, 102 NEEDS_WE_ALWAYS_ON = 0x0002 103 } quirks; 104 enum { 105 TEST_WIP, /* Not even finished */ 106 TEST_NONE, /* Untested */ 107 TEST_I, /* Identifies */ 108 TEST_IR, /* Identifies & Reads */ 109 TEST_IRW /* Identifies, Reads & Writes */ 110 } status; 111 unsigned char ven_id; 112 unsigned char dev_id; 113 unsigned long register_base; 114 unsigned long memory_base; 115 unsigned long bsz; /* block */ 116 unsigned long ssz; /* sector */ 117 unsigned long csz; /* chip */ 118 119 struct { 120 unsigned long size; 121 enum { 122 XFER_N, /* terminator value (must be zero) */ 123 XFER_RW, 124 XFER_R, 125 XFER_W 126 } type; 127 } xfers[8]; /* valid "IMSIZE" field sizes. */ 128 129 void (*s_erase)(struct dself *, unsigned long); 130 void (*b_erase)(struct dself *, unsigned long); 131 void (*c_erase)(struct dself *); 132 int (*erased)(struct dself *); 133 134 void (*write)(struct dself *, unsigned long, size_t, char *); 135 void (*read)(struct dself *, unsigned long, size_t, char *); 136 137 int (*probe)(struct dself *); 138 139 struct { 140 ndelay_t lad; 141 ndelay_t program; 142 ndelay_t s_erase; 143 ndelay_t b_erase; 144 ndelay_t c_erase; 145 ndelay_t toggle_bit_delay; 146 ndelay_t cycle; 147 ndelay_t regset; 148 } delay; 149 } mdev_t; 150 151 /* "Standardized" access functions for various types of chips. */ 152 void jedec_block_erase(mdev_t *, unsigned long); 153 void jedec_chip_erase(mdev_t *); 154 void jedec_sector_erase(mdev_t *, unsigned long); 155 void jedec_program(mdev_t *, unsigned long, size_t, char *); 156 void jedec_read(mdev_t *, unsigned long, size_t, char *); 157 int jedec_chip_identify(mdev_t *); 158 int toggle_d6_erased(mdev_t *d); 159 160 /* Dummy functions */ 161 void dummy_sector_erase(mdev_t *, unsigned long); 162 void dummy_block_erase(mdev_t *, unsigned long); 163 void dummy_chip_erase(mdev_t *); 164 void dummy_program(mdev_t *, unsigned long, size_t, char *); 165 void dummy_read(mdev_t *, unsigned long, size_t, char *); 166 167 /* SST "Mini-Command" functions */ 168 int sstmc_chip_identify(mdev_t *d); 169 170 mdev_t devicetab[] = { 171 { 172 .name = "dummy", 173 .status = TEST_IRW, 174 .bsz = 0x10000, 175 .ssz = 0x1000, 176 .csz = 0x100000, 177 .xfers = { { 128, XFER_RW } }, 178 .s_erase = dummy_sector_erase, 179 .b_erase = dummy_block_erase, 180 .c_erase = dummy_chip_erase, 181 .erased = NULL, 182 .write = dummy_program, 183 .read = dummy_read, 184 .probe = NULL, 185 .delay = {0} 186 }, 187 { 188 /* See "Design Considerations" in the datasheet. */ 189 .name = "SST49LF008A", 190 .type = BUS_FWH, 191 .quirks = NEEDS_MISC_BLOCK_UNLOCK, 192 .status = TEST_IRW, 193 .ven_id = 0xbf, 194 .dev_id = 0x5a, 195 .register_base = 0xff800000, 196 .memory_base = 0xffc00000, 197 .bsz = 0x10000, 198 .ssz = 0x1000, 199 .csz = 0x100000, 200 .s_erase = jedec_sector_erase, 201 .b_erase = jedec_block_erase, 202 .c_erase = NULL, 203 .erased = toggle_d6_erased, 204 .write = jedec_program, 205 .read = jedec_read, 206 .probe = jedec_chip_identify, 207 .delay = { 208 DEFAULT_LAD 209 } 210 }, 211 { 212 /* Similar to SST49LF008A, but not FWH and smaller. */ 213 .name = "SST49LF020", 214 .type = BUS_LPC_ISA, 215 .status = TEST_NONE, 216 .ven_id = 0xbf, 217 .dev_id = 0x61, 218 .register_base = 0xff800000, 219 .memory_base = 0xffc00000, 220 .bsz = 0x4000, 221 .ssz = 0x1000, 222 .csz = 0x40000, 223 .s_erase = jedec_sector_erase, 224 .b_erase = jedec_block_erase, 225 .c_erase = NULL, 226 .erased = toggle_d6_erased, 227 .write = jedec_program, 228 .read = jedec_read, 229 .probe = jedec_chip_identify, 230 .delay = { 231 DEFAULT_LAD 232 } 233 }, 234 { 235 /* Special considerations for this chip to save you the pain I 236 * went through: 237 * - Vpp must be 3.3V. (!) 238 * - All Vdd and Vss pins must be connected. 239 * - Use a high frequency/AC 0.1uF ceramic capacitor between 240 * Vdd and Vss no further than 1cm away from Vdd. 241 */ 242 .name = "W39V080FA", 243 .type = BUS_FWH, 244 .quirks = NEEDS_MISC_BLOCK_UNLOCK | NEEDS_WE_ALWAYS_ON, 245 .status = TEST_IRW, 246 .ven_id = 0xda, 247 .dev_id = 0xd3, 248 .register_base = 0xff800000, 249 .memory_base = 0xffc00000, 250 .bsz = 0x10000, 251 .ssz = 0x10000, 252 .csz = 0x100000, 253 .s_erase = jedec_sector_erase, 254 .b_erase = NULL, 255 .c_erase = NULL, 256 .erased = toggle_d6_erased, 257 .write = jedec_program, 258 .read = jedec_read, 259 .probe = jedec_chip_identify, 260 .delay = { 261 DEFAULT_LAD, 262 .toggle_bit_delay = MSEC(8) 263 } 264 }, 265 { 266 /* TODO: Finish this chip (does not identify, needs special 267 * commands). 268 */ 269 .name = "SST49LF016C", 270 .type = BUS_FWH, 271 .quirks = 0, 272 .status = TEST_WIP, 273 .ven_id = 0xbf, 274 .dev_id = 0x5c, 275 .register_base = 0xff800000, 276 .memory_base = 0xffc00000, 277 .bsz = 0x10000, 278 .ssz = 0x1000, 279 .csz = 0x200000, 280 .xfers = { 281 { 2 , XFER_RW }, { 2 , XFER_RW }, 282 { 4 , XFER_RW }, { 4 , XFER_RW }, 283 { 16 , XFER_R }, 284 { 128, XFER_R } 285 }, 286 .s_erase = NULL, 287 .b_erase = NULL, 288 .c_erase = NULL, 289 .erased = NULL, 290 .write = NULL, 291 .read = NULL, 292 .probe = sstmc_chip_identify, 293 .delay = { 294 DEFAULT_LAD 295 } 296 } 297 }; 298 int devices = sizeof(devicetab) / sizeof(devicetab[0]); 299 300 /* DISPLAY AND DEBUG HELPERS ----------------------------------------------- */ 301 302 303 #ifndef DEBUG_LEVEL 304 #define DEBUG_LEVEL 0 305 #endif 306 static int dbglvl = DEBUG_LEVEL; 307 308 #define ABORT(...) do { fprintf(stderr, __VA_ARGS__); safe_exit(); } while (0) 309 #define DEBUG(...) do { fprintf(stderr, __VA_ARGS__); } while (0) 310 #define ASSERT(cond) do { if (!(cond)) \ 311 ABORT("%d: assertion failed: " #cond "\n", __LINE__); \ 312 } while (0) 313 #define VDEBUG(l, ...) do { if ((l) <= dbglvl) DEBUG(__VA_ARGS__); } while (0) 314 315 #define TO_MS(tv) ((unsigned long long)tv.tv_sec * 1000LL) + \ 316 ((unsigned long long)tv.tv_usec / 1000LL) 317 318 static void 319 progress(char *op, unsigned long c, unsigned long t) 320 { 321 static struct timeval s1 = {0}, s2 = {0}; 322 struct timeval sub; 323 324 gettimeofday(&s1, NULL); 325 sub.tv_sec = s1.tv_sec - s2.tv_sec; 326 sub.tv_usec = s1.tv_usec - s2.tv_usec; 327 if (TO_MS(sub) > 250LL) { 328 s2 = s1; 329 DEBUG(" %s (%2d%%) %08lx / %08lx\r", 330 op, (int)((100 * c) / t), c, t); 331 } 332 } 333 334 /* MAIN DECLARATIONS ------------------------------------------------------- */ 335 336 337 static FILE *fp = NULL; 338 339 static void safe_exit(void); 340 341 static void we(mdev_t *, int); 342 static void reset(void); 343 344 static void lad_output(void); 345 static void lad_input(void); 346 static void lad_write(mdev_t *, unsigned char, int); 347 static unsigned char lad_read(mdev_t *); 348 static void prepare_pins(void); 349 350 static unsigned int log2i(unsigned int); 351 352 static void lad_address(mdev_t *, unsigned long address); 353 static void lad_rsync(mdev_t *); 354 static void lad_start(mdev_t *, int); 355 static void read_maddress(mdev_t *, unsigned long, size_t, char *); 356 static void write_maddress(mdev_t *, unsigned long, size_t, char *); 357 static unsigned char read_address(mdev_t *, unsigned long); 358 static void write_address(mdev_t *, unsigned long, unsigned char); 359 360 static size_t max_xfer(mdev_t *, unsigned long, size_t, int); 361 static unsigned char read_reg(mdev_t *, unsigned long); 362 static void write_reg(mdev_t *, unsigned long, unsigned char); 363 static void op_mmem(mdev_t *, unsigned long, size_t, char *, int); 364 static unsigned char read_mem(mdev_t *, unsigned long); 365 static void write_mem(mdev_t *, unsigned long, unsigned char); 366 367 static void get_jedec_id(mdev_t *, unsigned char *, unsigned char *); 368 static void get_jedec_id2(mdev_t *, unsigned char *, unsigned char *); 369 370 static void get_sstmc_id(mdev_t *, unsigned char *, unsigned char *); 371 372 static void reset_echk(void); 373 static void misc_unlock_block(mdev_t *d, unsigned long block); 374 375 static void gen_chip_setup(mdev_t *); 376 static void gen_read(mdev_t *, char *, unsigned long, unsigned long, int); 377 static void gen_wait_status(mdev_t *, ndelay_t, int); 378 static void gen_erase_block(mdev_t *, unsigned long); 379 static void gen_erase_chip(mdev_t *, int); 380 static void gen_write(mdev_t *, char *, unsigned long, unsigned long, int); 381 382 static char *alloc_chip(mdev_t *); 383 384 static void fwc_template(int); 385 static void fwc_setfield(int, int, char); 386 static void full_write_cycle(mdev_t *, char *); 387 388 static mdev_t *get_chip_by_name(char *); 389 static void usage(); 390 static const char *fmt_chip_status(int); 391 392 /* HIGH-ACCURACY DELAY AND TIME ROUTINES ----------------------------------- */ 393 394 395 /* Not all operating systems can sleep for a reasonable amount of time. On my 396 * system, usleep(1); makes the average full-chip read take up to a whole 397 * day(!), so in order to prioritize chip operation speed over host CPU usage, 398 * let's just create an unoptimized no-op loop and calibrate it. 399 */ 400 static int clob; 401 #define NOOP asm volatile ("nop" : "+r" (clob)) 402 #define NOOPLOOP(t) do { \ 403 unsigned long long i; for (i = 0; i < t; i++) NOOP; \ 404 } while (0) 405 #define BIGCLK(tv) (((unsigned long long)(tv)->tv_sec * 1000000000ULL) \ 406 + (unsigned long long)(tv)->tv_nsec) 407 #define MAX(a, b) ((a) > (b) ? (a) : (b)) 408 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 409 410 static void 411 ndelay(ndelay_t ns) 412 { 413 static unsigned long long itpms = 0, ax; 414 if (itpms == 0) { 415 struct timespec r1, r2; 416 unsigned long long tres; 417 int monot, realt, i; 418 clockid_t clck; 419 DEBUG("calibrating delay scale... "); 420 /* select the most accurate clock, assuming it won't change */ 421 monot = clock_getres(CLOCK_MONOTONIC, &r1); 422 realt = clock_getres(CLOCK_REALTIME, &r2); 423 if (monot != 0 || realt != 0) { 424 clck = realt == 0 ? CLOCK_REALTIME : CLOCK_MONOTONIC; 425 } else { 426 /* prioritizes monotonic if equal */ 427 clck = BIGCLK(&r2) < BIGCLK(&r1) ? 428 CLOCK_REALTIME : CLOCK_MONOTONIC; 429 } 430 tres = clck == CLOCK_MONOTONIC ? BIGCLK(&r1) : BIGCLK(&r2); 431 /* warm up the processor to max freq */ 432 NOOPLOOP(1000000); 433 /* now calibrate for 1msec over and over for shortest cycles */ 434 for (i = 0; i < 128; i++) { 435 ax = 2; 436 for (;;) { 437 clock_gettime(clck, &r1); 438 NOOPLOOP(ax); 439 clock_gettime(clck, &r2); 440 tres = BIGCLK(&r2) - BIGCLK(&r1); 441 if (tres >= 1000000) break; 442 ax *= 2; 443 } 444 ax = (1000000.0 / (double)tres) * (double)ax; 445 /* need to find the quickest run (the largest number of 446 * required instructions) as this varies by factors 447 * like CPU frequency and context switches. 448 */ 449 if (itpms == 0) itpms = ax; 450 else itpms = MAX(itpms, ax); 451 } 452 DEBUG("needs %llu iterations for 1msec\n", itpms); 453 clock_gettime(clck, &r1); 454 ndelay(150000); 455 clock_gettime(clck, &r2); 456 tres = BIGCLK(&r2) - BIGCLK(&r1); 457 DEBUG("slept for 150us, got %fus\n", (double)tres / 1000.0); 458 /* bail out if calibration is untrustworthy! */ 459 ASSERT(tres >= 150000); 460 } else { 461 ax = ((double)itpms / 1000000.0) * (double)ns; 462 VDEBUG(15, " (W %lluns %lluistr) ", ns, ax); 463 NOOPLOOP(ax); 464 } 465 } 466 467 #define DELAY_FOR(d, a) ndelay(d->delay.a) 468 469 /* ACCESS PRIMITIVES ------------------------------------------------------- */ 470 471 472 static void 473 safe_exit(void) 474 { 475 OUTP(PIN_RSET, 1); 476 MODEP(PIN_RSET, MOD_OUT); 477 OUTP(PIN_WREN, 0); 478 lad_input(); 479 MODEP(PIN_WREN, MOD_IN); 480 MODEP(PIN_LFRM, MOD_IN); 481 MODEP(PIN_LCLK, MOD_IN); 482 if (fp != NULL) fclose(fp); 483 exit(1); 484 } 485 486 static void 487 lad_output(void) 488 { 489 MODEP(PIN_LAD0, MOD_OUT); 490 MODEP(PIN_LAD1, MOD_OUT); 491 MODEP(PIN_LAD2, MOD_OUT); 492 MODEP(PIN_LAD3, MOD_OUT); 493 } 494 495 static void 496 lad_input(void) 497 { 498 MODEP(PIN_LAD0, MOD_IN); 499 MODEP(PIN_LAD1, MOD_IN); 500 MODEP(PIN_LAD2, MOD_IN); 501 MODEP(PIN_LAD3, MOD_IN); 502 } 503 504 static void 505 lad_write(mdev_t *d, unsigned char data, int start_frame) 506 { 507 ASSERT((data & 0xf0) == 0); 508 if (start_frame) 509 OUTP(PIN_LFRM, 0); 510 OUTP(PIN_LCLK, 0); 511 OUTP(PIN_LAD0, data & 0x1 ? 1 : 0); 512 OUTP(PIN_LAD1, data & 0x2 ? 1 : 0); 513 OUTP(PIN_LAD2, data & 0x4 ? 1 : 0); 514 OUTP(PIN_LAD3, data & 0x8 ? 1 : 0); 515 DELAY_FOR(d, lad); 516 OUTP(PIN_LCLK, 1); 517 if (start_frame) 518 OUTP(PIN_LFRM, 1); 519 VDEBUG(10, "LAD W: %02x (%d)\n", data, start_frame); 520 } 521 522 static unsigned char 523 lad_read(mdev_t *d) 524 { 525 unsigned char v = 0; 526 OUTP(PIN_LCLK, 1); 527 DELAY_FOR(d, lad); 528 if (INP(PIN_LAD0)) v |= 0x1; 529 if (INP(PIN_LAD1)) v |= 0x2; 530 if (INP(PIN_LAD2)) v |= 0x4; 531 if (INP(PIN_LAD3)) v |= 0x8; 532 OUTP(PIN_LCLK, 0); 533 VDEBUG(10, "LAD R: %02x\n", v); 534 return v; 535 } 536 537 static void 538 we(mdev_t *d, int v) 539 { 540 OUTP(PIN_WREN, d->quirks & NEEDS_WE_ALWAYS_ON ? 1 : v); 541 } 542 543 static void 544 reset(void) 545 { 546 OUTP(PIN_RSET, 0); 547 usleep(1000); 548 OUTP(PIN_RSET, 1); 549 usleep(500000); 550 } 551 552 static void 553 prepare_pins(void) 554 { 555 PSETUP(); 556 OUTP(PIN_RSET, 0); 557 OUTP(PIN_LCLK, 1); 558 OUTP(PIN_LFRM, 1); 559 OUTP(PIN_WREN, 0); 560 561 OUTP(PIN_LAD0, 0); 562 OUTP(PIN_LAD1, 0); 563 OUTP(PIN_LAD2, 0); 564 OUTP(PIN_LAD3, 0); 565 lad_input(); 566 MODEP(PIN_RSET, MOD_OUT); 567 MODEP(PIN_WREN, MOD_OUT); 568 MODEP(PIN_LFRM, MOD_OUT); 569 MODEP(PIN_LCLK, MOD_OUT); 570 reset(); 571 } 572 573 /* LPC/FPC PROTOCOL PRIMITIVES --------------------------------------------- */ 574 575 576 static void 577 lad_address(mdev_t *d, unsigned long address) 578 { 579 int i; 580 /* FWH has a 28-bit address space, LPC has a 32-bit address space. */ 581 for (i = 1; i <= (d->type == BUS_FWH ? 7 : 8); i++) 582 lad_write(d, 583 (address >> ((d->type == BUS_FWH ? 28 : 32) - 4 * i)) 584 & 0xf, 0); 585 } 586 587 static int xfer_errs_fatal = 0, global_t0 = 0; 588 589 static void 590 lad_rsync(mdev_t *d) 591 { 592 /* Some chips do not immediately respond with an RSYNC value of 0. 593 * The W39V080FA for example often provides a value of 5 several times, 594 * indicating the host to wait for a few more clock cycles. 595 */ 596 unsigned char v; 597 rsync_reset: 598 switch ((v = lad_read(d))) { 599 case 0: return; 600 case 5: ndelay(STABILIZE); goto rsync_reset; 601 case 6: ndelay(USEC(100)); goto rsync_reset; 602 default: 603 if (xfer_errs_fatal) 604 ABORT("(read) field RSYNC not zero: %01x\n", v); 605 } 606 } 607 608 static void 609 lad_start(mdev_t *d, int write) 610 { 611 unsigned char cyctype = (1<<2); 612 if (write) cyctype |= (1<<1); 613 switch (d->type) { 614 case BUS_FWH: 615 cyctype |= (1<<3); 616 if (!write) cyctype |= 1; 617 break; 618 case BUS_LPC: 619 if (write) cyctype |= 1; 620 break; 621 case BUS_LPC_ISA: 622 lad_write(d, 0x00, 1); 623 lad_write(d, cyctype, 0); 624 return; 625 } 626 lad_write(d, cyctype, 1); 627 } 628 629 static unsigned int 630 log2i(unsigned int v) 631 { 632 /* https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog */ 633 int i; 634 static const unsigned int b[] = {0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 635 0xFF00FF00, 0xFFFF0000}; 636 unsigned int r = (v & b[0]) != 0; 637 for (i = 4; i > 0; i--) 638 r |= ((v & b[i]) != 0) << i; 639 return r; 640 } 641 642 static void 643 read_maddress(mdev_t *d, unsigned long address, size_t a, char *out) 644 { 645 size_t i; 646 unsigned char v; 647 lad_output(); 648 /* FWH vs. LPC use different START bits for differentiation. */ 649 lad_start(d, 0); /* START (READ) */ 650 lad_write(d, 0x00, 0); /* IDSEL 0000 */ 651 lad_address(d, address); /* IMADDR */ 652 lad_write(d, log2i(a), 0); /* IMSIZE */ 653 lad_write(d, 0x0f, 0); /* TAR0 */ 654 lad_input(); 655 lad_read(d); /* TAR1 */ 656 lad_rsync(d); /* RSYNC */ 657 for (i = 0; i < a; i++) { 658 out[i] = lad_read(d); /* DATA (LOW) */ 659 out[i] |= lad_read(d) << 4; /* DATA (HIGH) */ 660 } 661 if((v = lad_read(d)) != 0xf && xfer_errs_fatal) /* TAR0 */ 662 ABORT("(read) field TAR0 not all ones: %01x\n", v); 663 global_t0 |= v; 664 lad_read(d); /* TAR1 */ 665 lad_output(); 666 DELAY_FOR(d, cycle); 667 } 668 669 static void 670 write_maddress(mdev_t *d, unsigned long address, size_t a, char *in) 671 { 672 size_t i; 673 unsigned char v; 674 lad_output(); 675 lad_start(d, 1); /* START (WRITE) */ 676 lad_write(d, 0x00, 0); /* IDSEL 0000 */ 677 lad_address(d, address); /* IMADDR */ 678 lad_write(d, log2i(a), 0); /* IMSIZE */ 679 for (i = 0; i < a; i++) { 680 lad_write(d, in[i] & 0xf , 0); /* DATA (LOW) */ 681 lad_write(d, (in[i] >> 4) & 0xf , 0); /* DATA (HIGH) */ 682 } 683 lad_write(d, 0x0f, 0); /* TAR0 */ 684 lad_input(); 685 lad_read(d); /* TAR1 */ 686 lad_rsync(d); /* RSYNC */ 687 if((v = lad_read(d)) != 0xf && xfer_errs_fatal) /* TAR0 */ 688 ABORT("(write) field TAR0 not all ones: %01x!\n", v); 689 global_t0 |= v; 690 lad_read(d); /* TAR1 */ 691 lad_output(); 692 DELAY_FOR(d, cycle); 693 } 694 695 static unsigned char 696 read_address(mdev_t *d, unsigned long address) 697 { 698 char buf[1]; 699 read_maddress(d, address, 1, buf); 700 VDEBUG(5, "1R: %08lx, %02x\n", address, buf[0]); 701 return buf[0]; 702 } 703 704 static void 705 write_address(mdev_t *d, unsigned long address, unsigned char data) 706 { 707 char buf[1]; 708 buf[0] = data; 709 VDEBUG(5, "1W: %08lx, %02x\n", address, buf[0]); 710 write_maddress(d, address, 1, buf); 711 } 712 713 /* CHIP REGION ACCESS PRIMITIVES ------------------------------------------- */ 714 715 716 static size_t 717 max_xfer(mdev_t *d, unsigned long s, size_t tc, int t) 718 { 719 /* XXX: work out the largest transfer size supported on the chip for 720 * a given type (read or write operation). "tc" (the total operation 721 * size) and "s" (the starting address) must be evenly divisible by (or 722 * rather, aligned with) the derived transfer chunk size. In most 723 * cases this is already true, so there's no real reason to optimize 724 * for the case where it wouldn't be. 725 */ 726 int pta, ptt, i; 727 size_t r = 1; 728 for (i = 0;;i++) { 729 pta = d->xfers[i].size; 730 ptt = d->xfers[i].type; 731 if (ptt == XFER_N) break; 732 733 if ( (pta > r) 734 && (ptt == t || ptt == XFER_RW) 735 && !(tc % pta) 736 && !(s % pta)) r = pta; 737 VDEBUG(10, "ESTABLISH XFER SZ: %08lx\n", (unsigned long)r); 738 } 739 return r; 740 } 741 742 #define XFERL(v, s, a, x, e) \ 743 for (v = s; v < (s + a); (e),v += x) 744 745 static int opp_q = 0; 746 #define PROG_PRINT(t, c, e) do { \ 747 if (!opp_q) progress(t == XFER_R ? "READ " : "WRITE", c, e); \ 748 } while (0) 749 #define PROG_FIN do { \ 750 if (!opp_q) DEBUG("\n"); \ 751 } while (0) 752 753 /* Produces variables i and xf, containing the current address and transfer 754 * size respectively, and a loop that iterates over an address space in 755 * transfer-sized chunks. 756 */ 757 #define XFEROP(d, s, a, t, ...) do { \ 758 unsigned long i; \ 759 size_t xf = max_xfer(d, s, a, t); \ 760 ASSERT(s + a <= d->csz); \ 761 XFERL(i, s, a, xf, buf += xf) { \ 762 PROG_PRINT(t, i, s + a); \ 763 __VA_ARGS__; \ 764 } \ 765 PROG_FIN; \ 766 } while (0); 767 768 static unsigned char 769 read_reg(mdev_t *d, unsigned long address) 770 { 771 return read_address(d, address + d->register_base); 772 } 773 774 static void 775 write_reg(mdev_t *d, unsigned long address, unsigned char data) 776 { 777 write_address(d, address + d->register_base, data); 778 DELAY_FOR(d, regset); 779 } 780 781 static void 782 op_mmem(mdev_t *d, unsigned long address, size_t a, char *buf, int w) 783 { 784 if (!w) read_maddress (d, address + d->memory_base, a, buf); 785 else write_maddress(d, address + d->memory_base, a, buf); 786 } 787 788 static unsigned char 789 read_mem(mdev_t *d, unsigned long address) 790 { 791 return read_address(d, address + d->memory_base); 792 } 793 794 static void 795 write_mem(mdev_t *d, unsigned long address, unsigned char data) 796 { 797 write_address(d, address + d->memory_base, data); 798 } 799 800 /* MISC FUNCTIONS ---------------------------------------------------------- */ 801 802 803 static void 804 misc_unlock_block(mdev_t *d, unsigned long block) 805 { 806 unsigned long ulock = 0x300002 | (d->bsz * block); 807 ASSERT(read_reg(d, ulock) == 0x01); 808 write_reg(d, ulock, 0x00); 809 ASSERT(read_reg(d, ulock) == 0x00); 810 } 811 812 /* JEDEC FUNCTIONS --------------------------------------------------------- */ 813 814 815 static unsigned char d6_lt; 816 817 int 818 toggle_d6_erased(mdev_t *d) 819 { 820 unsigned char v; 821 if ((v = read_mem(d, 0x0000) & 0x40) == d6_lt) return 1; 822 d6_lt = v; 823 return 0; 824 } 825 826 static void 827 reset_echk(void) 828 { 829 /* 830 * This function should be used for resetting erase-check state for all 831 * available chips. 832 */ 833 d6_lt = 0xAB; 834 } 835 836 static void 837 get_jedec_id(mdev_t *d, unsigned char *ven, unsigned char *dev) 838 { 839 *ven = read_reg(d, 0x3c0000); 840 *dev = read_reg(d, 0x3c0001); 841 } 842 843 static void 844 get_jedec_id2(mdev_t *d, unsigned char *ven, unsigned char *dev) 845 { 846 write_mem(d, 0x5555, 0xAA); 847 write_mem(d, 0x2AAA, 0x55); 848 write_mem(d, 0x5555, 0x90); 849 *ven = read_mem(d, 0x0000); 850 *dev = read_mem(d, 0x0001); 851 write_mem(d, 0x0000, 0xF0); 852 } 853 854 #define IDDBG(m, c, v, d, p) DEBUG( \ 855 m " identification method " c ": " \ 856 "ven %02x dev %02x (%s)\n", v, d, p ? "PASSED" : "FAILED"); 857 858 int 859 jedec_chip_identify(mdev_t *d) 860 { 861 unsigned char ven, dev; 862 int m2; 863 get_jedec_id(d, &ven, &dev); 864 if (ven == d->ven_id && dev == d->dev_id) { 865 IDDBG("jedec", "1", ven, dev, 1); 866 get_jedec_id2(d, &ven, &dev); 867 m2 = ven == d->ven_id && dev == d->dev_id; 868 IDDBG("jedec", "2", ven, dev, m2); 869 return m2; 870 } else return 0; 871 } 872 873 void 874 jedec_sector_erase(mdev_t *d, unsigned long sector) 875 { 876 write_mem(d, 0x5555, 0xAA); 877 write_mem(d, 0x2AAA, 0x55); 878 write_mem(d, 0x5555, 0x80); 879 write_mem(d, 0x5555, 0xAA); 880 write_mem(d, 0x2AAA, 0x55); 881 write_mem(d, d->ssz * sector, 0x30); 882 gen_wait_status(d, d->delay.s_erase, 1); 883 } 884 885 void 886 jedec_block_erase(mdev_t *d, unsigned long block) 887 { 888 write_mem(d, 0x5555, 0xAA); 889 write_mem(d, 0x2AAA, 0x55); 890 write_mem(d, 0x5555, 0x80); 891 write_mem(d, 0x5555, 0xAA); 892 write_mem(d, 0x2AAA, 0x55); 893 write_mem(d, d->bsz * block, 0x50); 894 gen_wait_status(d, d->delay.b_erase, 1); 895 } 896 897 void 898 jedec_chip_erase(mdev_t *d) 899 { 900 write_mem(d, 0x5555, 0xAA); 901 write_mem(d, 0x2AAA, 0x55); 902 write_mem(d, 0x5555, 0x80); 903 write_mem(d, 0x5555, 0xAA); 904 write_mem(d, 0x2AAA, 0x55); 905 write_mem(d, 0x5555, 0x10); 906 gen_wait_status(d, d->delay.c_erase, 1); 907 } 908 909 void 910 jedec_program(mdev_t *d, unsigned long address, size_t a, char *buf) 911 { 912 write_mem(d, 0x5555, 0xAA); 913 write_mem(d, 0x2AAA, 0x55); 914 write_mem(d, 0x5555, 0xA0); 915 op_mmem(d, address, a, buf, 1); 916 gen_wait_status(d, d->delay.program, 0); 917 } 918 919 void 920 jedec_read(mdev_t *d, unsigned long address, size_t a, char *buf) 921 { 922 op_mmem(d, address, a, buf, 0); 923 } 924 925 /* SST MINI-COMMAND IMPLEMENTATION ----------------------------------------- */ 926 927 928 enum sstmc_modes { 929 SSTMC_READARRAY, 930 SSTMC_SOFTWAREID, 931 SSTMC_STATUSREG 932 }; 933 934 static int sstmc_mode = SSTMC_READARRAY; 935 936 static void 937 get_sstmc_id(mdev_t *d, unsigned char *ven, unsigned char *dev) 938 { 939 if (sstmc_mode != SSTMC_SOFTWAREID) 940 write_mem(d, 0x0000, 0x90); 941 *ven = read_mem(d, 0x3c0000); 942 *dev = read_mem(d, 0x3c0001); 943 sstmc_mode = SSTMC_SOFTWAREID; 944 } 945 946 int 947 sstmc_chip_identify(mdev_t *d) 948 { 949 unsigned char ven, dev; 950 int m2; 951 get_jedec_id(d, &ven, &dev); 952 if ((ven == 0 && dev == 0) 953 || (ven == d->ven_id && dev == d->dev_id)) { 954 get_sstmc_id(d, &ven, &dev); 955 m2 = ven == d->ven_id && dev == d->dev_id; 956 IDDBG("sstmc", "1", ven, dev, m2); 957 return m2; 958 } else return 0; 959 } 960 961 /* DUMMY IMPLEMENTATION ---------------------------------------------------- */ 962 963 964 static FILE *dummy_chip = NULL; 965 966 #define FFILL(f, c, a) do { int i;for (i=0;i<a;i++) {fputc(c,f);} } while (0) 967 #define FSEEK(f, t) if (fseeko(f, t, SEEK_SET)<0) ABORT("failed to seek!\n"); 968 969 void 970 dummy_sector_erase(mdev_t *d, unsigned long sector) 971 { 972 if (!dummy_chip) return; 973 FSEEK(dummy_chip, sector * d->ssz); 974 FFILL(dummy_chip, 0xFF, d->ssz); 975 } 976 977 void 978 dummy_block_erase(mdev_t *d, unsigned long block) 979 { 980 if (!dummy_chip) return; 981 FSEEK(dummy_chip, block * d->bsz); 982 FFILL(dummy_chip, 0xFF, d->bsz); 983 } 984 985 void 986 dummy_chip_erase(mdev_t *d) 987 { 988 if (!dummy_chip) return; 989 FSEEK(dummy_chip, 0); 990 FFILL(dummy_chip, 0xFF, d->csz); 991 } 992 993 void 994 dummy_program(mdev_t *d, unsigned long address, size_t a, char *buf) 995 { 996 if (!dummy_chip) return; 997 FSEEK(dummy_chip, address); 998 ASSERT(fwrite(buf, a, 1, dummy_chip) == 1); 999 } 1000 1001 void 1002 dummy_read(mdev_t *d, unsigned long address, size_t a, char *buf) 1003 { 1004 if (!dummy_chip) return; 1005 FSEEK(dummy_chip, address); 1006 ASSERT(fread(buf, a, 1, dummy_chip) == 1); 1007 } 1008 1009 /* GENERIC IMPLEMENTATION -------------------------------------------------- */ 1010 1011 1012 static void 1013 gen_chip_setup(mdev_t *d) 1014 { 1015 unsigned long i, be; 1016 unsigned char bl; 1017 xfer_errs_fatal = 1; 1018 if (d->quirks & NEEDS_WE_ALWAYS_ON) { 1019 DEBUG("WARNING: chip requires WP# always active!\n"); 1020 we(d, 1); 1021 reset(); 1022 write_mem(d, 0x5555, 0xAA); 1023 write_mem(d, 0x2AAA, 0x55); 1024 write_mem(d, 0x5555, 0x90); 1025 if ((bl = read_mem(d, 0x000FFFF2) & 0xc) > 0) 1026 ABORT("CHIP STILL LOCKED! %02x\n", bl); 1027 write_mem(d, 0x0000, 0xF0); 1028 } 1029 if (d->quirks & NEEDS_MISC_BLOCK_UNLOCK) { 1030 be = d->csz / d->bsz; 1031 for (i = 0; i < be; i++) { 1032 DEBUG("unlocking block %lu / %lu\r", i + 1, be); 1033 misc_unlock_block(d, i); 1034 } 1035 DEBUG("\n"); 1036 } 1037 } 1038 1039 static void 1040 gen_read(mdev_t *d, char *buf, unsigned long s, unsigned long a, int o) 1041 { 1042 if (!d->read) 1043 ABORT("this chip has no read implementation!\n"); 1044 opp_q = !o; 1045 XFEROP(d, s, a, XFER_R, do { 1046 VDEBUG(3, "DREAD: %08lx, %08lx\n", i, (unsigned long)xf); 1047 d->read(d, i, xf, buf); 1048 } while (0)); 1049 } 1050 1051 static void 1052 gen_wait_status(mdev_t *d, ndelay_t fallback, int slow) 1053 { 1054 int t = 0; 1055 reset_echk(); 1056 if (!d->erased) { 1057 ndelay(fallback); 1058 return; 1059 } do { 1060 if (slow) 1061 DELAY_FOR(d, toggle_bit_delay); 1062 t++; 1063 } while (d->erased(d) == 0); 1064 VDEBUG(5, "WAITED: %d tries\n", t); 1065 } 1066 1067 static void 1068 gen_erase_block(mdev_t *d, unsigned long block) 1069 { 1070 unsigned long i, ss, se; 1071 char sanity[1]; 1072 we(d, 1); 1073 if (d->b_erase) { 1074 d->b_erase(d, block); 1075 } else if (d->bsz && d->csz && d->s_erase) { 1076 ss = (block ) * d->bsz / d->ssz; 1077 se = (block + 1) * d->bsz / d->ssz; 1078 for (i = ss; i < se; i++) 1079 d->s_erase(d, i); 1080 } else ABORT("no generic block erasure method could be employed.\n"); 1081 /* sanity check */ 1082 we(d, 0); 1083 gen_read(d, sanity, d->bsz * block, 1, 0); 1084 ASSERT(sanity[0] == 0xFF); 1085 } 1086 1087 static void 1088 gen_erase_chip(mdev_t *d, int o) 1089 { 1090 unsigned long i, be; 1091 we(d, 1); 1092 if (d->c_erase) { 1093 DEBUG("issuing a complete chip erase command...\n"); 1094 d->c_erase(d); 1095 } else { 1096 be = d->csz / d->bsz; 1097 for (i = 0; i < be; i++) { 1098 if (o) DEBUG("erase block %lu / %lu\r", i + 1, be); 1099 gen_erase_block(d, i); 1100 } 1101 if (o) DEBUG("\n"); 1102 } 1103 we(d, 0); 1104 } 1105 1106 static void 1107 gen_write(mdev_t *d, char *buf, unsigned long s, unsigned long a, int o) 1108 { 1109 unsigned long e = s + a; 1110 ASSERT(e <= d->csz); 1111 we(d, 1); 1112 if (!d->write) 1113 ABORT("this chip has no write implementation!\n"); 1114 opp_q = !o; 1115 XFEROP(d, s, a, XFER_W, do { 1116 VDEBUG(3, "DWRITE: %08lx, %08lx\n", i, (unsigned long)xf); 1117 d->write(d, i, xf, buf); 1118 } while (0)); 1119 we(d, 0); 1120 } 1121 1122 /* ERASE-WRITE-VERIFY CODE ------------------------------------------------- */ 1123 1124 1125 static char * 1126 alloc_chip(mdev_t *d) 1127 { 1128 return malloc(d->csz); 1129 } 1130 1131 enum fwf { 1132 FWF_ERASE, 1133 FWF_WRITE, 1134 FWF_VERIFY 1135 }; 1136 1137 enum fwc { 1138 FWF_WAIT = '.', 1139 FWF_PROGRESS = '%', 1140 FWF_DONE = 'S' 1141 }; 1142 1143 static void 1144 fwc_template(int blocks) 1145 { 1146 int i; 1147 #define PCM(...) for (i = 0; i < blocks; i++) DEBUG(__VA_ARGS__); DEBUG("\n"); 1148 DEBUG(" BLOCK : "); PCM("%01X", i); 1149 DEBUG(" ERASE : "); PCM("%c", FWF_WAIT); 1150 DEBUG(" WRITE : "); PCM("%c", FWF_WAIT); 1151 DEBUG(" VERIFY : "); PCM("%c", FWF_WAIT); 1152 } 1153 1154 static void 1155 fwc_setfield(int field, int block, char v) 1156 { 1157 DEBUG("\r\033[%dA\033[%dC%c\r\033[%dB", 1158 3 - field, 12 + block, v, 3 - field); 1159 fflush(stderr); 1160 } 1161 1162 static void 1163 full_write_cycle(mdev_t *d, char *buf) 1164 { 1165 char *vbuf; 1166 unsigned long i, be, bs; 1167 be = d->csz / d->bsz; 1168 DEBUG("initiating a full EWV (Erase Write Verify) cycle...\n\n"); 1169 fwc_template(be); 1170 vbuf = alloc_chip(d); 1171 for (i = 0; i < be; i++) { 1172 bs = i * d->bsz; 1173 fwc_setfield(FWF_ERASE, i, FWF_PROGRESS); 1174 gen_erase_block(d, i); 1175 fwc_setfield(FWF_ERASE, i, FWF_DONE); 1176 fwc_setfield(FWF_WRITE, i, FWF_PROGRESS); 1177 gen_write(d, buf + bs, bs, d->bsz, 0); 1178 fwc_setfield(FWF_WRITE, i, FWF_DONE); 1179 fwc_setfield(FWF_VERIFY, i, FWF_PROGRESS); 1180 gen_read(d, vbuf, bs, d->bsz, 0); 1181 if (memcmp(vbuf, buf + bs, d->bsz) != 0) 1182 ABORT("\nverify 1 failed for block %lu\n", i); 1183 fwc_setfield(FWF_VERIFY, i, FWF_DONE); 1184 } 1185 DEBUG("\n SUCCESS -- checking full chip...\n"); 1186 gen_read(d, vbuf, 0, d->csz, 1); 1187 if (memcmp(vbuf, buf, d->csz) != 0) 1188 ABORT("verify 2 failed for chip\n"); 1189 DEBUG(" SUCCESS -- all ok!\n"); 1190 free(vbuf); 1191 } 1192 1193 /* USER INTERFACE FUNCTIONALITY -------------------------------------------- */ 1194 1195 1196 static mdev_t * 1197 get_chip_by_name(char *name) 1198 { 1199 int i; 1200 mdev_t *r; 1201 for (i = 0; i < devices; i++) 1202 { 1203 r = &devicetab[i]; 1204 if (strcasecmp(r->name, name) == 0) 1205 return r; 1206 } 1207 return NULL; 1208 } 1209 1210 static void 1211 usage() 1212 { 1213 ABORT( 1214 "SBC FWH/LPC flash tool\n\n" 1215 " -i (identify only)\n" 1216 " -r <file> (read to file)\n" 1217 " -w <file> (write from file)\n" 1218 " -E (erase)\n" 1219 " -W (write without erasing)\n" 1220 " -c <chip> (override chip detection)\n" 1221 " -d <file> (open file as backing for dummy chip)\n" 1222 " -f (force untested chip)\n"); 1223 } 1224 1225 static const char * 1226 fmt_chip_status(int status) 1227 { 1228 switch (status) { 1229 default: 1230 case TEST_WIP: return "!WORK IN PROGRESS!"; 1231 case TEST_NONE: return "NONE"; 1232 case TEST_I: return "IDENTIFY"; 1233 case TEST_IR: return "IDENTIFY READ"; 1234 case TEST_IRW: return "IDENTIFY READ WRITE"; 1235 } 1236 } 1237 1238 int 1239 main(int argc, char **argv) 1240 { 1241 int ch, dwrite = 0, force = 0; 1242 enum { 1243 CM_NOTHING, 1244 CM_IDENTIFY, 1245 CM_READ, 1246 CM_WRITE, 1247 CM_ERASE 1248 } mode = CM_NOTHING; 1249 mdev_t *d = NULL; 1250 char *buf, *chip_name = NULL; 1251 #ifndef BOARD_DUMMY 1252 int i; 1253 mdev_t *dt; 1254 #endif 1255 prepare_pins(); 1256 1257 #define TRY_OPEN_FILE(f, m) if ((f = fopen(optarg, m)) == NULL) { \ 1258 perror(NULL); exit(1); } 1259 while ((ch = getopt(argc, argv, "hir:w:EW:c:d:f")) != -1) { 1260 switch (ch) { 1261 case 'i': 1262 mode = CM_IDENTIFY; 1263 break; 1264 case 'r': 1265 mode = CM_READ; 1266 TRY_OPEN_FILE(fp, "wb"); 1267 break; 1268 case 'w': 1269 mode = CM_WRITE; 1270 TRY_OPEN_FILE(fp, "rb"); 1271 break; 1272 case 'E': 1273 mode = CM_ERASE; 1274 break; 1275 case 'W': 1276 dwrite = 1; 1277 break; 1278 case 'c': 1279 chip_name = strdup(optarg); 1280 break; 1281 case 'd': 1282 TRY_OPEN_FILE(dummy_chip, "r+b"); 1283 break; 1284 case 'f': 1285 force = 1; 1286 break; 1287 case '?': 1288 case 'h': 1289 default: 1290 usage(); 1291 break; 1292 } 1293 } 1294 argc -= optind; 1295 argv += optind; 1296 1297 if (mode == CM_NOTHING) 1298 ABORT("no mode selected, aborting.\n"); 1299 if (dwrite && mode != CM_WRITE) 1300 ABORT("need to specify -w with -W.\n"); 1301 1302 #ifdef BOARD_DUMMY 1303 chip_name = "dummy"; 1304 d = get_chip_by_name(chip_name); 1305 #else 1306 if (chip_name) { 1307 d = get_chip_by_name(chip_name); 1308 if (d->probe && !d->probe(d)) { 1309 DEBUG("WARNING: forced chip but probe failed!\n"); 1310 } 1311 } else { 1312 for (i = 0; i < devices; i++) 1313 { 1314 dt = &devicetab[i]; 1315 if (dt->probe && dt->probe(dt)) { 1316 d = dt; 1317 break; 1318 } 1319 } 1320 } 1321 #endif 1322 if (dummy_chip) 1323 ASSERT(ftruncate(fileno(dummy_chip), d->csz) == 0); 1324 1325 if (global_t0 != 0xf) 1326 ABORT("wiring fault, tar0 max at %d\n", global_t0); 1327 if (!d) 1328 ABORT("no supported flash chip found!\n"); 1329 1330 DEBUG("found %s at %s!\n", d->name, 1331 d->type == BUS_FWH ? "FWH" : "LPC"); 1332 1333 DEBUG("detected chip tested for operations: %s\n", 1334 fmt_chip_status(d->status)); 1335 if (!force && d->status != TEST_IRW) 1336 ABORT( 1337 "detected chip hasn't been fully tested!\n" 1338 "you may leave the chip unrecoverable. (see -f)\n"); 1339 1340 if (mode == CM_IDENTIFY) return 0; 1341 gen_chip_setup(d); 1342 1343 buf = alloc_chip(d); 1344 1345 /* 1346 * Chip size and block size must always be defined (even if block size 1347 * is not a real number, although it must always be a multiple of the 1348 * sector size). 1349 */ 1350 ASSERT(d->bsz && d->csz); 1351 1352 switch (mode) { 1353 default: 1354 usage(); 1355 break; 1356 case CM_READ: 1357 gen_read(d, buf, 0, d->csz, 1); 1358 ASSERT(fwrite(buf, d->csz, 1, fp) == 1); 1359 break; 1360 case CM_WRITE: 1361 ASSERT(fread(buf, d->csz, 1, fp) == 1); 1362 if (!dwrite) full_write_cycle(d, buf); 1363 else gen_write(d, buf, 0, d->csz, 1); 1364 break; 1365 case CM_ERASE: 1366 gen_erase_chip(d, 1); 1367 break; 1368 } 1369 1370 if (fp) fclose(fp); 1371 if (dummy_chip) fclose(dummy_chip); 1372 free(buf); 1373 return 0; 1374 }