flashrom.c 16.4 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 6
 * Copyright (C) 2000 Silicon Integrated System Corporation
 * Copyright (C) 2004 Tyan Corp <yhlu@tyan.com>
 * Copyright (C) 2005-2007 coresystems GmbH 
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
7
 *
8 9 10 11
 * 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
12
 *
13 14 15 16
 * 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
17
 *
18 19 20
 * 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
21 22 23 24 25
 */

#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
26 27
#include <sys/types.h>
#include <sys/stat.h>
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
28 29
#include <unistd.h>
#include <stdio.h>
Ronald G. Minnich's avatar
Ronald G. Minnich committed
30
#include <string.h>
Ronald G. Minnich's avatar
Ronald G. Minnich committed
31
#include <stdlib.h>
32
#include <getopt.h>
33 34 35 36 37 38 39 40
#include <pci/pci.h>
/* for iopl */
#if defined (__sun) && (defined(__i386) || defined(__amd64))
#include <strings.h>
#include <sys/sysi86.h>
#include <sys/psw.h>
#include <asm/sunddi.h>
#endif
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
41 42
#include "flash.h"

Ronald G. Minnich's avatar
Ronald G. Minnich committed
43
char *chip_to_probe = NULL;
44
struct pci_access *pacc;	/* For board and chipset_enable */
Stefan Reinauer's avatar
Stefan Reinauer committed
45
int exclude_start_page, exclude_end_page;
Peter Stuge's avatar
Peter Stuge committed
46
int verbose = 0;
Stefan Reinauer's avatar
Stefan Reinauer committed
47 48
int fd_mem;

49
struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
50
{
51 52
	struct pci_dev *temp;
	struct pci_filter filter;
53

54 55 56
	pci_filter_init(NULL, &filter);
	filter.vendor = vendor;
	filter.device = device;
57

58 59 60
	for (temp = pacc->devices; temp; temp = temp->next)
		if (pci_filter_match(&filter, temp))
			return temp;
61

62
	return NULL;
63 64
}

65 66
struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
			      uint16_t card_vendor, uint16_t card_device)
67
{
68 69 70 71 72 73 74 75 76 77 78 79 80
	struct pci_dev *temp;
	struct pci_filter filter;

	pci_filter_init(NULL, &filter);
	filter.vendor = vendor;
	filter.device = device;

	for (temp = pacc->devices; temp; temp = temp->next)
		if (pci_filter_match(&filter, temp)) {
			if ((card_vendor == pci_read_word(temp, 0x2C)) &&
			    (card_device == pci_read_word(temp, 0x2E)))
				return temp;
		}
81

82
	return NULL;
83 84
}

85 86 87 88 89 90
int map_flash_registers(struct flashchip *flash)
{
	volatile uint8_t *registers;
	size_t size = flash->total_size * 1024;

	registers = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
Uwe Hermann's avatar
Uwe Hermann committed
91
			 fd_mem, (off_t) (0xFFFFFFFF - 0x400000 - size + 1));
92 93 94 95 96 97 98 99 100 101

	if (registers == MAP_FAILED) {
		perror("Can't mmap registers using " MEM_DEV);
		exit(1);
	}
	flash->virtual_registers = registers;

	return 0;
}

