flashrom.c 23.5 KB
Newer Older
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
1
/*
2
 * This file is part of the flashrom project.
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
3
 *
4 5
 * Copyright (C) 2000 Silicon Integrated System Corporation
 * Copyright (C) 2004 Tyan Corp <yhlu@tyan.com>
6
 * Copyright (C) 2005-2008 coresystems GmbH
7
 * Copyright (C) 2008,2009 Carl-Daniel Hailfinger
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
8
 *
9 10 11 12
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
13
 *
14 15 16 17
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
18
 *
19 20 21
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
22 23 24
 */

#include <fcntl.h>
25 26
#include <sys/types.h>
#include <sys/stat.h>
Ronald G. Minnich's avatar
Ronald G. Minnich committed
27
#include <string.h>
Ronald G. Minnich's avatar
Ronald G. Minnich committed
28
#include <stdlib.h>
29
#include <getopt.h>
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
30
#include "flash.h"
31
#include "flashchips.h"
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
32

Ronald G. Minnich's avatar
Ronald G. Minnich committed
33
char *chip_to_probe = NULL;
Peter Stuge's avatar
Peter Stuge committed
34
int verbose = 0;
35 36 37 38
int programmer = PROGRAMMER_INTERNAL;

const struct programmer_entry programmer_table[] = {
	{
39 40
		.init			= internal_init,
		.shutdown		= internal_shutdown,
41 42
		.map_flash_region	= physmap,
		.unmap_flash_region	= physunmap,
43 44 45
		.chip_readb		= internal_chip_readb,
		.chip_readw		= internal_chip_readw,
		.chip_readl		= internal_chip_readl,
46
		.chip_readn		= internal_chip_readn,
47 48 49
		.chip_writeb		= internal_chip_writeb,
		.chip_writew		= internal_chip_writew,
		.chip_writel		= internal_chip_writel,
50
		.chip_writen		= fallback_chip_writen,
51
		.delay			= internal_delay,
52 53
	},

54
	{
55 56
		.init			= dummy_init,
		.shutdown		= dummy_shutdown,
57 58
		.map_flash_region	= dummy_map,
		.unmap_flash_region	= dummy_unmap,
59 60 61
		.chip_readb		= dummy_chip_readb,
		.chip_readw		= dummy_chip_readw,
		.chip_readl		= dummy_chip_readl,
62
		.chip_readn		= dummy_chip_readn,
63 64 65
		.chip_writeb		= dummy_chip_writeb,
		.chip_writew		= dummy_chip_writew,
		.chip_writel		= dummy_chip_writel,
66
		.chip_writen		= dummy_chip_writen,
67
		.delay			= internal_delay,
68 69
	},

70 71 72
	{
		.init			= nic3com_init,
		.shutdown		= nic3com_shutdown,
73 74
		.map_flash_region	= fallback_map,
		.unmap_flash_region	= fallback_unmap,
75
		.chip_readb		= nic3com_chip_readb,
76 77
		.chip_readw		= fallback_chip_readw,
		.chip_readl		= fallback_chip_readl,
78
		.chip_readn		= fallback_chip_readn,
79
		.chip_writeb		= nic3com_chip_writeb,
80 81
		.chip_writew		= fallback_chip_writew,
		.chip_writel		= fallback_chip_writel,
82
		.chip_writen		= fallback_chip_writen,
83
		.delay			= internal_delay,
84 85
	},

86 87 88
	{
		.init			= satasii_init,
		.shutdown		= satasii_shutdown,
89 90
		.map_flash_region	= fallback_map,
		.unmap_flash_region	= fallback_unmap,
91 92 93
		.chip_readb		= satasii_chip_readb,
		.chip_readw		= fallback_chip_readw,
		.chip_readl		= fallback_chip_readl,
94
		.chip_readn		= fallback_chip_readn,
95 96 97
		.chip_writeb		= satasii_chip_writeb,
		.chip_writew		= fallback_chip_writew,
		.chip_writel		= fallback_chip_writel,
98
		.chip_writen		= fallback_chip_writen,
99
		.delay			= internal_delay,
100 101
	},

102 103 104 105 106 107
	{
		.init			= it87spi_init,
		.shutdown		= dummy_shutdown,
		.map_flash_region	= dummy_map,
		.unmap_flash_region	= dummy_unmap,
		.chip_readb		= dummy_chip_readb,
108 109 110
		.chip_readw		= fallback_chip_readw,
		.chip_readl		= fallback_chip_readl,
		.chip_readn		= fallback_chip_readn,
111
		.chip_writeb		= dummy_chip_writeb,
112 113 114
		.chip_writew		= fallback_chip_writew,
		.chip_writel		= fallback_chip_writel,
		.chip_writen		= fallback_chip_writen,
115
		.delay			= internal_delay,
116 117
	},

118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
	{
		.init			= ft2232_spi_init,
		.shutdown		= dummy_shutdown,
		.map_flash_region	= dummy_map,
		.unmap_flash_region	= dummy_unmap,
		.chip_readb		= dummy_chip_readb,
		.chip_readw		= fallback_chip_readw,
		.chip_readl		= fallback_chip_readl,
		.chip_readn		= fallback_chip_readn,
		.chip_writeb		= dummy_chip_writeb,
		.chip_writew		= fallback_chip_writew,
		.chip_writel		= fallback_chip_writel,
		.chip_writen		= fallback_chip_writen,
		.delay			= internal_delay,
	},
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
	{
		.init			= serprog_init,
		.shutdown		= serprog_shutdown,
		.map_flash_region	= fallback_map,
		.unmap_flash_region	= fallback_unmap,
		.chip_readb		= serprog_chip_readb,
		.chip_readw		= fallback_chip_readw,
		.chip_readl		= fallback_chip_readl,
		.chip_readn		= serprog_chip_readn,
		.chip_writeb		= serprog_chip_writeb,
		.chip_writew		= fallback_chip_writew,
		.chip_writel		= fallback_chip_writel,
		.chip_writen		= fallback_chip_writen,
		.delay			= serprog_delay,
	},
148

149 150
	{},
};
151

