blob: cf895a0a59d471608e8bf6ad6dad7ed281c81054 [file] [log] [blame]
rminnich8d3ff912003-10-25 17:01:29 +00001/*
stepane9134fb2007-04-11 23:31:45 +00002 * flashrom.c: Flash programming utility
rminnich8d3ff912003-10-25 17:01:29 +00003 *
4 * Copyright 2000 Silicon Integrated System Corporation
yhlu5d4383a2004-10-20 05:07:16 +00005 * Copyright 2004 Tyan Corp
6 * yhlu yhlu@tyan.com add exclude start and end option
stepan782fb172007-04-06 11:58:03 +00007 * Copyright 2005-2007 coresystems GmbH
stepanc98b80b2006-03-16 16:57:41 +00008 * Stefan Reinauer <stepan@coresystems.de> added rom layout
9 * support, and checking for suitable rom image, various fixes
10 * support for flashing the Technologic Systems 5300.
ollie6a600992005-11-26 21:55:36 +000011 *
rminnich8d3ff912003-10-25 17:01:29 +000012 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
rminnich8d3ff912003-10-25 17:01:29 +000026 */
27
28#include <errno.h>
29#include <fcntl.h>
30#include <sys/mman.h>
stepan1da96c02006-11-21 23:48:51 +000031#include <sys/types.h>
32#include <sys/stat.h>
rminnich8d3ff912003-10-25 17:01:29 +000033#include <unistd.h>
34#include <stdio.h>
rminnich8d3ff912003-10-25 17:01:29 +000035#include <string.h>
36#include <stdlib.h>
ollie6a600992005-11-26 21:55:36 +000037#include <getopt.h>
stepan927d4e22007-04-04 22:45:58 +000038#include <pci/pci.h>
39
40/* for iopl */
41#if defined (__sun) && (defined(__i386) || defined(__amd64))
42#include <strings.h>
43#include <sys/sysi86.h>
44#include <sys/psw.h>
45#include <asm/sunddi.h>
46#endif
rminnich8d3ff912003-10-25 17:01:29 +000047
48#include "flash.h"
ollie6a600992005-11-26 21:55:36 +000049#include "lbtable.h"
50#include "layout.h"
51#include "debug.h"
rminnich8d3ff912003-10-25 17:01:29 +000052
53char *chip_to_probe = NULL;
uwef6641642007-05-09 10:17:44 +000054struct pci_access *pacc; /* For board and chipset_enable */
stepan193c9c22005-12-18 16:41:10 +000055int exclude_start_page, exclude_end_page;
uwef6641642007-05-09 10:17:44 +000056int force = 0, verbose = 0;
stepan193c9c22005-12-18 16:41:10 +000057
stepan782fb172007-04-06 11:58:03 +000058int fd_mem;
59
stepan927d4e22007-04-04 22:45:58 +000060/*
61 *
62 */
uwef6641642007-05-09 10:17:44 +000063struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
stepan927d4e22007-04-04 22:45:58 +000064{
uwef6641642007-05-09 10:17:44 +000065 struct pci_dev *temp;
66 struct pci_filter filter;
stepan927d4e22007-04-04 22:45:58 +000067
uwef6641642007-05-09 10:17:44 +000068 pci_filter_init(NULL, &filter);
69 filter.vendor = vendor;
70 filter.device = device;
stepan927d4e22007-04-04 22:45:58 +000071
uwef6641642007-05-09 10:17:44 +000072 for (temp = pacc->devices; temp; temp = temp->next)
73 if (pci_filter_match(&filter, temp))
74 return temp;
stepan927d4e22007-04-04 22:45:58 +000075
uwef6641642007-05-09 10:17:44 +000076 return NULL;
stepan927d4e22007-04-04 22:45:58 +000077}
78
79/*
80 *
81 */
uwef6641642007-05-09 10:17:44 +000082struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
83 uint16_t card_vendor, uint16_t card_device)
stepan927d4e22007-04-04 22:45:58 +000084{
uwef6641642007-05-09 10:17:44 +000085 struct pci_dev *temp;
86 struct pci_filter filter;
stepan927d4e22007-04-04 22:45:58 +000087
uwef6641642007-05-09 10:17:44 +000088 pci_filter_init(NULL, &filter);
89 filter.vendor = vendor;
90 filter.device = device;
stepan927d4e22007-04-04 22:45:58 +000091
uwef6641642007-05-09 10:17:44 +000092 for (temp = pacc->devices; temp; temp = temp->next)
93 if (pci_filter_match(&filter, temp)) {
94 if ((card_vendor == pci_read_word(temp, 0x2C)) &&
95 (card_device == pci_read_word(temp, 0x2E)))
96 return temp;
97 }
stepan927d4e22007-04-04 22:45:58 +000098
uwef6641642007-05-09 10:17:44 +000099 return NULL;
stepan927d4e22007-04-04 22:45:58 +0000100}
101
ollie5b621572004-03-20 16:46:10 +0000102struct flashchip *probe_flash(struct flashchip *flash)
rminnich8d3ff912003-10-25 17:01:29 +0000103{
ollie6a600992005-11-26 21:55:36 +0000104 volatile uint8_t *bios;
stepan782fb172007-04-06 11:58:03 +0000105 unsigned long flash_baseaddr, size;
rminnich8d3ff912003-10-25 17:01:29 +0000106
ollie5672ac62004-03-17 22:22:08 +0000107 while (flash->name != NULL) {
ollief1845bd2004-03-27 00:18:15 +0000108 if (chip_to_probe && strcmp(flash->name, chip_to_probe) != 0) {
ollie5672ac62004-03-17 22:22:08 +0000109 flash++;
110 continue;
111 }
uwef6641642007-05-09 10:17:44 +0000112 printf_debug("Probing for %s, %d KB\n",
113 flash->name, flash->total_size);
stepan782fb172007-04-06 11:58:03 +0000114
ollie5672ac62004-03-17 22:22:08 +0000115 size = flash->total_size * 1024;
stepan782fb172007-04-06 11:58:03 +0000116
117#ifdef TS5300
118 // FIXME: Wrong place for this decision
119 flash_baseaddr = 0x9400000;
120#else
121 flash_baseaddr = (0xffffffff - size + 1);
122#endif
123
124 /* If getpagesize() > size ->
125 * `Error MMAP /dev/mem: Invalid argument'
126 * This should never happen as we don't support any flash chips
127 * smaller than 4k or 8k yet.
128 */
129
ollie5672ac62004-03-17 22:22:08 +0000130 if (getpagesize() > size) {
131 size = getpagesize();
stepan782fb172007-04-06 11:58:03 +0000132 printf("WARNING: size: %d -> %ld (page size)\n",
uwef6641642007-05-09 10:17:44 +0000133 flash->total_size * 1024, (unsigned long)size);
ollie5672ac62004-03-17 22:22:08 +0000134 }
stepan927d4e22007-04-04 22:45:58 +0000135
ollie5b621572004-03-20 16:46:10 +0000136 bios = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
uwef6641642007-05-09 10:17:44 +0000137 fd_mem, (off_t) flash_baseaddr);
ollie5672ac62004-03-17 22:22:08 +0000138 if (bios == MAP_FAILED) {
stepan927d4e22007-04-04 22:45:58 +0000139 perror("Error: Can't mmap " MEM_DEV ".");
ollie5672ac62004-03-17 22:22:08 +0000140 exit(1);
141 }
142 flash->virt_addr = bios;
rminnich8d3ff912003-10-25 17:01:29 +0000143
ollie5672ac62004-03-17 22:22:08 +0000144 if (flash->probe(flash) == 1) {
ollie5b621572004-03-20 16:46:10 +0000145 printf("%s found at physical address: 0x%lx\n",
stepan782fb172007-04-06 11:58:03 +0000146 flash->name, flash_baseaddr);
ollie5672ac62004-03-17 22:22:08 +0000147 return flash;
148 }
uwef6641642007-05-09 10:17:44 +0000149 munmap((void *)bios, size);
stepanc98b80b2006-03-16 16:57:41 +0000150
ollie5672ac62004-03-17 22:22:08 +0000151 flash++;
rminnich8d3ff912003-10-25 17:01:29 +0000152 }
ollie5672ac62004-03-17 22:22:08 +0000153 return NULL;
rminnich8d3ff912003-10-25 17:01:29 +0000154}
155
stepan193c9c22005-12-18 16:41:10 +0000156int verify_flash(struct flashchip *flash, uint8_t *buf)
rminnich8d3ff912003-10-25 17:01:29 +0000157{
stepanc98b80b2006-03-16 16:57:41 +0000158 int idx;
ollie5b621572004-03-20 16:46:10 +0000159 int total_size = flash->total_size * 1024;
ollie6a600992005-11-26 21:55:36 +0000160 volatile uint8_t *bios = flash->virt_addr;
rminnich8d3ff912003-10-25 17:01:29 +0000161
stepanc98b80b2006-03-16 16:57:41 +0000162 printf("Verifying flash ");
uwef6641642007-05-09 10:17:44 +0000163
164 if (verbose)
165 printf("address: 0x00000000\b\b\b\b\b\b\b\b\b\b");
166
stepanc98b80b2006-03-16 16:57:41 +0000167 for (idx = 0; idx < total_size; idx++) {
uwef6641642007-05-09 10:17:44 +0000168 if (verbose && ((idx & 0xfff) == 0xfff))
stepanc98b80b2006-03-16 16:57:41 +0000169 printf("0x%08x", idx);
170
171 if (*(bios + idx) != *(buf + idx)) {
172 if (verbose) {
173 printf("0x%08x ", idx);
174 }
175 printf("- FAILED\n");
176 return 1;
ollie5672ac62004-03-17 22:22:08 +0000177 }
uwef6641642007-05-09 10:17:44 +0000178
179 if (verbose && ((idx & 0xfff) == 0xfff))
ollie5672ac62004-03-17 22:22:08 +0000180 printf("\b\b\b\b\b\b\b\b\b\b");
rminnich8d3ff912003-10-25 17:01:29 +0000181 }
uwef6641642007-05-09 10:17:44 +0000182 if (verbose)
stepanc98b80b2006-03-16 16:57:41 +0000183 printf("\b\b\b\b\b\b\b\b\b\b ");
uwef6641642007-05-09 10:17:44 +0000184
stepanc98b80b2006-03-16 16:57:41 +0000185 printf("- VERIFIED \n");
186 return 0;
rminnich8d3ff912003-10-25 17:01:29 +0000187}
188
rminnich8d3ff912003-10-25 17:01:29 +0000189void usage(const char *name)
190{
stepanc211b472006-08-03 10:49:09 +0000191 printf("usage: %s [-rwvEVfh] [-c chipname] [-s exclude_start]\n", name);
192 printf(" [-e exclude_end] [-m vendor:part] [-l file.layout] [-i imagename] [file]\n");
uwef6641642007-05-09 10:17:44 +0000193 printf
194 (" -r | --read: read flash and save into file\n"
195 " -w | --write: write file into flash (default when\n"
196 " file is specified)\n"
197 " -v | --verify: verify flash against file\n"
198 " -E | --erase: erase flash device\n"
199 " -V | --verbose: more verbose output\n"
200 " -c | --chip <chipname>: probe only for specified flash chip\n"
201 " -s | --estart <addr>: exclude start position\n"
202 " -e | --eend <addr>: exclude end postion\n"
203 " -m | --mainboard <vendor:part>: override mainboard settings\n"
204 " -f | --force: force write without checking image\n"
205 " -l | --layout <file.layout>: read rom layout from file\n"
206 " -i | --image <name>: only flash image name from flash layout\n"
207 "\n" " If no file is specified, then all that happens\n"
208 " is that flash info is dumped.\n\n");
ollie5672ac62004-03-17 22:22:08 +0000209 exit(1);
rminnich8d3ff912003-10-25 17:01:29 +0000210}
211
ollie5b621572004-03-20 16:46:10 +0000212int main(int argc, char *argv[])
rminnich8d3ff912003-10-25 17:01:29 +0000213{
ollie6a600992005-11-26 21:55:36 +0000214 uint8_t *buf;
ollie5672ac62004-03-17 22:22:08 +0000215 unsigned long size;
ollie5b621572004-03-20 16:46:10 +0000216 FILE *image;
217 struct flashchip *flash;
ollie5672ac62004-03-17 22:22:08 +0000218 int opt;
ollie6a600992005-11-26 21:55:36 +0000219 int option_index = 0;
uwef6641642007-05-09 10:17:44 +0000220 int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0;
stepan83eca252006-01-04 16:42:57 +0000221 int ret = 0;
ollie6a600992005-11-26 21:55:36 +0000222
uwef6641642007-05-09 10:17:44 +0000223 static struct option long_options[] = {
224 {"read", 0, 0, 'r'},
225 {"write", 0, 0, 'w'},
226 {"erase", 0, 0, 'E'},
227 {"verify", 0, 0, 'v'},
228 {"chip", 1, 0, 'c'},
229 {"estart", 1, 0, 's'},
230 {"eend", 1, 0, 'e'},
231 {"mainboard", 1, 0, 'm'},
232 {"verbose", 0, 0, 'V'},
233 {"force", 0, 0, 'f'},
234 {"layout", 1, 0, 'l'},
235 {"image", 1, 0, 'i'},
236 {"help", 0, 0, 'h'},
237 {0, 0, 0, 0}
ollie6a600992005-11-26 21:55:36 +0000238 };
uwef6641642007-05-09 10:17:44 +0000239
ollie5672ac62004-03-17 22:22:08 +0000240 char *filename = NULL;
rminnich8d3ff912003-10-25 17:01:29 +0000241
uwef6641642007-05-09 10:17:44 +0000242 unsigned int exclude_start_position = 0, exclude_end_position = 0; // [x,y)
243 char *tempstr = NULL, *tempstr2 = NULL;
yhlu5d4383a2004-10-20 05:07:16 +0000244
245 if (argc > 1) {
246 /* Yes, print them. */
247 int i;
uwef6641642007-05-09 10:17:44 +0000248 printf_debug("The arguments are:\n");
yhlu5d4383a2004-10-20 05:07:16 +0000249 for (i = 1; i < argc; ++i)
uwef6641642007-05-09 10:17:44 +0000250 printf_debug("%s\n", argv[i]);
yhlu5d4383a2004-10-20 05:07:16 +0000251 }
252
ollie5672ac62004-03-17 22:22:08 +0000253 setbuf(stdout, NULL);
uwef6641642007-05-09 10:17:44 +0000254 while ((opt = getopt_long(argc, argv, "rwvVEfc:s:e:m:l:i:h",
255 long_options, &option_index)) != EOF) {
ollie5672ac62004-03-17 22:22:08 +0000256 switch (opt) {
257 case 'r':
258 read_it = 1;
259 break;
260 case 'w':
261 write_it = 1;
262 break;
263 case 'v':
264 verify_it = 1;
265 break;
266 case 'c':
267 chip_to_probe = strdup(optarg);
268 break;
ollie077017b2004-03-18 20:27:33 +0000269 case 'V':
270 verbose = 1;
271 break;
ollie0eb62d62004-12-08 20:10:01 +0000272 case 'E':
273 erase_it = 1;
274 break;
yhlu5d4383a2004-10-20 05:07:16 +0000275 case 's':
276 tempstr = strdup(optarg);
uwef6641642007-05-09 10:17:44 +0000277 sscanf(tempstr, "%x", &exclude_start_position);
yhlu5d4383a2004-10-20 05:07:16 +0000278 break;
279 case 'e':
olliea4302802004-12-07 03:15:51 +0000280 tempstr = strdup(optarg);
uwef6641642007-05-09 10:17:44 +0000281 sscanf(tempstr, "%x", &exclude_end_position);
olliea4302802004-12-07 03:15:51 +0000282 break;
ollie6a600992005-11-26 21:55:36 +0000283 case 'm':
284 tempstr = strdup(optarg);
285 strtok(tempstr, ":");
uwef6641642007-05-09 10:17:44 +0000286 tempstr2 = strtok(NULL, ":");
ollie6a600992005-11-26 21:55:36 +0000287 if (tempstr2) {
uwef6641642007-05-09 10:17:44 +0000288 lb_vendor = tempstr;
289 lb_part = tempstr2;
ollie6a600992005-11-26 21:55:36 +0000290 } else {
291 printf("warning: ignored wrong format of"
uwef6641642007-05-09 10:17:44 +0000292 " mainboard: %s\n", tempstr);
ollie6a600992005-11-26 21:55:36 +0000293 }
294 break;
295 case 'f':
uwef6641642007-05-09 10:17:44 +0000296 force = 1;
ollie6a600992005-11-26 21:55:36 +0000297 break;
298 case 'l':
uwef6641642007-05-09 10:17:44 +0000299 tempstr = strdup(optarg);
stepan14566ee2007-04-14 16:32:59 +0000300 if (read_romlayout(tempstr))
301 exit(1);
ollie6a600992005-11-26 21:55:36 +0000302 break;
303 case 'i':
uwef6641642007-05-09 10:17:44 +0000304 tempstr = strdup(optarg);
ollie6a600992005-11-26 21:55:36 +0000305 find_romentry(tempstr);
306 break;
307 case 'h':
ollie5672ac62004-03-17 22:22:08 +0000308 default:
309 usage(argv[0]);
310 break;
311 }
312 }
yhlu5d4383a2004-10-20 05:07:16 +0000313
ollie5672ac62004-03-17 22:22:08 +0000314 if (read_it && write_it) {
315 printf("-r and -w are mutually exclusive\n");
316 usage(argv[0]);
317 }
rminnich8d3ff912003-10-25 17:01:29 +0000318
ollie5672ac62004-03-17 22:22:08 +0000319 if (optind < argc)
320 filename = argv[optind++];
rminnich8d3ff912003-10-25 17:01:29 +0000321
uwef6641642007-05-09 10:17:44 +0000322 /* First get full io access */
stepan927d4e22007-04-04 22:45:58 +0000323#if defined (__sun) && (defined(__i386) || defined(__amd64))
uwef6641642007-05-09 10:17:44 +0000324 if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) {
stepan927d4e22007-04-04 22:45:58 +0000325#else
326 if (iopl(3) != 0) {
327#endif
uwef6641642007-05-09 10:17:44 +0000328 fprintf(stderr, "ERROR: iopl failed: \"%s\"\n",
329 strerror(errno));
stepan927d4e22007-04-04 22:45:58 +0000330 exit(1);
331 }
332
uwef6641642007-05-09 10:17:44 +0000333 /* Initialize PCI access for flash enables */
stepan927d4e22007-04-04 22:45:58 +0000334 pacc = pci_alloc(); /* Get the pci_access structure */
335 /* Set all options you want -- here we stick with the defaults */
336 pci_init(pacc); /* Initialize the PCI library */
337 pci_scan_bus(pacc); /* We want to get the list of devices */
338
stepan782fb172007-04-06 11:58:03 +0000339 /* Open the memory device. A lot of functions need it */
340 if ((fd_mem = open(MEM_DEV, O_RDWR)) < 0) {
uwef6641642007-05-09 10:17:44 +0000341 perror("Error: Can not access memory using " MEM_DEV
342 ". You need to be root.");
stepan782fb172007-04-06 11:58:03 +0000343 exit(1);
344 }
345
ollie5672ac62004-03-17 22:22:08 +0000346 myusec_calibrate_delay();
ollie6a600992005-11-26 21:55:36 +0000347
348 /* We look at the lbtable first to see if we need a
349 * mainboard specific flash enable sequence.
350 */
351 linuxbios_init();
rminnich8d3ff912003-10-25 17:01:29 +0000352
ollie5672ac62004-03-17 22:22:08 +0000353 /* try to enable it. Failure IS an option, since not all motherboards
ollie6a600992005-11-26 21:55:36 +0000354 * really need this to be done, etc., etc.
ollie5672ac62004-03-17 22:22:08 +0000355 */
uwef6641642007-05-09 10:17:44 +0000356 ret = chipset_flash_enable();
357 if (ret == -2) {
358 printf("WARNING: No chipset found. Flash detection "
359 "will most likely fail.\n");
360 }
stepan927d4e22007-04-04 22:45:58 +0000361
uwef6641642007-05-09 10:17:44 +0000362 board_flash_enable(lb_vendor, lb_part);
ollie5b621572004-03-20 16:46:10 +0000363
364 if ((flash = probe_flash(flashchips)) == NULL) {
ollie6a600992005-11-26 21:55:36 +0000365 printf("No EEPROM/flash device found.\n");
ollie5672ac62004-03-17 22:22:08 +0000366 exit(1);
367 }
rminnich8d3ff912003-10-25 17:01:29 +0000368
stepan603f9552006-10-07 00:23:51 +0000369 printf("Flash part is %s (%d KB)\n", flash->name, flash->total_size);
ollie6a600992005-11-26 21:55:36 +0000370
ollie0eb62d62004-12-08 20:10:01 +0000371 if (!filename && !erase_it) {
ollie6a600992005-11-26 21:55:36 +0000372 // FIXME: Do we really want this feature implicitly?
373 printf("OK, only ENABLING flash write, but NOT FLASHING.\n");
ollie5672ac62004-03-17 22:22:08 +0000374 return 0;
375 }
ollie5672ac62004-03-17 22:22:08 +0000376
ollie6a600992005-11-26 21:55:36 +0000377 size = flash->total_size * 1024;
378 buf = (uint8_t *) calloc(size, sizeof(char));
uwef6641642007-05-09 10:17:44 +0000379
ollie0eb62d62004-12-08 20:10:01 +0000380 if (erase_it) {
381 printf("Erasing flash chip\n");
382 flash->erase(flash);
uwef6641642007-05-09 10:17:44 +0000383 exit(0);
ollie0eb62d62004-12-08 20:10:01 +0000384 } else if (read_it) {
ollie5b621572004-03-20 16:46:10 +0000385 if ((image = fopen(filename, "w")) == NULL) {
ollie5672ac62004-03-17 22:22:08 +0000386 perror(filename);
387 exit(1);
388 }
389 printf("Reading Flash...");
olliea3def632004-03-19 22:10:07 +0000390 if (flash->read == NULL)
uwef6641642007-05-09 10:17:44 +0000391 memcpy(buf, (const char *)flash->virt_addr, size);
ollie5672ac62004-03-17 22:22:08 +0000392 else
ollie5b621572004-03-20 16:46:10 +0000393 flash->read(flash, buf);
yhlu5d4383a2004-10-20 05:07:16 +0000394
olliea4302802004-12-07 03:15:51 +0000395 if (exclude_end_position - exclude_start_position > 0)
uwef6641642007-05-09 10:17:44 +0000396 memset(buf + exclude_start_position, 0,
397 exclude_end_position - exclude_start_position);
yhlu5d4383a2004-10-20 05:07:16 +0000398
ollie5672ac62004-03-17 22:22:08 +0000399 fwrite(buf, sizeof(char), size, image);
400 fclose(image);
401 printf("done\n");
402 } else {
stepan1da96c02006-11-21 23:48:51 +0000403 struct stat image_stat;
404
ollie5b621572004-03-20 16:46:10 +0000405 if ((image = fopen(filename, "r")) == NULL) {
ollie5672ac62004-03-17 22:22:08 +0000406 perror(filename);
407 exit(1);
408 }
stepan1da96c02006-11-21 23:48:51 +0000409 if (fstat(fileno(image), &image_stat) != 0) {
410 perror(filename);
411 exit(1);
412 }
uwef6641642007-05-09 10:17:44 +0000413 if (image_stat.st_size != flash->total_size * 1024) {
stepan6ef87752007-03-22 14:51:45 +0000414 fprintf(stderr, "Error: Image size doesnt match\n");
stepan1da96c02006-11-21 23:48:51 +0000415 exit(1);
416 }
417
ollie5b621572004-03-20 16:46:10 +0000418 fread(buf, sizeof(char), size, image);
ollie6a600992005-11-26 21:55:36 +0000419 show_id(buf, size);
ollie5672ac62004-03-17 22:22:08 +0000420 fclose(image);
421 }
422
ollie6a600992005-11-26 21:55:36 +0000423 /* exclude range stuff. Nice idea, but at the moment it is only
424 * supported in hardware by the pm49fl004 chips.
425 * Instead of implementing this for all chips I suggest advancing
426 * it to the rom layout feature below and drop exclude range
427 * completely once all flash chips can do rom layouts. stepan
428 */
uwef6641642007-05-09 10:17:44 +0000429
ollie6a600992005-11-26 21:55:36 +0000430 // ////////////////////////////////////////////////////////////
olliea4302802004-12-07 03:15:51 +0000431 if (exclude_end_position - exclude_start_position > 0)
uwef6641642007-05-09 10:17:44 +0000432 memcpy(buf + exclude_start_position,
433 (const char *)flash->virt_addr + exclude_start_position,
434 exclude_end_position - exclude_start_position);
olliea4302802004-12-07 03:15:51 +0000435
uwef6641642007-05-09 10:17:44 +0000436 exclude_start_page = exclude_start_position / flash->page_size;
437 if ((exclude_start_position % flash->page_size) != 0) {
olliea4302802004-12-07 03:15:51 +0000438 exclude_start_page++;
439 }
uwef6641642007-05-09 10:17:44 +0000440 exclude_end_page = exclude_end_position / flash->page_size;
ollie6a600992005-11-26 21:55:36 +0000441 // ////////////////////////////////////////////////////////////
yhlu5d4383a2004-10-20 05:07:16 +0000442
ollie6a600992005-11-26 21:55:36 +0000443 // This should be moved into each flash part's code to do it
444 // cleanly. This does the job.
uwef6641642007-05-09 10:17:44 +0000445 handle_romentries(buf, (uint8_t *) flash->virt_addr);
446
ollie6a600992005-11-26 21:55:36 +0000447 // ////////////////////////////////////////////////////////////
uwef6641642007-05-09 10:17:44 +0000448
ollie6a600992005-11-26 21:55:36 +0000449 if (write_it)
stepan83eca252006-01-04 16:42:57 +0000450 ret |= flash->write(flash, buf);
ollie6a600992005-11-26 21:55:36 +0000451
ollie5672ac62004-03-17 22:22:08 +0000452 if (verify_it)
stepan83eca252006-01-04 16:42:57 +0000453 ret |= verify_flash(flash, buf);
ollie6a600992005-11-26 21:55:36 +0000454
stepan83eca252006-01-04 16:42:57 +0000455 return ret;
rminnich8d3ff912003-10-25 17:01:29 +0000456}