Peter Stuge's avatar
Peter Stuge committed
102
struct flashchip *probe_flash(struct flashchip *flash, int force)
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
103
{
104
	volatile uint8_t *bios;
Stefan Reinauer's avatar
Stefan Reinauer committed
105
	unsigned long flash_baseaddr, size;
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
106

107
	while (flash->name != NULL) {
108
		if (chip_to_probe && strcmp(flash->name, chip_to_probe) != 0) {
109 110 111
			flash++;
			continue;
		}
112 113
		printf_debug("Probing for %s %s, %d KB: ",
			     flash->vendor, flash->name, flash->total_size);
Peter Stuge's avatar
Peter Stuge committed
114
		if (!flash->probe && !force) {
115 116 117 118
			printf_debug("failed! flashrom has no probe function for this flash chip.\n");
			flash++;
			continue;
		}
Stefan Reinauer's avatar
Stefan Reinauer committed
119

120
		size = flash->total_size * 1024;
Stefan Reinauer's avatar
Stefan Reinauer committed
121 122 123

#ifdef TS5300
		// FIXME: Wrong place for this decision
Stefan Reinauer's avatar
Stefan Reinauer committed
124
		// FIXME: This should be autodetected. It is trivial.
Stefan Reinauer's avatar
Stefan Reinauer committed
125 126 127 128 129 130
		flash_baseaddr = 0x9400000;
#else
		flash_baseaddr = (0xffffffff - size + 1);
#endif

		/* If getpagesize() > size -> 
Stefan Reinauer's avatar
Stefan Reinauer committed
131
		 * "Can't mmap memory using /dev/mem: Invalid argument"
Stefan Reinauer's avatar
Stefan Reinauer committed
132
		 * This should never happen as we don't support any flash chips
Stefan Reinauer's avatar
Stefan Reinauer committed
133
		 * smaller than 4k or 8k (yet).
Stefan Reinauer's avatar
Stefan Reinauer committed
134 135
		 */

136
		if (getpagesize() > size) {
137 138 139 140 141
			/*
			 * if a flash size of 0 is mapped, we map a single page
			 * so we can probe in that area whether we know the
			 * vendor at least.
			 */
142 143
			size = getpagesize();
		}
144

145
		bios = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
146
			    fd_mem, (off_t) flash_baseaddr);
147
		if (bios == MAP_FAILED) {
Stefan Reinauer's avatar
Stefan Reinauer committed
148
			perror("Can't mmap memory using " MEM_DEV);
149 150
			exit(1);
		}
151
		flash->virtual_memory = bios;
152

Peter Stuge's avatar
Peter Stuge committed
153
		if (force || flash->probe(flash) == 1) {
Uwe Hermann's avatar
Uwe Hermann committed
154 155 156
			printf("Found chip \"%s %s\" (%d KB) at physical address 0x%lx.\n",
			       flash->vendor, flash->name, flash->total_size,
			       flash_baseaddr);
157 158
			return flash;
		}
159
		munmap((void *)bios, size);
Stefan Reinauer's avatar
Stefan Reinauer committed
160

161
		flash++;
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
162
	}
Uwe Hermann's avatar
Uwe Hermann committed
163

164
	return NULL;
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
165 166
}

Stefan Reinauer's avatar
Stefan Reinauer committed
167
int verify_flash(struct flashchip *flash, uint8_t *buf)
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
168
{
Stefan Reinauer's avatar
Stefan Reinauer committed
169
	int idx;
170
	int total_size = flash->total_size * 1024;
171 172 173 174 175
	uint8_t *buf2 = (uint8_t *) calloc(total_size, sizeof(char));
	if (flash->read == NULL)
		memcpy(buf2, (const char *)flash->virtual_memory, total_size);
	else
		flash->read(flash, buf2);
176

177
	printf("Verifying flash... ");
178 179 180 181

	if (verbose)
		printf("address: 0x00000000\b\b\b\b\b\b\b\b\b\b");

Stefan Reinauer's avatar
Stefan Reinauer committed
182
	for (idx = 0; idx < total_size; idx++) {
183
		if (verbose && ((idx & 0xfff) == 0xfff))
Stefan Reinauer's avatar
Stefan Reinauer committed
184 185
			printf("0x%08x", idx);

186
		if (*(buf2 + idx) != *(buf + idx)) {
Stefan Reinauer's avatar
Stefan Reinauer committed
187 188 189
			if (verbose) {
				printf("0x%08x ", idx);
			}
190 191
			printf("FAILED!  Expected=0x%02x, Read=0x%02x\n",
				*(buf + idx), *(buf2 + idx));
Stefan Reinauer's avatar
Stefan Reinauer committed
192
			return 1;
193
		}
194 195

		if (verbose && ((idx & 0xfff) == 0xfff))
196
			printf("\b\b\b\b\b\b\b\b\b\b");
Ronald G. Minnich's avatar
Fixes  
Ronald G. Minnich committed
197
	}
198
	if (verbose)
Stefan Reinauer's avatar
Stefan Reinauer committed
199
		printf("\b\b\b\b\b\b\b\b\b\b ");
200

201
	printf("VERIFIED.          \n");
Uwe Hermann's avatar
Uwe Hermann committed
202

Stefan Reinauer's avatar
Stefan Reinauer committed
203
	return 0;
Ronald G. Minnich's avatar
Fixes  
Ronald G. Minnich committed
204 205
}