152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
int programmer_init(void)
{
	return programmer_table[programmer].init();
}

int programmer_shutdown(void)
{
	return programmer_table[programmer].shutdown();
}

void *programmer_map_flash_region(const char *descr, unsigned long phys_addr,
				  size_t len)
{
	return programmer_table[programmer].map_flash_region(descr,
							     phys_addr, len);
}

void programmer_unmap_flash_region(void *virt_addr, size_t len)
{
	programmer_table[programmer].unmap_flash_region(virt_addr, len);
}

void chip_writeb(uint8_t val, chipaddr addr)
{
	programmer_table[programmer].chip_writeb(val, addr);
}

void chip_writew(uint16_t val, chipaddr addr)
{
	programmer_table[programmer].chip_writew(val, addr);
}

void chip_writel(uint32_t val, chipaddr addr)
{
	programmer_table[programmer].chip_writel(val, addr);
}

189 190 191 192 193
void chip_writen(uint8_t *buf, chipaddr addr, size_t len)
{
	programmer_table[programmer].chip_writen(buf, addr, len);
}

194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
uint8_t chip_readb(const chipaddr addr)
{
	return programmer_table[programmer].chip_readb(addr);
}

uint16_t chip_readw(const chipaddr addr)
{
	return programmer_table[programmer].chip_readw(addr);
}

uint32_t chip_readl(const chipaddr addr)
{
	return programmer_table[programmer].chip_readl(addr);
}

209 210 211 212 213 214
void chip_readn(uint8_t *buf, chipaddr addr, size_t len)
{
	programmer_table[programmer].chip_readn(buf, addr, len);
	return;
}

215 216 217 218 219
void programmer_delay(int usecs)
{
	programmer_table[programmer].delay(usecs);
}

220
void map_flash_registers(struct flashchip *flash)
221 222
{
	size_t size = flash->total_size * 1024;
223
	/* Flash registers live 4 MByte below the flash. */
224
	flash->virtual_registers = (chipaddr)programmer_map_flash_region("flash chip registers", (0xFFFFFFFF - 0x400000 - size + 1), size);
225 226
}

227
int read_memmapped(struct flashchip *flash, uint8_t *buf, int start, int len)
228
{
229
	chip_readn(buf, flash->virtual_memory + start, len);
230 231 232 233
		
	return 0;
}

