blob: 04c86001d391c00182a032fcc167ee6920d5bd53 [file] [log] [blame]
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +00001/*
Uwe Hermann9a37ba62007-04-11 23:31:45 +00002 * flashrom.c: Flash programming utility
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +00003 *
4 * Copyright 2000 Silicon Integrated System Corporation
Yinghai Luad8ffd22004-10-20 05:07:16 +00005 * Copyright 2004 Tyan Corp
6 * yhlu yhlu@tyan.com add exclude start and end option
Stefan Reinauer70385642007-04-06 11:58:03 +00007 * Copyright 2005-2007 coresystems GmbH
Stefan Reinauerfcb63682006-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.
Ollie Lho184a4042005-11-26 21:55:36 +000011 *
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +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 *
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +000026 */
27
28#include <errno.h>
29#include <fcntl.h>
30#include <sys/mman.h>
Stefan Reinauer018aca82006-11-21 23:48:51 +000031#include <sys/types.h>
32#include <sys/stat.h>
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +000033#include <unistd.h>
34#include <stdio.h>
Ronald G. Minnichceec4202003-07-25 04:37:41 +000035#include <string.h>
Ronald G. Minnicheaab50b2003-09-12 22:41:53 +000036#include <stdlib.h>
Ollie Lho184a4042005-11-26 21:55:36 +000037#include <getopt.h>
Luc Verhaegen8e3a6002007-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
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +000047
48#include "flash.h"
Ollie Lho184a4042005-11-26 21:55:36 +000049#include "lbtable.h"
50#include "layout.h"
51#include "debug.h"
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +000052
Ronald G. Minnichceec4202003-07-25 04:37:41 +000053char *chip_to_probe = NULL;
Luc Verhaegen8e3a6002007-04-04 22:45:58 +000054struct pci_access *pacc; /* For board and chipset_enable */
Stefan Reinauere3705282005-12-18 16:41:10 +000055int exclude_start_page, exclude_end_page;
56int force=0, verbose=0;
57
Stefan Reinauer70385642007-04-06 11:58:03 +000058int fd_mem;
59
Luc Verhaegen8e3a6002007-04-04 22:45:58 +000060/*
61 *
62 */
63struct pci_dev *
64pci_dev_find(uint16_t vendor, uint16_t device)
65{
66 struct pci_dev *temp;
67 struct pci_filter filter;
68
69 pci_filter_init(NULL, &filter);
70 filter.vendor = vendor;
71 filter.device = device;
72
73 for (temp = pacc->devices; temp; temp = temp->next)
74 if (pci_filter_match(&filter, temp))
75 return temp;
76
77 return NULL;
78}
79
80/*
81 *
82 */
83struct pci_dev *
84pci_card_find(uint16_t vendor, uint16_t device,
85 uint16_t card_vendor, uint16_t card_device)
86{
87 struct pci_dev *temp;
88 struct pci_filter filter;
89
90 pci_filter_init(NULL, &filter);
91 filter.vendor = vendor;
92 filter.device = device;
93
94 for (temp = pacc->devices; temp; temp = temp->next)
95 if (pci_filter_match(&filter, temp)) {
96 if ((card_vendor == pci_read_word(temp, 0x2C)) &&
97 (card_device == pci_read_word(temp, 0x2E)))
98 return temp;
99 }
100
101 return NULL;
102}
103
Ollie Lho761bf1b2004-03-20 16:46:10 +0000104struct flashchip *probe_flash(struct flashchip *flash)
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +0000105{
Ollie Lho184a4042005-11-26 21:55:36 +0000106 volatile uint8_t *bios;
Stefan Reinauer70385642007-04-06 11:58:03 +0000107 unsigned long flash_baseaddr, size;
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +0000108
Ollie Lhocbbf1252004-03-17 22:22:08 +0000109 while (flash->name != NULL) {
Ollie Lho8b8897a2004-03-27 00:18:15 +0000110 if (chip_to_probe && strcmp(flash->name, chip_to_probe) != 0) {
Ollie Lhocbbf1252004-03-17 22:22:08 +0000111 flash++;
112 continue;
113 }
Stefan Reinauer70385642007-04-06 11:58:03 +0000114 printf_debug("Probing for %s, %d KB\n",
115 flash->name, flash->total_size);
116
Ollie Lhocbbf1252004-03-17 22:22:08 +0000117 size = flash->total_size * 1024;
Stefan Reinauer70385642007-04-06 11:58:03 +0000118
119#ifdef TS5300
120 // FIXME: Wrong place for this decision
121 flash_baseaddr = 0x9400000;
122#else
123 flash_baseaddr = (0xffffffff - size + 1);
124#endif
125
126 /* If getpagesize() > size ->
127 * `Error MMAP /dev/mem: Invalid argument'
128 * This should never happen as we don't support any flash chips
129 * smaller than 4k or 8k yet.
130 */
131
Ollie Lhocbbf1252004-03-17 22:22:08 +0000132 if (getpagesize() > size) {
133 size = getpagesize();
Stefan Reinauer70385642007-04-06 11:58:03 +0000134 printf("WARNING: size: %d -> %ld (page size)\n",
135 flash->total_size * 1024, (unsigned long) size);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000136 }
Luc Verhaegen8e3a6002007-04-04 22:45:58 +0000137
Ollie Lho761bf1b2004-03-20 16:46:10 +0000138 bios = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
Stefan Reinauer70385642007-04-06 11:58:03 +0000139 fd_mem, (off_t)flash_baseaddr );
Ollie Lhocbbf1252004-03-17 22:22:08 +0000140 if (bios == MAP_FAILED) {
Luc Verhaegen8e3a6002007-04-04 22:45:58 +0000141 perror("Error: Can't mmap " MEM_DEV ".");
Ollie Lhocbbf1252004-03-17 22:22:08 +0000142 exit(1);
143 }
144 flash->virt_addr = bios;
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +0000145
Ollie Lhocbbf1252004-03-17 22:22:08 +0000146 if (flash->probe(flash) == 1) {
Ollie Lho761bf1b2004-03-20 16:46:10 +0000147 printf("%s found at physical address: 0x%lx\n",
Stefan Reinauer70385642007-04-06 11:58:03 +0000148 flash->name, flash_baseaddr);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000149 return flash;
150 }
Ollie Lho761bf1b2004-03-20 16:46:10 +0000151 munmap((void *) bios, size);
Stefan Reinauerfcb63682006-03-16 16:57:41 +0000152
Ollie Lhocbbf1252004-03-17 22:22:08 +0000153 flash++;
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +0000154 }
Ollie Lhocbbf1252004-03-17 22:22:08 +0000155 return NULL;
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +0000156}
157
Stefan Reinauere3705282005-12-18 16:41:10 +0000158int verify_flash(struct flashchip *flash, uint8_t *buf)
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +0000159{
Stefan Reinauerfcb63682006-03-16 16:57:41 +0000160 int idx;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000161 int total_size = flash->total_size * 1024;
Ollie Lho184a4042005-11-26 21:55:36 +0000162 volatile uint8_t *bios = flash->virt_addr;
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +0000163
Stefan Reinauerfcb63682006-03-16 16:57:41 +0000164 printf("Verifying flash ");
165
166 if(verbose) printf("address: 0x00000000\b\b\b\b\b\b\b\b\b\b");
167
168 for (idx = 0; idx < total_size; idx++) {
169 if (verbose && ( (idx & 0xfff) == 0xfff ))
170 printf("0x%08x", idx);
171
172 if (*(bios + idx) != *(buf + idx)) {
173 if (verbose) {
174 printf("0x%08x ", idx);
175 }
176 printf("- FAILED\n");
177 return 1;
Ollie Lhocbbf1252004-03-17 22:22:08 +0000178 }
Stefan Reinauerfcb63682006-03-16 16:57:41 +0000179
180 if (verbose && ( (idx & 0xfff) == 0xfff ))
Ollie Lhocbbf1252004-03-17 22:22:08 +0000181 printf("\b\b\b\b\b\b\b\b\b\b");
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +0000182 }
Stefan Reinauerfcb63682006-03-16 16:57:41 +0000183 if (verbose)
184 printf("\b\b\b\b\b\b\b\b\b\b ");
185
186 printf("- VERIFIED \n");
187 return 0;
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +0000188}
189
Ronald G. Minnichc73ad982003-02-11 21:06:09 +0000190
Ronald G. Minniche5559572003-03-28 03:29:43 +0000191void usage(const char *name)
192{
Stefan Reinauerf8337dd2006-08-03 10:49:09 +0000193 printf("usage: %s [-rwvEVfh] [-c chipname] [-s exclude_start]\n", name);
194 printf(" [-e exclude_end] [-m vendor:part] [-l file.layout] [-i imagename] [file]\n");
195 printf(" -r | --read: read flash and save into file\n"
196 " -w | --write: write file into flash (default when\n"
197 " file is specified)\n"
198 " -v | --verify: verify flash against file\n"
199 " -E | --erase: erase flash device\n"
200 " -V | --verbose: more verbose output\n"
201 " -c | --chip <chipname>: probe only for specified flash chip\n"
202 " -s | --estart <addr>: exclude start position\n"
203 " -e | --eend <addr>: exclude end postion\n"
Ollie Lho184a4042005-11-26 21:55:36 +0000204 " -m | --mainboard <vendor:part>: override mainboard settings\n"
Stefan Reinauerf8337dd2006-08-03 10:49:09 +0000205 " -f | --force: force write without checking image\n"
206 " -l | --layout <file.layout>: read rom layout from file\n"
207 " -i | --image <name>: only flash image name from flash layout\n"
Ollie Lho184a4042005-11-26 21:55:36 +0000208 "\n"
Ollie Lhocbbf1252004-03-17 22:22:08 +0000209 " If no file is specified, then all that happens\n"
Stefan Reinauerf8337dd2006-08-03 10:49:09 +0000210 " is that flash info is dumped.\n\n");
Ollie Lhocbbf1252004-03-17 22:22:08 +0000211 exit(1);
Ronald G. Minniche5559572003-03-28 03:29:43 +0000212}
213
Ollie Lho761bf1b2004-03-20 16:46:10 +0000214int main(int argc, char *argv[])
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +0000215{
Ollie Lho184a4042005-11-26 21:55:36 +0000216 uint8_t *buf;
Ollie Lhocbbf1252004-03-17 22:22:08 +0000217 unsigned long size;
Ollie Lho761bf1b2004-03-20 16:46:10 +0000218 FILE *image;
219 struct flashchip *flash;
Ollie Lhocbbf1252004-03-17 22:22:08 +0000220 int opt;
Ollie Lho184a4042005-11-26 21:55:36 +0000221 int option_index = 0;
222 int read_it = 0,
223 write_it = 0,
224 erase_it = 0,
225 verify_it = 0;
Stefan Reinauer143da0b2006-01-04 16:42:57 +0000226 int ret = 0;
Ollie Lho184a4042005-11-26 21:55:36 +0000227
228 static struct option long_options[]= {
229 { "read", 0, 0, 'r' },
230 { "write", 0, 0, 'w' },
231 { "erase", 0, 0, 'E' },
232 { "verify", 0, 0, 'v' },
233 { "chip", 1, 0, 'c' },
234 { "estart", 1, 0, 's' },
235 { "eend", 1, 0, 'e' },
236 { "mainboard", 1, 0, 'm' },
237 { "verbose", 0, 0, 'V' },
238 { "force", 0, 0, 'f' },
239 { "layout", 1, 0, 'l' },
240 { "image", 1, 0, 'i' },
241 { "help", 0, 0, 'h' },
242 { 0, 0, 0, 0 }
243 };
244
Ollie Lhocbbf1252004-03-17 22:22:08 +0000245 char *filename = NULL;
Ronald G. Minnichceec4202003-07-25 04:37:41 +0000246
Yinghai Luad8ffd22004-10-20 05:07:16 +0000247
248 unsigned int exclude_start_position=0, exclude_end_position=0; // [x,y)
Ollie Lho184a4042005-11-26 21:55:36 +0000249 char *tempstr=NULL, *tempstr2=NULL;
Yinghai Luad8ffd22004-10-20 05:07:16 +0000250
251 if (argc > 1) {
252 /* Yes, print them. */
253 int i;
Ollie Lho184a4042005-11-26 21:55:36 +0000254 printf_debug ("The arguments are:\n");
Yinghai Luad8ffd22004-10-20 05:07:16 +0000255 for (i = 1; i < argc; ++i)
Ollie Lho184a4042005-11-26 21:55:36 +0000256 printf_debug ("%s\n", argv[i]);
Yinghai Luad8ffd22004-10-20 05:07:16 +0000257 }
258
Ollie Lhocbbf1252004-03-17 22:22:08 +0000259 setbuf(stdout, NULL);
Ollie Lho184a4042005-11-26 21:55:36 +0000260 while ((opt = getopt_long(argc, argv, "rwvVEfc:s:e:m:l:i:h", long_options,
261 &option_index)) != EOF) {
Ollie Lhocbbf1252004-03-17 22:22:08 +0000262 switch (opt) {
263 case 'r':
264 read_it = 1;
265 break;
266 case 'w':
267 write_it = 1;
268 break;
269 case 'v':
270 verify_it = 1;
271 break;
272 case 'c':
273 chip_to_probe = strdup(optarg);
274 break;
Ollie Lho789ad3d2004-03-18 20:27:33 +0000275 case 'V':
276 verbose = 1;
277 break;
Ollie Lhoefa28582004-12-08 20:10:01 +0000278 case 'E':
279 erase_it = 1;
280 break;
Yinghai Luad8ffd22004-10-20 05:07:16 +0000281 case 's':
282 tempstr = strdup(optarg);
283 sscanf(tempstr,"%x",&exclude_start_position);
284 break;
285 case 'e':
Ollie Lho98bea8a2004-12-07 03:15:51 +0000286 tempstr = strdup(optarg);
287 sscanf(tempstr,"%x",&exclude_end_position);
288 break;
Ollie Lho184a4042005-11-26 21:55:36 +0000289 case 'm':
290 tempstr = strdup(optarg);
291 strtok(tempstr, ":");
292 tempstr2=strtok(NULL, ":");
293 if (tempstr2) {
294 lb_vendor=tempstr;
295 lb_part=tempstr2;
296 } else {
297 printf("warning: ignored wrong format of"
298 " mainboard: %s\n", tempstr);
299 }
300 break;
301 case 'f':
302 force=1;
303 break;
304 case 'l':
305 tempstr=strdup(optarg);
Stefan Reinauer0a05d672007-04-14 16:32:59 +0000306 if (read_romlayout(tempstr))
307 exit(1);
Ollie Lho184a4042005-11-26 21:55:36 +0000308 break;
309 case 'i':
310 tempstr=strdup(optarg);
311 find_romentry(tempstr);
312 break;
313 case 'h':
Ollie Lhocbbf1252004-03-17 22:22:08 +0000314 default:
315 usage(argv[0]);
316 break;
317 }
318 }
Yinghai Luad8ffd22004-10-20 05:07:16 +0000319
Ollie Lhocbbf1252004-03-17 22:22:08 +0000320 if (read_it && write_it) {
321 printf("-r and -w are mutually exclusive\n");
322 usage(argv[0]);
323 }
Ronald G. Minniche5559572003-03-28 03:29:43 +0000324
Ollie Lhocbbf1252004-03-17 22:22:08 +0000325 if (optind < argc)
326 filename = argv[optind++];
Ronald G. Minniche5559572003-03-28 03:29:43 +0000327
Luc Verhaegen8e3a6002007-04-04 22:45:58 +0000328 /* First get full io access */
329#if defined (__sun) && (defined(__i386) || defined(__amd64))
330 if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0){
331#else
332 if (iopl(3) != 0) {
333#endif
334 fprintf(stderr, "ERROR: iopl failed: \"%s\"\n", strerror(errno));
335 exit(1);
336 }
337
338 /* Initialize PCI access for flash enables */
339 pacc = pci_alloc(); /* Get the pci_access structure */
340 /* Set all options you want -- here we stick with the defaults */
341 pci_init(pacc); /* Initialize the PCI library */
342 pci_scan_bus(pacc); /* We want to get the list of devices */
343
Stefan Reinauer70385642007-04-06 11:58:03 +0000344 /* Open the memory device. A lot of functions need it */
345 if ((fd_mem = open(MEM_DEV, O_RDWR)) < 0) {
346 perror("Error: Can not access memory using " MEM_DEV ". You need to be root.");
347 exit(1);
348 }
349
Ollie Lhocbbf1252004-03-17 22:22:08 +0000350 myusec_calibrate_delay();
Ollie Lho184a4042005-11-26 21:55:36 +0000351
352 /* We look at the lbtable first to see if we need a
353 * mainboard specific flash enable sequence.
354 */
355 linuxbios_init();
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +0000356
Ollie Lhocbbf1252004-03-17 22:22:08 +0000357 /* try to enable it. Failure IS an option, since not all motherboards
Ollie Lho184a4042005-11-26 21:55:36 +0000358 * really need this to be done, etc., etc.
Ollie Lhocbbf1252004-03-17 22:22:08 +0000359 */
Luc Verhaegen8e3a6002007-04-04 22:45:58 +0000360 ret = chipset_flash_enable();
361 if (ret == -2)
362 printf("WARNING: No chipset found. Flash detection "
363 "will most likely fail.\n");
364
365 board_flash_enable(lb_vendor, lb_part);
366
Ollie Lho761bf1b2004-03-20 16:46:10 +0000367
368 if ((flash = probe_flash(flashchips)) == NULL) {
Ollie Lho184a4042005-11-26 21:55:36 +0000369 printf("No EEPROM/flash device found.\n");
Ollie Lhocbbf1252004-03-17 22:22:08 +0000370 exit(1);
371 }
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +0000372
Uwe Hermannd1915c12006-10-07 00:23:51 +0000373 printf("Flash part is %s (%d KB)\n", flash->name, flash->total_size);
Ollie Lho184a4042005-11-26 21:55:36 +0000374
Ollie Lhoefa28582004-12-08 20:10:01 +0000375 if (!filename && !erase_it) {
Ollie Lho184a4042005-11-26 21:55:36 +0000376 // FIXME: Do we really want this feature implicitly?
377 printf("OK, only ENABLING flash write, but NOT FLASHING.\n");
Ollie Lhocbbf1252004-03-17 22:22:08 +0000378 return 0;
379 }
Ollie Lhocbbf1252004-03-17 22:22:08 +0000380
Ollie Lho184a4042005-11-26 21:55:36 +0000381 size = flash->total_size * 1024;
382 buf = (uint8_t *) calloc(size, sizeof(char));
383
Ollie Lhoefa28582004-12-08 20:10:01 +0000384 if (erase_it) {
385 printf("Erasing flash chip\n");
386 flash->erase(flash);
387 exit(0);
388 } else if (read_it) {
Ollie Lho761bf1b2004-03-20 16:46:10 +0000389 if ((image = fopen(filename, "w")) == NULL) {
Ollie Lhocbbf1252004-03-17 22:22:08 +0000390 perror(filename);
391 exit(1);
392 }
393 printf("Reading Flash...");
Ollie Lho73eca802004-03-19 22:10:07 +0000394 if (flash->read == NULL)
Ollie Lhocbbf1252004-03-17 22:22:08 +0000395 memcpy(buf, (const char *) flash->virt_addr, size);
396 else
Ollie Lho761bf1b2004-03-20 16:46:10 +0000397 flash->read(flash, buf);
Yinghai Luad8ffd22004-10-20 05:07:16 +0000398
Ollie Lho98bea8a2004-12-07 03:15:51 +0000399 if (exclude_end_position - exclude_start_position > 0)
400 memset(buf+exclude_start_position, 0,
401 exclude_end_position-exclude_start_position);
Yinghai Luad8ffd22004-10-20 05:07:16 +0000402
Ollie Lhocbbf1252004-03-17 22:22:08 +0000403 fwrite(buf, sizeof(char), size, image);
404 fclose(image);
405 printf("done\n");
406 } else {
Stefan Reinauer018aca82006-11-21 23:48:51 +0000407 struct stat image_stat;
408
Ollie Lho761bf1b2004-03-20 16:46:10 +0000409 if ((image = fopen(filename, "r")) == NULL) {
Ollie Lhocbbf1252004-03-17 22:22:08 +0000410 perror(filename);
411 exit(1);
412 }
Stefan Reinauer018aca82006-11-21 23:48:51 +0000413 if (fstat(fileno(image), &image_stat) != 0) {
414 perror(filename);
415 exit(1);
416 }
417 if(image_stat.st_size!=flash->total_size*1024) {
Stefan Reinauerdf8a3c82007-03-22 14:51:45 +0000418 fprintf(stderr, "Error: Image size doesnt match\n");
Stefan Reinauer018aca82006-11-21 23:48:51 +0000419 exit(1);
420 }
421
Ollie Lho761bf1b2004-03-20 16:46:10 +0000422 fread(buf, sizeof(char), size, image);
Ollie Lho184a4042005-11-26 21:55:36 +0000423 show_id(buf, size);
Ollie Lhocbbf1252004-03-17 22:22:08 +0000424 fclose(image);
425 }
426
Ollie Lho184a4042005-11-26 21:55:36 +0000427 /* exclude range stuff. Nice idea, but at the moment it is only
428 * supported in hardware by the pm49fl004 chips.
429 * Instead of implementing this for all chips I suggest advancing
430 * it to the rom layout feature below and drop exclude range
431 * completely once all flash chips can do rom layouts. stepan
432 */
433
434 // ////////////////////////////////////////////////////////////
Ollie Lho98bea8a2004-12-07 03:15:51 +0000435 if (exclude_end_position - exclude_start_position > 0)
Ollie Lhod11f3612004-12-07 17:19:04 +0000436 memcpy(buf+exclude_start_position,
Ollie Lho98bea8a2004-12-07 03:15:51 +0000437 (const char *) flash->virt_addr+exclude_start_position,
438 exclude_end_position-exclude_start_position);
439
Yinghai Luad8ffd22004-10-20 05:07:16 +0000440 exclude_start_page = exclude_start_position/flash->page_size;
Ollie Lho98bea8a2004-12-07 03:15:51 +0000441 if ((exclude_start_position%flash->page_size) != 0) {
442 exclude_start_page++;
443 }
444 exclude_end_page = exclude_end_position/flash->page_size;
Ollie Lho184a4042005-11-26 21:55:36 +0000445 // ////////////////////////////////////////////////////////////
Yinghai Luad8ffd22004-10-20 05:07:16 +0000446
Ollie Lho184a4042005-11-26 21:55:36 +0000447 // This should be moved into each flash part's code to do it
448 // cleanly. This does the job.
449 handle_romentries(buf, (uint8_t *)flash->virt_addr);
450
451 // ////////////////////////////////////////////////////////////
452
453 if (write_it)
Stefan Reinauer143da0b2006-01-04 16:42:57 +0000454 ret |= flash->write(flash, buf);
Ollie Lho184a4042005-11-26 21:55:36 +0000455
Ollie Lhocbbf1252004-03-17 22:22:08 +0000456 if (verify_it)
Stefan Reinauer143da0b2006-01-04 16:42:57 +0000457 ret |= verify_flash(flash, buf);
Ollie Lho184a4042005-11-26 21:55:36 +0000458
Stefan Reinauer143da0b2006-01-04 16:42:57 +0000459 return ret;
Ronald G. Minnichf4cf2ba2002-01-29 18:26:26 +0000460}