206 207 208 209 210 211 212
void print_supported_chips(void)
{
	int i;

	printf("Supported ROM chips:\n\n");

	for (i = 0; flashchips[i].name != NULL; i++)
213
		printf("%s %s\n", flashchips[i].vendor, flashchips[i].name);
214 215
}

Ronald G. Minnich's avatar
Ronald G. Minnich committed
216 217
void usage(const char *name)
{
218
	printf("usage: %s [-rwvEVfLhR] [-c chipname] [-s exclude_start]\n", name);
219
	printf("       [-e exclude_end] [-m [vendor:]part] [-l file.layout] [-i imagename] [file]\n");
220
	printf
221 222 223 224 225 226 227 228 229 230 231 232
	    ("   -r | --read:                      read flash and save into file\n"
	     "   -w | --write:                     write file into flash\n"
	     "   -v | --verify:                    verify flash against file\n"
	     "   -E | --erase:                     erase flash device\n"
	     "   -V | --verbose:                   more verbose output\n"
	     "   -c | --chip <chipname>:           probe only for specified flash chip\n"
	     "   -s | --estart <addr>:             exclude start position\n"
	     "   -e | --eend <addr>:               exclude end postion\n"
	     "   -m | --mainboard <[vendor:]part>: override mainboard settings\n"
	     "   -f | --force:                     force write without checking image\n"
	     "   -l | --layout <file.layout>:      read rom layout from file\n"
	     "   -i | --image <name>:              only flash image name from flash layout\n"
233 234
	     "   -L | --list-supported:            print supported devices\n"
	     "   -h | --help:                      print this help text\n"
235
	     "   -R | --version:                   print the version (release)\n"
236
	     "\n" " If no file is specified, then all that happens"
237
	     " is that flash info is dumped.\n\n");
238
	exit(1);
Ronald G. Minnich's avatar
Ronald G. Minnich committed
239 240
}

241 242 243 244 245
void print_version(void)
{
	printf("flashrom r%s\n", FLASHROM_VERSION);
}