234 235 236 237 238
int min(int a, int b)
{
	return (a < b) ? a : b;
}

239 240 241 242 243
int max(int a, int b)
{
	return (a > b) ? a : b;
}

244 245 246 247 248 249 250 251 252
char *strcat_realloc(char *dest, const char *src)
{
	dest = realloc(dest, strlen(dest) + strlen(src) + 1);
	if (!dest)
		return NULL;
	strcat(dest, src);
	return dest;
}

253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
/* start is an offset to the base address of the flash chip */
int check_erased_range(struct flashchip *flash, int start, int len)
{
	int ret;
	uint8_t *cmpbuf = malloc(len);

	if (!cmpbuf) {
		fprintf(stderr, "Could not allocate memory!\n");
		exit(1);
	}
	memset(cmpbuf, 0xff, len);
	ret = verify_range(flash, cmpbuf, start, len, "ERASE");
	free(cmpbuf);
	return ret;
}

/**
 * @cmpbuf	buffer to compare against
 * @start	offset to the base address of the flash chip
 * @len		length of the verified area
 * @message	string to print in the "FAILED" message
 * @return	0 for success, -1 for failure
 */
int verify_range(struct flashchip *flash, uint8_t *cmpbuf, int start, int len, char *message)
{
	int i, j, starthere, lenhere, ret = 0;
	int page_size = flash->page_size;
	uint8_t *readbuf = malloc(page_size);

	if (!len)
		goto out_free;

285 286 287 288
	if (!flash->read) {
		fprintf(stderr, "ERROR: flashrom has no read function for this flash chip.\n");
		return 1;
	}
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
	if (!readbuf) {
		fprintf(stderr, "Could not allocate memory!\n");
		exit(1);
	}

	if (start + len > flash->total_size * 1024) {
		fprintf(stderr, "Error: %s called with start 0x%x + len 0x%x >"
			" total_size 0x%x\n", __func__, start, len,
			flash->total_size * 1024);
		ret = -1;
		goto out_free;
	}
	if (!message)
		message = "VERIFY";
	
	/* Warning: This loop has a very unusual condition and body.
	 * The loop needs to go through each page with at least one affected
	 * byte. The lowest page number is (start / page_size) since that
	 * division rounds down. The highest page number we want is the page
	 * where the last byte of the range lives. That last byte has the
	 * address (start + len - 1), thus the highest page number is
	 * (start + len - 1) / page_size. Since we want to include that last
	 * page as well, the loop condition uses <=.
	 */
	for (i = start / page_size; i <= (start + len - 1) / page_size; i++) {
		/* Byte position of the first byte in the range in this page. */
		starthere = max(start, i * page_size);
		/* Length of bytes in the range in this page. */
		lenhere = min(start + len, (i + 1) * page_size) - starthere;
318
		flash->read(flash, readbuf, starthere, lenhere);
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
		for (j = 0; j < lenhere; j++) {
			if (cmpbuf[starthere - start + j] != readbuf[j]) {
				fprintf(stderr, "%s FAILED at 0x%08x! "
					"Expected=0x%02x, Read=0x%02x\n",
					message, starthere + j,
					cmpbuf[starthere - start + j], readbuf[j]);
				ret = -1;
				goto out_free;
			}
		}
	}

out_free:
	free(readbuf);
	return ret;
}

