eb0d8e0fd9669fbdf0287571c5de7af9cfc17aa9
[coreboot.git] / util / flashrom / flashrom.c
1 /*
2  * This file is part of the flashrom project.
3  *
4  * Copyright (C) 2000 Silicon Integrated System Corporation
5  * Copyright (C) 2004 Tyan Corp <yhlu@tyan.com>
6  * Copyright (C) 2005-2008 coresystems GmbH 
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
21  */
22
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <sys/mman.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <getopt.h>
33 #include <pci/pci.h>
34 /* for iopl */
35 #if defined (__sun) && (defined(__i386) || defined(__amd64))
36 #include <strings.h>
37 #include <sys/sysi86.h>
38 #include <sys/psw.h>
39 #include <asm/sunddi.h>
40 #endif
41 #include "flash.h"
42
43 char *chip_to_probe = NULL;
44 struct pci_access *pacc;        /* For board and chipset_enable */
45 int exclude_start_page, exclude_end_page;
46 int verbose = 0;
47 int fd_mem;
48
49 struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
50 {
51         struct pci_dev *temp;
52         struct pci_filter filter;
53
54         pci_filter_init(NULL, &filter);
55         filter.vendor = vendor;
56         filter.device = device;
57
58         for (temp = pacc->devices; temp; temp = temp->next)
59                 if (pci_filter_match(&filter, temp))
60                         return temp;
61
62         return NULL;
63 }
64
65 struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
66                               uint16_t card_vendor, uint16_t card_device)
67 {
68         struct pci_dev *temp;
69         struct pci_filter filter;
70
71         pci_filter_init(NULL, &filter);
72         filter.vendor = vendor;
73         filter.device = device;
74
75         for (temp = pacc->devices; temp; temp = temp->next)
76                 if (pci_filter_match(&filter, temp)) {
77                         if ((card_vendor ==
78                              pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
79                             && (card_device ==
80                                 pci_read_word(temp, PCI_SUBSYSTEM_ID)))
81                                 return temp;
82                 }
83
84         return NULL;
85 }
86
87 void mmap_errmsg()
88 {
89         if (EINVAL == errno) {
90                 fprintf(stderr, "In Linux this error can be caused by the CONFIG_NONPROMISC_DEVMEM (<2.6.27),\n");
91                 fprintf(stderr, "CONFIG_STRICT_DEVMEM (>=2.6.27) and CONFIG_X86_PAT kernel options.\n");
92                 fprintf(stderr, "Please check if either is enabled in your kernel before reporting a failure.\n");
93                 fprintf(stderr, "You can override CONFIG_X86_PAT at boot with the nopat kernel parameter but\n");
94                 fprintf(stderr, "disabling the other option unfortunately requires a kernel recompile. Sorry!\n");
95         }
96 }
97
98 void map_flash_registers(struct flashchip *flash)
99 {
100         volatile uint8_t *registers;
101         size_t size = flash->total_size * 1024;
102
103         registers = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
104                          fd_mem, (off_t) (0xFFFFFFFF - 0x400000 - size + 1));
105
106         if (registers == MAP_FAILED) {
107                 perror("Can't mmap registers using " MEM_DEV);
108                 mmap_errmsg();
109                 exit(1);
110         }
111         flash->virtual_registers = registers;
112 }
113
114 struct flashchip *probe_flash(struct flashchip *first_flash, int force)
115 {
116         volatile uint8_t *bios;
117         struct flashchip *flash;
118         unsigned long base = 0, size;
119
120         for (flash = first_flash; flash && flash->name; flash++) {
121                 if (chip_to_probe && strcmp(flash->name, chip_to_probe) != 0)
122                         continue;
123                 printf_debug("Probing for %s %s, %d KB: ",
124                              flash->vendor, flash->name, flash->total_size);
125                 if (!flash->probe && !force) {
126                         printf_debug("failed! flashrom has no probe function for this flash chip.\n");
127                         continue;
128                 }
129
130                 size = flash->total_size * 1024;
131
132                 /* If getpagesize() > size -> 
133                  * "Can't mmap memory using /dev/mem: Invalid argument"
134                  * This should never happen as we don't support any flash chips
135                  * smaller than 4k or 8k (yet).
136                  */
137
138                 if (getpagesize() > size) {
139                         /*
140                          * if a flash size of 0 is mapped, we map a single page
141                          * so we can probe in that area whether we know the
142                          * vendor at least.
143                          */
144                         size = getpagesize();
145                 }
146
147                 base = flashbase ? flashbase : (0xffffffff - size + 1);
148                 bios = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
149                             fd_mem, (off_t) base);
150                 if (bios == MAP_FAILED) {
151                         perror("Can't mmap memory using " MEM_DEV);
152                         mmap_errmsg();
153                         exit(1);
154                 }
155                 flash->virtual_memory = bios;
156
157                 if (force)
158                         break;
159
160                 if (flash->probe(flash) != 1)
161                         goto notfound;
162
163                 if (first_flash == flashchips
164                     || flash->model_id != GENERIC_DEVICE_ID)
165                         break;
166
167 notfound:
168                 munmap((void *)bios, size);
169         }
170
171         if (!flash || !flash->name)
172                 return NULL;
173
174         printf("Found chip \"%s %s\" (%d KB) at physical address 0x%lx.\n",
175                flash->vendor, flash->name, flash->total_size, base);
176         flashbase = base;
177         return flash;
178 }
179
180 int verify_flash(struct flashchip *flash, uint8_t *buf)
181 {
182         int idx;
183         int total_size = flash->total_size * 1024;
184         uint8_t *buf2 = (uint8_t *) calloc(total_size, sizeof(char));
185         if (flash->read == NULL)
186                 memcpy(buf2, (const char *)flash->virtual_memory, total_size);
187         else
188                 flash->read(flash, buf2);
189
190         printf("Verifying flash... ");
191
192         if (verbose)
193                 printf("address: 0x00000000\b\b\b\b\b\b\b\b\b\b");
194
195         for (idx = 0; idx < total_size; idx++) {
196                 if (verbose && ((idx & 0xfff) == 0xfff))
197                         printf("0x%08x", idx);
198
199                 if (*(buf2 + idx) != *(buf + idx)) {
200                         if (verbose)
201                                 printf("0x%08x FAILED!", idx);
202                         else
203                                 printf("FAILED at 0x%08x!", idx);
204                         printf("  Expected=0x%02x, Read=0x%02x\n",
205                                *(buf + idx), *(buf2 + idx));
206                         return 1;
207                 }
208
209                 if (verbose && ((idx & 0xfff) == 0xfff))
210                         printf("\b\b\b\b\b\b\b\b\b\b");
211         }
212         if (verbose)
213                 printf("\b\b\b\b\b\b\b\b\b\b ");
214
215         printf("VERIFIED.          \n");
216
217         return 0;
218 }
219
220 #define MAX(a, b) ((a) > (b) ? (a) : (b))
221 #define POS_PRINT(x) do { pos += strlen(x); printf(x); } while (0)
222
223 void print_supported_chips(void)
224 {
225         int okcol = 0, pos = 0;
226         struct flashchip *f;
227
228         for (f = flashchips; f->name != NULL; f++) {
229                 if (GENERIC_DEVICE_ID == f->model_id)
230                         continue;
231                 okcol = MAX(okcol, strlen(f->vendor) + 1 + strlen(f->name));
232         }
233         okcol = (okcol + 7) & ~7;
234
235         POS_PRINT("Supported flash chips:");
236         while (pos < okcol) {
237                 printf("\t");
238                 pos += 8 - (pos % 8);
239         }
240         printf("Tested OK operations:\tKnown BAD operations:\n\n");
241
242         for (f = flashchips; f->name != NULL; f++) {
243                 printf("%s %s", f->vendor, f->name);
244                 pos = strlen(f->vendor) + 1 + strlen(f->name);
245                 while (pos < okcol) {
246                         printf("\t");
247                         pos += 8 - (pos % 8);
248                 }
249                 if ((f->tested & TEST_OK_MASK)) {
250                         if ((f->tested & TEST_OK_PROBE))
251                                 POS_PRINT("PROBE ");
252                         if ((f->tested & TEST_OK_READ))
253                                 POS_PRINT("READ ");
254                         if ((f->tested & TEST_OK_ERASE))
255                                 POS_PRINT("ERASE ");
256                         if ((f->tested & TEST_OK_WRITE))
257                                 POS_PRINT("WRITE");
258                 }
259                 while (pos < okcol + 24) {
260                         printf("\t");
261                         pos += 8 - (pos % 8);
262                 }
263                 if ((f->tested & TEST_BAD_MASK)) {
264                         if ((f->tested & TEST_BAD_PROBE))
265                                 printf("PROBE ");
266                         if ((f->tested & TEST_BAD_READ))
267                                 printf("READ ");
268                         if ((f->tested & TEST_BAD_ERASE))
269                                 printf("ERASE ");
270                         if ((f->tested & TEST_BAD_WRITE))
271                                 printf("WRITE");
272                 }
273                 printf("\n");
274         }
275 }
276
277 void usage(const char *name)
278 {
279         printf("usage: %s [-rwvEVfLhR] [-c chipname] [-s exclude_start]\n",
280                name);
281         printf("       [-e exclude_end] [-m [vendor:]part] [-l file.layout] [-i imagename] [file]\n");
282         printf
283             ("   -r | --read:                      read flash and save into file\n"
284              "   -w | --write:                     write file into flash\n"
285              "   -v | --verify:                    verify flash against file\n"
286              "   -E | --erase:                     erase flash device\n"
287              "   -V | --verbose:                   more verbose output\n"
288              "   -c | --chip <chipname>:           probe only for specified flash chip\n"
289              "   -s | --estart <addr>:             exclude start position\n"
290              "   -e | --eend <addr>:               exclude end postion\n"
291              "   -m | --mainboard <[vendor:]part>: override mainboard settings\n"
292              "   -f | --force:                     force write without checking image\n"
293              "   -l | --layout <file.layout>:      read rom layout from file\n"
294              "   -i | --image <name>:              only flash image name from flash layout\n"
295              "   -L | --list-supported:            print supported devices\n"
296              "   -h | --help:                      print this help text\n"
297              "   -R | --version:                   print the version (release)\n"
298              "\n" " If no file is specified, then all that happens"
299              " is that flash info is dumped.\n\n");
300         exit(1);
301 }
302
303 void print_version(void)
304 {
305         printf("flashrom r%s\n", FLASHROM_VERSION);
306 }
307
308 int main(int argc, char *argv[])
309 {
310         uint8_t *buf;
311         unsigned long size, numbytes;
312         uint32_t erasedbytes;
313         FILE *image;
314         /* Probe for up to three flash chips. */
315         struct flashchip *flash, *flashes[3];
316         int opt;
317         int option_index = 0;
318         int force = 0;
319         int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0;
320         int ret = 0, i;
321 #ifdef __FreeBSD__
322         int io_fd;
323 #endif
324
325         static struct option long_options[] = {
326                 {"read", 0, 0, 'r'},
327                 {"write", 0, 0, 'w'},
328                 {"erase", 0, 0, 'E'},
329                 {"verify", 0, 0, 'v'},
330                 {"chip", 1, 0, 'c'},
331                 {"estart", 1, 0, 's'},
332                 {"eend", 1, 0, 'e'},
333                 {"mainboard", 1, 0, 'm'},
334                 {"verbose", 0, 0, 'V'},
335                 {"force", 0, 0, 'f'},
336                 {"layout", 1, 0, 'l'},
337                 {"image", 1, 0, 'i'},
338                 {"list-supported", 0, 0, 'L'},
339                 {"help", 0, 0, 'h'},
340                 {"version", 0, 0, 'R'},
341                 {0, 0, 0, 0}
342         };
343
344         char *filename = NULL;
345
346         unsigned int exclude_start_position = 0, exclude_end_position = 0;      // [x,y)
347         char *tempstr = NULL, *tempstr2 = NULL;
348
349         if (argc > 1) {
350                 /* Yes, print them. */
351                 int i;
352                 printf_debug("The arguments are:\n");
353                 for (i = 1; i < argc; ++i)
354                         printf_debug("%s\n", argv[i]);
355         }
356
357         setbuf(stdout, NULL);
358         while ((opt = getopt_long(argc, argv, "rRwvVEfc:s:e:m:l:i:Lh",
359                                   long_options, &option_index)) != EOF) {
360                 switch (opt) {
361                 case 'r':
362                         read_it = 1;
363                         break;
364                 case 'w':
365                         write_it = 1;
366                         break;
367                 case 'v':
368                         verify_it = 1;
369                         break;
370                 case 'c':
371                         chip_to_probe = strdup(optarg);
372                         break;
373                 case 'V':
374                         verbose = 1;
375                         break;
376                 case 'E':
377                         erase_it = 1;
378                         break;
379                 case 's':
380                         tempstr = strdup(optarg);
381                         sscanf(tempstr, "%x", &exclude_start_position);
382                         break;
383                 case 'e':
384                         tempstr = strdup(optarg);
385                         sscanf(tempstr, "%x", &exclude_end_position);
386                         break;
387                 case 'm':
388                         tempstr = strdup(optarg);
389                         strtok(tempstr, ":");
390                         tempstr2 = strtok(NULL, ":");
391                         if (tempstr2) {
392                                 lb_vendor = tempstr;
393                                 lb_part = tempstr2;
394                         } else {
395                                 lb_vendor = NULL;
396                                 lb_part = tempstr;
397                         }
398                         break;
399                 case 'f':
400                         force = 1;
401                         break;
402                 case 'l':
403                         tempstr = strdup(optarg);
404                         if (read_romlayout(tempstr))
405                                 exit(1);
406                         break;
407                 case 'i':
408                         tempstr = strdup(optarg);
409                         find_romentry(tempstr);
410                         break;
411                 case 'L':
412                         print_supported_chips();
413                         print_supported_chipsets();
414                         print_supported_boards();
415                         exit(0);
416                         break;
417                 case 'R':
418                         print_version();
419                         exit(0);
420                         break;
421                 case 'h':
422                 default:
423                         usage(argv[0]);
424                         break;
425                 }
426         }
427
428         if (read_it && write_it) {
429                 printf("Error: -r and -w are mutually exclusive.\n");
430                 usage(argv[0]);
431         }
432
433         if (optind < argc)
434                 filename = argv[optind++];
435
436         /* First get full io access */
437 #if defined (__sun) && (defined(__i386) || defined(__amd64))
438         if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) {
439 #elif defined(__FreeBSD__)
440         if ((io_fd = open("/dev/io", O_RDWR)) < 0) {
441 #else
442         if (iopl(3) != 0) {
443 #endif
444                 fprintf(stderr, "ERROR: Could not get IO privileges (%s).\nYou need to be root.\n", strerror(errno));
445                 exit(1);
446         }
447
448         /* Initialize PCI access for flash enables */
449         pacc = pci_alloc();     /* Get the pci_access structure */
450         /* Set all options you want -- here we stick with the defaults */
451         pci_init(pacc);         /* Initialize the PCI library */
452         pci_scan_bus(pacc);     /* We want to get the list of devices */
453
454         /* Open the memory device UNCACHED. That's important for MMIO. */
455         if ((fd_mem = open(MEM_DEV, O_RDWR | O_SYNC)) < 0) {
456                 perror("Error: Can not access memory using " MEM_DEV
457                        ". You need to be root.");
458                 exit(1);
459         }
460
461         myusec_calibrate_delay();
462
463         /* We look at the lbtable first to see if we need a
464          * mainboard specific flash enable sequence.
465          */
466         coreboot_init();
467
468         /* try to enable it. Failure IS an option, since not all motherboards
469          * really need this to be done, etc., etc.
470          */
471         ret = chipset_flash_enable();
472         if (ret == -2) {
473                 printf("WARNING: No chipset found. Flash detection "
474                        "will most likely fail.\n");
475         }
476
477         board_flash_enable(lb_vendor, lb_part);
478
479         for (i = 0; i < ARRAY_SIZE(flashes); i++) {
480                 flashes[i] =
481                     probe_flash(i ? flashes[i - 1] + 1 : flashchips, 0);
482                 if (!flashes[i])
483                         for (i++; i < ARRAY_SIZE(flashes); i++)
484                                 flashes[i] = NULL;
485         }
486
487         if (flashes[1]) {
488                 printf("Multiple flash chips were detected:");
489                 for (i = 0; i < ARRAY_SIZE(flashes) && flashes[i]; i++)
490                         printf(" %s", flashes[i]->name);
491                 printf("\nPlease specify which chip to use with the -c <chipname> option.\n");
492                 exit(1);
493         } else if (!flashes[0]) {
494                 printf("No EEPROM/flash device found.\n");
495                 if (!force || !chip_to_probe) {
496                         printf("If you know which flash chip you have, and if this version of flashrom\n");
497                         printf("supports a similar flash chip, you can try to force read your chip. Run:\n");
498                         printf("flashrom -f -r -c similar_supported_flash_chip filename\n");
499                         printf("\n");
500                         printf("Note: flashrom can never write when the flash chip isn't found automatically.\n");
501                 }
502                 if (force && read_it && chip_to_probe) {
503                         printf("Force read (-f -r -c) requested, forcing chip probe success:\n");
504                         flashes[0] = probe_flash(flashchips, 1);
505                         if (!flashes[0]) {
506                                 printf("flashrom does not support a flash chip named '%s'.\n", chip_to_probe);
507                                 printf("Run flashrom -L to view the hardware supported in this flashrom version.\n");
508                                 exit(1);
509                         }
510                         if (!filename) {
511                                 printf("Error: No filename specified.\n");
512                                 exit(1);
513                         }
514                         size = flashes[0]->total_size * 1024;
515                         buf = (uint8_t *) calloc(size, sizeof(char));
516
517                         if ((image = fopen(filename, "w")) == NULL) {
518                                 perror(filename);
519                                 exit(1);
520                         }
521                         printf("Force reading flash... ");
522                         if (!flashes[0]->read)
523                                 memcpy(buf, (const char *)flashes[0]->virtual_memory, size);
524                         else
525                                 flashes[0]->read(flashes[0], buf);
526
527                         if (exclude_end_position - exclude_start_position > 0)
528                                 memset(buf + exclude_start_position, 0,
529                                        exclude_end_position -
530                                        exclude_start_position);
531
532                         numbytes = fwrite(buf, 1, size, image);
533                         fclose(image);
534                         printf("%s.\n", numbytes == size ? "done" : "FAILED");
535                         free(buf);
536                         return numbytes != size;
537                 }
538                 // FIXME: flash writes stay enabled!
539                 exit(1);
540         }
541
542         flash = flashes[0];
543
544         if (TEST_OK_MASK != (flash->tested & TEST_OK_MASK)) {
545                 printf("===\n");
546                 if (flash->tested & TEST_BAD_MASK) {
547                         printf("This flash part has status NOT WORKING for operations:");
548                         if (flash->tested & TEST_BAD_PROBE)
549                                 printf(" PROBE");
550                         if (flash->tested & TEST_BAD_READ)
551                                 printf(" READ");
552                         if (flash->tested & TEST_BAD_ERASE)
553                                 printf(" ERASE");
554                         if (flash->tested & TEST_BAD_WRITE)
555                                 printf(" WRITE");
556                         printf("\n");
557                 }
558                 if ((!(flash->tested & TEST_BAD_PROBE) && !(flash->tested & TEST_OK_PROBE)) ||
559                     (!(flash->tested & TEST_BAD_READ) && !(flash->tested & TEST_OK_READ)) ||
560                     (!(flash->tested & TEST_BAD_ERASE) && !(flash->tested & TEST_OK_ERASE)) ||
561                     (!(flash->tested & TEST_BAD_WRITE) && !(flash->tested & TEST_OK_WRITE))) {
562                         printf("This flash part has status UNTESTED for operations:");
563                         if (!(flash->tested & TEST_BAD_PROBE) && !(flash->tested & TEST_OK_PROBE))
564                                 printf(" PROBE");
565                         if (!(flash->tested & TEST_BAD_READ) && !(flash->tested & TEST_OK_READ))
566                                 printf(" READ");
567                         if (!(flash->tested & TEST_BAD_ERASE) && !(flash->tested & TEST_OK_ERASE))
568                                 printf(" ERASE");
569                         if (!(flash->tested & TEST_BAD_WRITE) && !(flash->tested & TEST_OK_WRITE))
570                                 printf(" WRITE");
571                         printf("\n");
572                 }
573                 printf("Please email a report to flashrom@coreboot.org if any of the above operations\n");
574                 printf("work correctly for you with this flash part. Please include the full output\n");
575                 printf("from the program, including chipset found. Thank you for your help!\n");
576                 printf("===\n");
577         }
578
579         if (!(read_it | write_it | verify_it | erase_it)) {
580                 printf("No operations were specified.\n");
581                 // FIXME: flash writes stay enabled!
582                 exit(1);
583         }
584
585         if (!filename && !erase_it) {
586                 printf("Error: No filename specified.\n");
587                 // FIXME: flash writes stay enabled!
588                 exit(1);
589         }
590
591         size = flash->total_size * 1024;
592         buf = (uint8_t *) calloc(size, sizeof(char));
593
594         if (erase_it) {
595                 printf("Erasing flash chip... ");
596                 if (NULL == flash->erase) {
597                         printf("FAILED!\n");
598                         fprintf(stderr, "ERROR: flashrom has no erase function for this flash chip.\n");
599                         return 1;
600                 }
601                 flash->erase(flash);
602                 if (NULL == flash->read)
603                         memcpy(buf, (const char *)flash->virtual_memory, size);
604                 else
605                         flash->read(flash, buf);
606                 for (erasedbytes = 0; erasedbytes < size; erasedbytes++)
607                         if (0xff != buf[erasedbytes]) {
608                                 printf("FAILED!\n");
609                                 fprintf(stderr, "ERROR at 0x%08x: Expected=0xff, Read=0x%02x\n",
610                                         erasedbytes, buf[erasedbytes]);
611                                 return 1;
612                         }
613                 printf("SUCCESS.\n");
614                 return 0;
615         } else if (read_it) {
616                 if ((image = fopen(filename, "w")) == NULL) {
617                         perror(filename);
618                         exit(1);
619                 }
620                 printf("Reading flash... ");
621                 if (flash->read == NULL)
622                         memcpy(buf, (const char *)flash->virtual_memory, size);
623                 else
624                         flash->read(flash, buf);
625
626                 if (exclude_end_position - exclude_start_position > 0)
627                         memset(buf + exclude_start_position, 0,
628                                exclude_end_position - exclude_start_position);
629
630                 numbytes = fwrite(buf, 1, size, image);
631                 fclose(image);
632                 printf("%s.\n", numbytes == size ? "done" : "FAILED");
633                 if (numbytes != size)
634                         return 1;
635         } else {
636                 struct stat image_stat;
637
638                 if ((image = fopen(filename, "r")) == NULL) {
639                         perror(filename);
640                         exit(1);
641                 }
642                 if (fstat(fileno(image), &image_stat) != 0) {
643                         perror(filename);
644                         exit(1);
645                 }
646                 if (image_stat.st_size != flash->total_size * 1024) {
647                         fprintf(stderr, "Error: Image size doesn't match\n");
648                         exit(1);
649                 }
650
651                 numbytes = fread(buf, 1, size, image);
652                 show_id(buf, size, force);
653                 fclose(image);
654                 if (numbytes != size) {
655                         fprintf(stderr, "Error: Failed to read file. Got %ld bytes, wanted %ld!\n", numbytes, size);
656                         return 1;
657                 }
658         }
659
660         /* exclude range stuff. Nice idea, but at the moment it is only
661          * supported in hardware by the pm49fl004 chips. 
662          * Instead of implementing this for all chips I suggest advancing
663          * it to the rom layout feature below and drop exclude range
664          * completely once all flash chips can do rom layouts. stepan
665          */
666
667         // ////////////////////////////////////////////////////////////
668         if (exclude_end_position - exclude_start_position > 0)
669                 memcpy(buf + exclude_start_position,
670                        (const char *)flash->virtual_memory +
671                        exclude_start_position,
672                        exclude_end_position - exclude_start_position);
673
674         exclude_start_page = exclude_start_position / flash->page_size;
675         if ((exclude_start_position % flash->page_size) != 0) {
676                 exclude_start_page++;
677         }
678         exclude_end_page = exclude_end_position / flash->page_size;
679         // ////////////////////////////////////////////////////////////
680
681         // This should be moved into each flash part's code to do it 
682         // cleanly. This does the job.
683         handle_romentries(buf, (uint8_t *) flash->virtual_memory);
684
685         // ////////////////////////////////////////////////////////////
686
687         if (write_it) {
688                 if (!flash->write) {
689                         fprintf(stderr, "Error: flashrom has no write function for this flash chip.\n");
690                         return 1;
691                 }
692                 ret |= flash->write(flash, buf);
693         }
694
695         if (verify_it)
696                 ret |= verify_flash(flash, buf);
697
698 #ifdef __FreeBSD__
699         close(io_fd);
700 #endif
701         return ret;
702 }