246
int main(int argc, char *argv[])
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
247
{
248
	uint8_t *buf;
249
	unsigned long size;
250
	FILE *image;
Claus Gindhart's avatar
Claus Gindhart committed
251 252
	/* Probe for up to three flash chips. */
	struct flashchip *flash, *flashes[3];
253
	int opt;
254
	int option_index = 0;
Peter Stuge's avatar
Peter Stuge committed
255
	int force = 0;
256
	int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0;
Claus Gindhart's avatar
Claus Gindhart committed
257
	int ret = 0, i;
258 259 260
#ifdef __FreeBSD__
	int io_fd;
#endif
261

262 263 264 265 266 267 268 269 270 271 272 273 274
	static struct option long_options[] = {
		{"read", 0, 0, 'r'},
		{"write", 0, 0, 'w'},
		{"erase", 0, 0, 'E'},
		{"verify", 0, 0, 'v'},
		{"chip", 1, 0, 'c'},
		{"estart", 1, 0, 's'},
		{"eend", 1, 0, 'e'},
		{"mainboard", 1, 0, 'm'},
		{"verbose", 0, 0, 'V'},
		{"force", 0, 0, 'f'},
		{"layout", 1, 0, 'l'},
		{"image", 1, 0, 'i'},
275
		{"list-supported", 0, 0, 'L'},
276
		{"help", 0, 0, 'h'},
277
		{"version", 0, 0, 'R'},
278
		{0, 0, 0, 0}
279
	};
280

281
	char *filename = NULL;
282

283 284
	unsigned int exclude_start_position = 0, exclude_end_position = 0;	// [x,y)
	char *tempstr = NULL, *tempstr2 = NULL;
285 286 287 288

	if (argc > 1) {
		/* Yes, print them. */
		int i;
289
		printf_debug("The arguments are:\n");
290
		for (i = 1; i < argc; ++i)
291
			printf_debug("%s\n", argv[i]);
292 293
	}

294
	setbuf(stdout, NULL);
295
	while ((opt = getopt_long(argc, argv, "rRwvVEfc:s:e:m:l:i:Lh",
296
				  long_options, &option_index)) != EOF) {
297 298 299 300 301 302 303 304 305 306 307 308 309
		switch (opt) {
		case 'r':
			read_it = 1;
			break;
		case 'w':
			write_it = 1;
			break;
		case 'v':
			verify_it = 1;
			break;
		case 'c':
			chip_to_probe = strdup(optarg);
			break;
Ollie Lho's avatar
Ollie Lho committed
310 311 312
		case 'V':
			verbose = 1;
			break;
313 314 315
		case 'E':
			erase_it = 1;
			break;
316 317
		case 's':
			tempstr = strdup(optarg);
318
			sscanf(tempstr, "%x", &exclude_start_position);
319 320
			break;
		case 'e':
321
			tempstr = strdup(optarg);
322
			sscanf(tempstr, "%x", &exclude_end_position);
323
			break;
324 325 326
		case 'm':
			tempstr = strdup(optarg);
			strtok(tempstr, ":");
327
			tempstr2 = strtok(NULL, ":");
328
			if (tempstr2) {
329 330
				lb_vendor = tempstr;
				lb_part = tempstr2;
331
			} else {
332 333
				lb_vendor = NULL;
				lb_part = tempstr;
334 335 336
			}
			break;
		case 'f':
337
			force = 1;
338 339
			break;
		case 'l':
340
			tempstr = strdup(optarg);
341 342
			if (read_romlayout(tempstr))
				exit(1);
343 344
			break;
		case 'i':
345
			tempstr = strdup(optarg);
346 347
			find_romentry(tempstr);
			break;
348 349 350 351 352 353
		case 'L':
			print_supported_chips();
			print_supported_chipsets();
			print_supported_boards();
			exit(0);
			break;
354 355 356 357
		case 'R':
			print_version();
			exit(0);
			break;
358
		case 'h':
359 360 361 362 363
		default:
			usage(argv[0]);
			break;
		}
	}
364

365
	if (read_it && write_it) {
Uwe Hermann's avatar
Uwe Hermann committed
366
		printf("Error: -r and -w are mutually exclusive.\n");
367 368
		usage(argv[0]);
	}
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
369

370 371
	if (optind < argc)
		filename = argv[optind++];
Ronald G. Minnich's avatar
Ronald G. Minnich committed
372

373
	/* First get full io access */
374
#if defined (__sun) && (defined(__i386) || defined(__amd64))
375
	if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) {
376 377
#elif defined(__FreeBSD__)
	if ((io_fd = open("/dev/io", O_RDWR)) < 0) {
378 379 380
#else
	if (iopl(3) != 0) {
#endif
Stefan Reinauer's avatar
Stefan Reinauer committed
381
               fprintf(stderr, "ERROR: Could not get IO privileges (%s).\nYou need to be root.\n",
382
			strerror(errno));
383 384 385
		exit(1);
	}

386
	/* Initialize PCI access for flash enables */
387 388 389 390 391
	pacc = pci_alloc();	/* Get the pci_access structure */
	/* Set all options you want -- here we stick with the defaults */
	pci_init(pacc);		/* Initialize the PCI library */
	pci_scan_bus(pacc);	/* We want to get the list of devices */

392 393
	/* Open the memory device UNCACHED. That's important for MMIO. */
	if ((fd_mem = open(MEM_DEV, O_RDWR|O_SYNC)) < 0) {
394 395
		perror("Error: Can not access memory using " MEM_DEV
		       ". You need to be root.");
Stefan Reinauer's avatar
Stefan Reinauer committed
396 397 398
		exit(1);
	}

399
	myusec_calibrate_delay();
400 401 402 403

	/* We look at the lbtable first to see if we need a
	 * mainboard specific flash enable sequence.
	 */
Stefan Reinauer's avatar
Stefan Reinauer committed
404
	coreboot_init();
Ronald G. Minnich's avatar
Ronald G. Minnich committed
405

406
	/* try to enable it. Failure IS an option, since not all motherboards
407
	 * really need this to be done, etc., etc.
408
	 */
409 410 411 412 413
	ret = chipset_flash_enable();
	if (ret == -2) {
		printf("WARNING: No chipset found. Flash detection "
		       "will most likely fail.\n");
	}
414

415
	board_flash_enable(lb_vendor, lb_part);
416

Claus Gindhart's avatar
Claus Gindhart committed
417
	for (i = 0; i < ARRAY_SIZE(flashes); i++) {
Peter Stuge's avatar
Peter Stuge committed
418
		flashes[i] = probe_flash(i ? flashes[i - 1] + 1 : flashchips, 0);
Claus Gindhart's avatar
Claus Gindhart committed
419 420 421 422 423 424 425 426 427 428 429 430
		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]) {
431
		printf("No EEPROM/flash device found.\n");
Peter Stuge's avatar
Peter Stuge committed
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
		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);
			}
			size = flashes[0]->total_size * 1024;
			buf = (uint8_t *) calloc(size, sizeof(char));

			if ((image = fopen(filename, "w")) == NULL) {
				perror(filename);
				exit(1);
			}
			printf("Force reading flash...");
			if (!flashes[0]->read)
				memcpy(buf, (const char *)flashes[0]->virtual_memory, size);
			else
				flashes[0]->read(flashes[0], buf);

			if (exclude_end_position - exclude_start_position > 0)
				memset(buf + exclude_start_position, 0,
				       exclude_end_position - exclude_start_position);

			fwrite(buf, sizeof(char), size, image);
			fclose(image);
			printf("done\n");
			free(buf);
			exit(0);
		}