336
struct flashchip *probe_flash(struct flashchip *first_flash, int force)
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
337
{
338
	struct flashchip *flash;
339
	unsigned long base = 0, size;
340
	char *tmp;
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
341

342
	for (flash = first_flash; flash && flash->name; flash++) {
343
		if (chip_to_probe && strcmp(flash->name, chip_to_probe) != 0)
344
			continue;
345 346
		printf_debug("Probing for %s %s, %d KB: ",
			     flash->vendor, flash->name, flash->total_size);
Peter Stuge's avatar
Peter Stuge committed
347
		if (!flash->probe && !force) {
348 349 350
			printf_debug("failed! flashrom has no probe function for this flash chip.\n");
			continue;
		}
351 352 353 354 355 356 357 358 359
		if (!(buses_supported & flash->bustype)) {
			tmp = flashbuses_to_text(buses_supported);
			printf_debug("skipped. Host bus type %s ", tmp);
			free(tmp);
			tmp = flashbuses_to_text(flash->bustype);
			printf_debug("and chip bus type %s are incompatible.\n", tmp);
			free(tmp);
			continue;
		}
Stefan Reinauer's avatar
Stefan Reinauer committed
360

361
		size = flash->total_size * 1024;
Stefan Reinauer's avatar
Stefan Reinauer committed
362

363
		base = flashbase ? flashbase : (0xffffffff - size + 1);
364
		flash->virtual_memory = (chipaddr)programmer_map_flash_region("flash chip", base, size);
365

366 367 368
		if (force)
			break;

369 370 371
		if (flash->probe(flash) != 1)
			goto notfound;

372 373
		if (first_flash == flashchips
		    || flash->model_id != GENERIC_DEVICE_ID)
374
			break;
Stefan Reinauer's avatar
Stefan Reinauer committed
375

376
notfound:
377
		programmer_unmap_flash_region((void *)flash->virtual_memory, size);
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
378
	}
Uwe Hermann's avatar
Uwe Hermann committed
379

380 381 382 383
	if (!flash || !flash->name)
		return NULL;

	printf("Found chip \"%s %s\" (%d KB) at physical address 0x%lx.\n",
Peter Stuge's avatar
Peter Stuge committed
384
	       flash->vendor, flash->name, flash->total_size, base);
385
	return flash;
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
386 387
}

Stefan Reinauer's avatar
Stefan Reinauer committed
388
int verify_flash(struct flashchip *flash, uint8_t *buf)
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
389
{
390
	int ret;
391
	int total_size = flash->total_size * 1024;
392

393
	printf("Verifying flash... ");
394

395
	ret = verify_range(flash, buf, 0, total_size, NULL);
396

397 398
	if (!ret)
		printf("VERIFIED.          \n");
399

400
	return ret;
Ronald G. Minnich's avatar
Fixes  
Ronald G. Minnich committed
401 402
}

403
int read_flash(struct flashchip *flash, char *filename)
404 405 406 407 408
{
	unsigned long numbytes;
	FILE *image;
	unsigned long size = flash->total_size * 1024;
	unsigned char *buf = calloc(size, sizeof(char));
409 410 411 412 413

	if (!filename) {
		printf("Error: No filename specified.\n");
		return 1;
	}
414 415 416 417 418
	if ((image = fopen(filename, "w")) == NULL) {
		perror(filename);
		exit(1);
	}
	printf("Reading flash... ");
419 420 421 422 423
	if (!flash->read) {
		printf("FAILED!\n");
		fprintf(stderr, "ERROR: flashrom has no read function for this flash chip.\n");
		return 1;
	} else
424
		flash->read(flash, buf, 0, size);
425 426 427

	numbytes = fwrite(buf, 1, size, image);
	fclose(image);
428
	free(buf);
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
	printf("%s.\n", numbytes == size ? "done" : "FAILED");
	if (numbytes != size)
		return 1;
	return 0;
}

int erase_flash(struct flashchip *flash)
{
	uint32_t erasedbytes;
	unsigned long size = flash->total_size * 1024;
	unsigned char *buf = calloc(size, sizeof(char));
	printf("Erasing flash chip... ");
	if (NULL == flash->erase) {
		printf("FAILED!\n");
		fprintf(stderr, "ERROR: flashrom has no erase function for this flash chip.\n");
		return 1;
	}
446 447
	flash->erase(flash);

448 449 450
	/* FIXME: The lines below are superfluous. We should check the result
	 * of flash->erase(flash) instead.
	 */
451 452 453 454 455
	if (!flash->read) {
		printf("FAILED!\n");
		fprintf(stderr, "ERROR: flashrom has no read function for this flash chip.\n");
		return 1;
	} else
456
		flash->read(flash, buf, 0, size);
457

458 459 460 461 462 463 464 465 466 467 468
	for (erasedbytes = 0; erasedbytes < size; erasedbytes++)
		if (0xff != buf[erasedbytes]) {
			printf("FAILED!\n");
			fprintf(stderr, "ERROR at 0x%08x: Expected=0xff, Read=0x%02x\n",
				erasedbytes, buf[erasedbytes]);
			return 1;
		}
	printf("SUCCESS.\n");
	return 0;
}

Ronald G. Minnich's avatar
Ronald G. Minnich committed
469 470
void usage(const char *name)
{
471
	printf("usage: %s [-VfLzhR] [-E|-r file|-w file|-v file] [-c chipname]\n"
472
              "       [-m [vendor:]part] [-l file] [-i image] [-p programmer]\n\n", name);
473

474 475 476 477
	printf("Please note that the command line interface for flashrom will "
		"change before\nflashrom 1.0. Do not use flashrom in scripts "
		"or other automated tools without\nchecking that your flashrom"
		" version won't interpret options in a different way.\n\n");
478

479
	printf
480 481 482
	    ("   -r | --read:                      read flash and save into file\n"
	     "   -w | --write:                     write file into flash\n"
	     "   -v | --verify:                    verify flash against file\n"
483
	     "   -n | --noverify:                  don't verify flash against file\n"
484 485 486 487 488
	     "   -E | --erase:                     erase flash device\n"
	     "   -V | --verbose:                   more verbose output\n"
	     "   -c | --chip <chipname>:           probe only for specified flash chip\n"
	     "   -m | --mainboard <[vendor:]part>: override mainboard settings\n"
	     "   -f | --force:                     force write without checking image\n"
489
	     "   -l | --layout <file.layout>:      read ROM layout from file\n"
490
	     "   -i | --image <name>:              only flash image name from flash layout\n"
491
	     "   -L | --list-supported:            print supported devices\n"
492
	     "   -z | --list-supported-wiki:       print supported devices in wiki syntax\n"
493
	     "   -p | --programmer <name>:         specify the programmer device\n"
494
	     "                                     (internal, dummy, nic3com, satasii,\n"
495
	     "                                     it87spi, ft2232spi, serprog)\n"
496
	     "   -h | --help:                      print this help text\n"
497
	     "   -R | --version:                   print the version (release)\n"
498 499
	     "\nYou can specify one of -E, -r, -w, -v or no operation. If no operation is\n"
	     "specified, then all that happens is that flash info is dumped.\n\n");
500
	exit(1);
Ronald G. Minnich's avatar
Ronald G. Minnich committed
501 502
}

503 504
void print_version(void)
{
Carl-Daniel Hailfinger's avatar
Carl-Daniel Hailfinger committed
505
	printf("flashrom v%s\n", FLASHROM_VERSION);
506 507
}