470
		// FIXME: flash writes stay enabled!
471 472
		exit(1);
	}
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
473

Claus Gindhart's avatar
Claus Gindhart committed
474 475
	flash = flashes[0];

476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
	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");
		} else {
			printf("This flash part has status UNTESTED for operations:");
			if (!(flash->tested & TEST_OK_PROBE))
				printf(" PROBE");
			if (!(flash->tested & TEST_OK_READ))
				printf(" READ");
			if (!(flash->tested & TEST_OK_ERASE))
				printf(" ERASE");
			if (!(flash->tested & TEST_OK_WRITE))
				printf(" WRITE");
			printf("\n");
		}
		printf("Please email a report to flashrom@coreboot.org if any of the above operations\n");
		printf("work correctly for you with this flash part. Please include the full output\n");
		printf("from the program, including chipset found. Thank you for your help!\n");
		printf("===\n");
	}
506

507 508 509 510 511 512
	if (!(read_it | write_it | verify_it | erase_it)) {
		printf("No operations were specified.\n");
		// FIXME: flash writes stay enabled!
		exit(1);
	}

513
	if (!filename && !erase_it) {
514 515 516
		printf("Error: No filename specified.\n");
		// FIXME: flash writes stay enabled!
		exit(1);
517 518
	}

519 520
	size = flash->total_size * 1024;
	buf = (uint8_t *) calloc(size, sizeof(char));