508
int main(int argc, char *argv[])
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
509
{
510
	uint8_t *buf;
511
	unsigned long size, numbytes;
512
	FILE *image;
Claus Gindhart's avatar
Claus Gindhart committed
513 514
	/* Probe for up to three flash chips. */
	struct flashchip *flash, *flashes[3];
515
	int opt;
516
	int option_index = 0;
Peter Stuge's avatar
Peter Stuge committed
517
	int force = 0;
518
	int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0;
519
	int dont_verify_it = 0, list_supported = 0, list_supported_wiki = 0;
520
	int operation_specified = 0;
Claus Gindhart's avatar
Claus Gindhart committed
521
	int ret = 0, i;
522

523 524 525 526 527
	static struct option long_options[] = {
		{"read", 0, 0, 'r'},
		{"write", 0, 0, 'w'},
		{"erase", 0, 0, 'E'},
		{"verify", 0, 0, 'v'},
528
		{"noverify", 0, 0, 'n'},
529 530 531 532 533 534
		{"chip", 1, 0, 'c'},
		{"mainboard", 1, 0, 'm'},
		{"verbose", 0, 0, 'V'},
		{"force", 0, 0, 'f'},
		{"layout", 1, 0, 'l'},
		{"image", 1, 0, 'i'},
535
		{"list-supported", 0, 0, 'L'},
536
		{"list-supported-wiki", 0, 0, 'z'},
537
		{"programmer", 1, 0, 'p'},
538
		{"help", 0, 0, 'h'},
539
		{"version", 0, 0, 'R'},
540
		{0, 0, 0, 0}
541
	};
542

543
	char *filename = NULL;
544

545
	char *tempstr = NULL, *tempstr2 = NULL;
546

547 548
	print_version();

549 550 551
	if (argc > 1) {
		/* Yes, print them. */
		int i;
552
		printf_debug("The arguments are:\n");
553
		for (i = 1; i < argc; ++i)
554
			printf_debug("%s\n", argv[i]);
555 556
	}

557
	setbuf(stdout, NULL);
558
	while ((opt = getopt_long(argc, argv, "rRwvnVEfc:m:l:i:p:Lzh",
559
				  long_options, &option_index)) != EOF) {
560 561
		switch (opt) {
		case 'r':
562 563 564 565 566
			if (++operation_specified > 1) {
				fprintf(stderr, "More than one operation "
					"specified. Aborting.\n");
				exit(1);
			}
567 568 569
			read_it = 1;
			break;
		case 'w':
570 571 572 573 574
			if (++operation_specified > 1) {
				fprintf(stderr, "More than one operation "
					"specified. Aborting.\n");
				exit(1);
			}
575 576 577
			write_it = 1;
			break;
		case 'v':
578 579 580 581 582
			if (++operation_specified > 1) {
				fprintf(stderr, "More than one operation "
					"specified. Aborting.\n");
				exit(1);
			}
583 584
			verify_it = 1;
			break;
585 586 587
		case 'n':
			dont_verify_it = 1;
			break;
588 589 590
		case 'c':
			chip_to_probe = strdup(optarg);
			break;
Ollie Lho's avatar
Ollie Lho committed
591 592 593
		case 'V':
			verbose = 1;
			break;
594
		case 'E':
595 596 597 598 599
			if (++operation_specified > 1) {
				fprintf(stderr, "More than one operation "
					"specified. Aborting.\n");
				exit(1);
			}
600 601
			erase_it = 1;
			break;
602 603 604
		case 'm':
			tempstr = strdup(optarg);
			strtok(tempstr, ":");
605
			tempstr2 = strtok(NULL, ":");
606
			if (tempstr2) {
607 608
				lb_vendor = tempstr;
				lb_part = tempstr2;
609
			} else {
610 611
				lb_vendor = NULL;
				lb_part = tempstr;
612 613 614
			}
			break;
		case 'f':
615
			force = 1;
616 617
			break;
		case 'l':
618
			tempstr = strdup(optarg);
619 620
			if (read_romlayout(tempstr))
				exit(1);
621 622
			break;
		case 'i':
623
			tempstr = strdup(optarg);
624 625
			find_romentry(tempstr);
			break;
626
		case 'L':
Uwe Hermann's avatar
Uwe Hermann committed
627
			list_supported = 1;
628
			break;
629 630 631
		case 'z':
			list_supported_wiki = 1;
			break;
632 633 634
		case 'p':
			if (strncmp(optarg, "internal", 8) == 0) {
				programmer = PROGRAMMER_INTERNAL;
635 636
			} else if (strncmp(optarg, "dummy", 5) == 0) {
				programmer = PROGRAMMER_DUMMY;
637 638
				if (optarg[5] == '=')
					dummytype = strdup(optarg + 6);
639 640
			} else if (strncmp(optarg, "nic3com", 7) == 0) {
				programmer = PROGRAMMER_NIC3COM;
641
				if (optarg[7] == '=')
642
					pcidev_bdf = strdup(optarg + 8);
643 644 645 646
			} else if (strncmp(optarg, "satasii", 7) == 0) {
				programmer = PROGRAMMER_SATASII;
				if (optarg[7] == '=')
					pcidev_bdf = strdup(optarg + 8);
647 648
			} else if (strncmp(optarg, "it87spi", 7) == 0) {
				programmer = PROGRAMMER_IT87SPI;
649 650
			} else if (strncmp(optarg, "ft2232spi", 9) == 0) {
				programmer = PROGRAMMER_FT2232SPI;
651 652 653 654
 			} else if (strncmp(optarg, "serprog", 7) == 0) {
 				programmer = PROGRAMMER_SERPROG;
 				if (optarg[7] == '=')
 					serprog_param = strdup(optarg + 8);
655 656 657 658 659
			} else {
				printf("Error: Unknown programmer.\n");
				exit(1);
			}
			break;
660
		case 'R':
661
			/* print_version() is always called during startup. */
662 663
			exit(0);
			break;
664
		case 'h':
665 666 667 668 669
		default:
			usage(argv[0]);
			break;
		}
	}
670

Uwe Hermann's avatar
Uwe Hermann committed
671 672 673 674 675 676 677
	if (list_supported) {
		print_supported_chips();
		print_supported_chipsets();
		print_supported_boards();
		printf("\nSupported PCI devices flashrom can use "
		       "as programmer:\n\n");
		print_supported_pcidevs(nics_3com);
678
		print_supported_pcidevs(satas_sii);
Uwe Hermann's avatar
Uwe Hermann committed
679 680 681
		exit(0);
	}

682
	if (list_supported_wiki) {
Uwe Hermann's avatar
Uwe Hermann committed
683
		print_wiki_tables();
684 685 686
		exit(0);
	}

687
	if (read_it && write_it) {
Uwe Hermann's avatar
Uwe Hermann committed
688
		printf("Error: -r and -w are mutually exclusive.\n");
689 690
		usage(argv[0]);
	}
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
691

692 693
	if (optind < argc)
		filename = argv[optind++];
Ronald G. Minnich's avatar
Ronald G. Minnich committed
694

695 696 697 698
	if (programmer_init()) {
		fprintf(stderr, "Error: Programmer initialization failed.\n");
		exit(1);
	}
699

700
	myusec_calibrate_delay();
701

Claus Gindhart's avatar
Claus Gindhart committed
702
	for (i = 0; i < ARRAY_SIZE(flashes); i++) {
703 704
		flashes[i] =
		    probe_flash(i ? flashes[i - 1] + 1 : flashchips, 0);
Claus Gindhart's avatar
Claus Gindhart committed
705 706 707 708 709 710 711 712 713 714 715 716
		if (!flashes[i])
			for (i++; i < ARRAY_SIZE(flashes); i++)
				flashes[i] = NULL;
	}

	if (flashes[1]) {
		printf("Multiple flash chips were detected:");
		for (i = 0; i < ARRAY_SIZE(flashes) && flashes[i]; i++)
			printf(" %s", flashes[i]->name);
		printf("\nPlease specify which chip to use with the -c <chipname> option.\n");
		exit(1);
	} else if (!flashes[0]) {
717
		printf("No EEPROM/flash device found.\n");
Peter Stuge's avatar
Peter Stuge committed
718 719 720 721 722 723 724 725 726 727 728 729 730 731 732
		if (!force || !chip_to_probe) {
			printf("If you know which flash chip you have, and if this version of flashrom\n");
			printf("supports a similar flash chip, you can try to force read your chip. Run:\n");
			printf("flashrom -f -r -c similar_supported_flash_chip filename\n");
			printf("\n");
			printf("Note: flashrom can never write when the flash chip isn't found automatically.\n");
		}
		if (force && read_it && chip_to_probe) {
			printf("Force read (-f -r -c) requested, forcing chip probe success:\n");
			flashes[0] = probe_flash(flashchips, 1);
			if (!flashes[0]) {
				printf("flashrom does not support a flash chip named '%s'.\n", chip_to_probe);
				printf("Run flashrom -L to view the hardware supported in this flashrom version.\n");
				exit(1);
			}
733
			return read_flash(flashes[0], filename);
Peter Stuge's avatar
Peter Stuge committed
734
		}
735
		// FIXME: flash writes stay enabled!
736 737
		exit(1);
	}
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
738

Claus Gindhart's avatar
Claus Gindhart committed
739 740
	flash = flashes[0];

741 742 743 744 745 746 747 748 749 750 751 752 753
	if (TEST_OK_MASK != (flash->tested & TEST_OK_MASK)) {
		printf("===\n");
		if (flash->tested & TEST_BAD_MASK) {
			printf("This flash part has status NOT WORKING for operations:");
			if (flash->tested & TEST_BAD_PROBE)
				printf(" PROBE");
			if (flash->tested & TEST_BAD_READ)
				printf(" READ");
			if (flash->tested & TEST_BAD_ERASE)
				printf(" ERASE");
			if (flash->tested & TEST_BAD_WRITE)
				printf(" WRITE");
			printf("\n");
754 755 756 757 758
		}
		if ((!(flash->tested & TEST_BAD_PROBE) && !(flash->tested & TEST_OK_PROBE)) ||
		    (!(flash->tested & TEST_BAD_READ) && !(flash->tested & TEST_OK_READ)) ||
		    (!(flash->tested & TEST_BAD_ERASE) && !(flash->tested & TEST_OK_ERASE)) ||
		    (!(flash->tested & TEST_BAD_WRITE) && !(flash->tested & TEST_OK_WRITE))) {
759
			printf("This flash part has status UNTESTED for operations:");
760
			if (!(flash->tested & TEST_BAD_PROBE) && !(flash->tested & TEST_OK_PROBE))
761
				printf(" PROBE");
762
			if (!(flash->tested & TEST_BAD_READ) && !(flash->tested & TEST_OK_READ))
763
				printf(" READ");
764
			if (!(flash->tested & TEST_BAD_ERASE) && !(flash->tested & TEST_OK_ERASE))
765
				printf(" ERASE");
766
			if (!(flash->tested & TEST_BAD_WRITE) && !(flash->tested & TEST_OK_WRITE))
767 768 769
				printf(" WRITE");
			printf("\n");
		}
770 771 772 773 774 775
		printf("Please email a report to flashrom@coreboot.org if any "
		       "of the above operations\nwork correctly for you with "
		       "this flash part. Please include the flashrom\noutput "
		       "with the additional -V option for all operations you "
		       "tested (-V, -rV,\n-wV, -EV), and mention which "
		       "mainboard you tested. Thanks for your help!\n===\n");
776
	}
777

778 779 780 781 782 783
	if (!(read_it | write_it | verify_it | erase_it)) {
		printf("No operations were specified.\n");
		// FIXME: flash writes stay enabled!
		exit(1);
	}

784
	if (!filename && !erase_it) {
785 786 787
		printf("Error: No filename specified.\n");
		// FIXME: flash writes stay enabled!
		exit(1);
788 789
	}

790 791 792 793
	/* Always verify write operations unless -n is used. */
	if (write_it && !dont_verify_it)
		verify_it = 1;

794 795
	size = flash->total_size * 1024;
	buf = (uint8_t *) calloc(size, sizeof(char));
796

797
	if (erase_it) {
798
		if (erase_flash(flash))
799
			return 1;
800
	} else if (read_it) {
801
		if (read_flash(flash, filename))
802
			return 1;
803
	} else {
804 805
		struct stat image_stat;

806
		if ((image = fopen(filename, "r")) == NULL) {
807 808 809
			perror(filename);
			exit(1);
		}
810 811 812 813
		if (fstat(fileno(image), &image_stat) != 0) {
			perror(filename);
			exit(1);
		}
814
		if (image_stat.st_size != flash->total_size * 1024) {
Uwe Hermann's avatar
Uwe Hermann committed
815
			fprintf(stderr, "Error: Image size doesn't match\n");
816 817 818
			exit(1);
		}

819
		numbytes = fread(buf, 1, size, image);
Peter Stuge's avatar
Peter Stuge committed
820
		show_id(buf, size, force);
821
		fclose(image);
822 823 824 825
		if (numbytes != size) {
			fprintf(stderr, "Error: Failed to read file. Got %ld bytes, wanted %ld!\n", numbytes, size);
			return 1;
		}
826
	}
Ronald G. Minnich's avatar
Ronald G. Minnich committed
827

828 829
	// This should be moved into each flash part's code to do it 
	// cleanly. This does the job.
830
	/* FIXME: Adapt to the external flasher infrastructure. */
831
	handle_romentries(buf, (uint8_t *) flash->virtual_memory);
832

833
	// ////////////////////////////////////////////////////////////
834

835
	if (write_it) {
836
		printf("Writing flash chip... ");
837 838 839 840
		if (!flash->write) {
			fprintf(stderr, "Error: flashrom has no write function for this flash chip.\n");
			return 1;
		}
Stefan Reinauer's avatar
Stefan Reinauer committed
841
		ret |= flash->write(flash, buf);
842
		if (!ret) printf("COMPLETE.\n");
843
	}
844

845
	if (verify_it)
Stefan Reinauer's avatar
Stefan Reinauer committed
846
		ret |= verify_flash(flash, buf);
847

848 849
	programmer_shutdown();

Stefan Reinauer's avatar
Stefan Reinauer committed
850
	return ret;
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
851
}