521

522
	if (erase_it) {
Uwe Hermann's avatar
Uwe Hermann committed
523
		printf("Erasing flash chip.\n");
524 525 526 527
		if (!flash->erase) {
			fprintf(stderr, "Error: flashrom has no erase function for this flash chip.\n");
			return 1;
		}
528
		flash->erase(flash);
529
		exit(0);
530
	} else if (read_it) {
531
		if ((image = fopen(filename, "w")) == NULL) {
532 533 534 535
			perror(filename);
			exit(1);
		}
		printf("Reading Flash...");
Ollie Lho's avatar
Ollie Lho committed
536
		if (flash->read == NULL)
537
			memcpy(buf, (const char *)flash->virtual_memory, size);
538
		else
539
			flash->read(flash, buf);
540

541
		if (exclude_end_position - exclude_start_position > 0)
542 543
			memset(buf + exclude_start_position, 0,
			       exclude_end_position - exclude_start_position);
544

545 546 547 548
		fwrite(buf, sizeof(char), size, image);
		fclose(image);
		printf("done\n");
	} else {
549 550
		struct stat image_stat;

551
		if ((image = fopen(filename, "r")) == NULL) {
552 553 554
			perror(filename);
			exit(1);
		}
555 556 557 558
		if (fstat(fileno(image), &image_stat) != 0) {
			perror(filename);
			exit(1);
		}
559
		if (image_stat.st_size != flash->total_size * 1024) {
Uwe Hermann's avatar
Uwe Hermann committed
560
			fprintf(stderr, "Error: Image size doesn't match\n");
561 562 563
			exit(1);
		}

564
		fread(buf, sizeof(char), size, image);
Peter Stuge's avatar
Peter Stuge committed
565
		show_id(buf, size, force);
566 567
		fclose(image);
	}
Ronald G. Minnich's avatar
Ronald G. Minnich committed
568

569 570 571 572 573 574
	/* exclude range stuff. Nice idea, but at the moment it is only
	 * supported in hardware by the pm49fl004 chips. 
	 * Instead of implementing this for all chips I suggest advancing
	 * it to the rom layout feature below and drop exclude range
	 * completely once all flash chips can do rom layouts. stepan
	 */
575

576
	// ////////////////////////////////////////////////////////////
577
	if (exclude_end_position - exclude_start_position > 0)
578
		memcpy(buf + exclude_start_position,
Uwe Hermann's avatar
Uwe Hermann committed
579 580
		       (const char *)flash->virtual_memory +
		       exclude_start_position,
581
		       exclude_end_position - exclude_start_position);
582

583 584
	exclude_start_page = exclude_start_position / flash->page_size;
	if ((exclude_start_position % flash->page_size) != 0) {
585 586
		exclude_start_page++;
	}
587
	exclude_end_page = exclude_end_position / flash->page_size;
588 589 590 591
	// ////////////////////////////////////////////////////////////

	// This should be moved into each flash part's code to do it 
	// cleanly. This does the job.
592
	handle_romentries(buf, (uint8_t *) flash->virtual_memory);
593

594
	// ////////////////////////////////////////////////////////////
595

596 597 598 599 600
	if (write_it) {
		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
601
		ret |= flash->write(flash, buf);
602
	}
603

604
	if (verify_it)
Stefan Reinauer's avatar
Stefan Reinauer committed
605
		ret |= verify_flash(flash, buf);
606

607 608 609
#ifdef __FreeBSD__
	close(io_fd);
#endif
Stefan Reinauer's avatar
Stefan Reinauer committed
610
	return ret;
Ronald G. Minnich's avatar
Dammit  
Ronald G. Minnich committed
611
}