blob: a05def76b3b6ab010848ff6ba72a03312b257f88 [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
stepanb584a472007-05-23 18:24:58 +0000119 // FIXME: This should be autodetected. It is trivial.
stepan782fb172007-04-06 11:58:03 +0000120 flash_baseaddr = 0x9400000;
121#else
122 flash_baseaddr = (0xffffffff - size + 1);
123#endif
124
125 /* If getpagesize() > size ->
stepanb584a472007-05-23 18:24:58 +0000126 * "Can't mmap memory using /dev/mem: Invalid argument"
stepan782fb172007-04-06 11:58:03 +0000127 * This should never happen as we don't support any flash chips
stepanb584a472007-05-23 18:24:58 +0000128 * smaller than 4k or 8k (yet).
stepan782fb172007-04-06 11:58:03 +0000129 */
130
ollie5672ac62004-03-17 22:22:08 +0000131 if (getpagesize() > size) {
132 size = getpagesize();
stepan782fb172007-04-06 11:58:03 +0000133 printf("WARNING: size: %d -> %ld (page size)\n",
uwef6641642007-05-09 10:17:44 +0000134 flash->total_size * 1024, (unsigned long)size);
ollie5672ac62004-03-17 22:22:08 +0000135 }
stepan927d4e22007-04-04 22:45:58 +0000136
ollie5b621572004-03-20 16:46:10 +0000137 bios = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
uwef6641642007-05-09 10:17:44 +0000138 fd_mem, (off_t) flash_baseaddr);
ollie5672ac62004-03-17 22:22:08 +0000139 if (bios == MAP_FAILED) {
stepanb584a472007-05-23 18:24:58 +0000140 perror("Can't mmap memory using " MEM_DEV);
ollie5672ac62004-03-17 22:22:08 +0000141 exit(1);
142 }
stepan7cd945e2007-05-23 17:20:56 +0000143 flash->virtual_memory = bios;
rminnich8d3ff912003-10-25 17:01:29 +0000144
ollie5672ac62004-03-17 22:22:08 +0000145 if (flash->probe(flash) == 1) {
ollie5b621572004-03-20 16:46:10 +0000146 printf("%s found at physical address: 0x%lx\n",
stepan782fb172007-04-06 11:58:03 +0000147 flash->name, flash_baseaddr);
ollie5672ac62004-03-17 22:22:08 +0000148 return flash;
149 }
uwef6641642007-05-09 10:17:44 +0000150 munmap((void *)bios, size);
stepanc98b80b2006-03-16 16:57:41 +0000151
ollie5672ac62004-03-17 22:22:08 +0000152 flash++;
rminnich8d3ff912003-10-25 17:01:29 +0000153 }
ollie5672ac62004-03-17 22:22:08 +0000154 return NULL;
rminnich8d3ff912003-10-25 17:01:29 +0000155}
156
stepan193c9c22005-12-18 16:41:10 +0000157int verify_flash(struct flashchip *flash, uint8_t *buf)
rminnich8d3ff912003-10-25 17:01:29 +0000158{
stepanc98b80b2006-03-16 16:57:41 +0000159 int idx;
ollie5b621572004-03-20 16:46:10 +0000160 int total_size = flash->total_size * 1024;
stepan7cd945e2007-05-23 17:20:56 +0000161 volatile uint8_t *bios = flash->virtual_memory;
rminnich8d3ff912003-10-25 17:01:29 +0000162
stepanc98b80b2006-03-16 16:57:41 +0000163 printf("Verifying flash ");
uwef6641642007-05-09 10:17:44 +0000164
165 if (verbose)
166 printf("address: 0x00000000\b\b\b\b\b\b\b\b\b\b");
167
stepanc98b80b2006-03-16 16:57:41 +0000168 for (idx = 0; idx < total_size; idx++) {
uwef6641642007-05-09 10:17:44 +0000169 if (verbose && ((idx & 0xfff) == 0xfff))
stepanc98b80b2006-03-16 16:57:41 +0000170 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;
ollie5672ac62004-03-17 22:22:08 +0000178 }
uwef6641642007-05-09 10:17:44 +0000179
180 if (verbose && ((idx & 0xfff) == 0xfff))
ollie5672ac62004-03-17 22:22:08 +0000181 printf("\b\b\b\b\b\b\b\b\b\b");
rminnich8d3ff912003-10-25 17:01:29 +0000182 }
uwef6641642007-05-09 10:17:44 +0000183 if (verbose)
stepanc98b80b2006-03-16 16:57:41 +0000184 printf("\b\b\b\b\b\b\b\b\b\b ");
uwef6641642007-05-09 10:17:44 +0000185
stepanc98b80b2006-03-16 16:57:41 +0000186 printf("- VERIFIED \n");
187 return 0;
rminnich8d3ff912003-10-25 17:01:29 +0000188}
189
rminnich8d3ff912003-10-25 17:01:29 +0000190void usage(const char *name)
191{
stepanc211b472006-08-03 10:49:09 +0000192 printf("usage: %s [-rwvEVfh] [-c chipname] [-s exclude_start]\n", name);
193 printf(" [-e exclude_end] [-m vendor:part] [-l file.layout] [-i imagename] [file]\n");
uwef6641642007-05-09 10:17:44 +0000194 printf
195 (" -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"
204 " -m | --mainboard <vendor:part>: override mainboard settings\n"
205 " -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"
208 "\n" " If no file is specified, then all that happens\n"
209 " is that flash info is dumped.\n\n");
ollie5672ac62004-03-17 22:22:08 +0000210 exit(1);
rminnich8d3ff912003-10-25 17:01:29 +0000211}
212
ollie5b621572004-03-20 16:46:10 +0000213int main(int argc, char *argv[])
rminnich8d3ff912003-10-25 17:01:29 +0000214{
ollie6a600992005-11-26 21:55:36 +0000215 uint8_t *buf;
ollie5672ac62004-03-17 22:22:08 +0000216 unsigned long size;
ollie5b621572004-03-20 16:46:10 +0000217 FILE *image;
218 struct flashchip *flash;
ollie5672ac62004-03-17 22:22:08 +0000219 int opt;
ollie6a600992005-11-26 21:55:36 +0000220 int option_index = 0;
uwef6641642007-05-09 10:17:44 +0000221 int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0;
stepan83eca252006-01-04 16:42:57 +0000222 int ret = 0;
ollie6a600992005-11-26 21:55:36 +0000223
uwef6641642007-05-09 10:17:44 +0000224 static struct option long_options[] = {
225 {"read", 0, 0, 'r'},
226 {"write", 0, 0, 'w'},
227 {"erase", 0, 0, 'E'},
228 {"verify", 0, 0, 'v'},
229 {"chip", 1, 0, 'c'},
230 {"estart", 1, 0, 's'},
231 {"eend", 1, 0, 'e'},
232 {"mainboard", 1, 0, 'm'},
233 {"verbose", 0, 0, 'V'},
234 {"force", 0, 0, 'f'},
235 {"layout", 1, 0, 'l'},
236 {"image", 1, 0, 'i'},
237 {"help", 0, 0, 'h'},
238 {0, 0, 0, 0}
ollie6a600992005-11-26 21:55:36 +0000239 };
uwef6641642007-05-09 10:17:44 +0000240
ollie5672ac62004-03-17 22:22:08 +0000241 char *filename = NULL;
rminnich8d3ff912003-10-25 17:01:29 +0000242
uwef6641642007-05-09 10:17:44 +0000243 unsigned int exclude_start_position = 0, exclude_end_position = 0; // [x,y)
244 char *tempstr = NULL, *tempstr2 = NULL;
yhlu5d4383a2004-10-20 05:07:16 +0000245
246 if (argc > 1) {
247 /* Yes, print them. */
248 int i;
uwef6641642007-05-09 10:17:44 +0000249 printf_debug("The arguments are:\n");
yhlu5d4383a2004-10-20 05:07:16 +0000250 for (i = 1; i < argc; ++i)
uwef6641642007-05-09 10:17:44 +0000251 printf_debug("%s\n", argv[i]);
yhlu5d4383a2004-10-20 05:07:16 +0000252 }
253
ollie5672ac62004-03-17 22:22:08 +0000254 setbuf(stdout, NULL);
uwef6641642007-05-09 10:17:44 +0000255 while ((opt = getopt_long(argc, argv, "rwvVEfc:s:e:m:l:i:h",
256 long_options, &option_index)) != EOF) {
ollie5672ac62004-03-17 22:22:08 +0000257 switch (opt) {
258 case 'r':
259 read_it = 1;
260 break;
261 case 'w':
262 write_it = 1;
263 break;
264 case 'v':
265 verify_it = 1;
266 break;
267 case 'c':
268 chip_to_probe = strdup(optarg);
269 break;
ollie077017b2004-03-18 20:27:33 +0000270 case 'V':
271 verbose = 1;
272 break;
ollie0eb62d62004-12-08 20:10:01 +0000273 case 'E':
274 erase_it = 1;
275 break;
yhlu5d4383a2004-10-20 05:07:16 +0000276 case 's':
277 tempstr = strdup(optarg);
uwef6641642007-05-09 10:17:44 +0000278 sscanf(tempstr, "%x", &exclude_start_position);
yhlu5d4383a2004-10-20 05:07:16 +0000279 break;
280 case 'e':
olliea4302802004-12-07 03:15:51 +0000281 tempstr = strdup(optarg);
uwef6641642007-05-09 10:17:44 +0000282 sscanf(tempstr, "%x", &exclude_end_position);
olliea4302802004-12-07 03:15:51 +0000283 break;
ollie6a600992005-11-26 21:55:36 +0000284 case 'm':
285 tempstr = strdup(optarg);
286 strtok(tempstr, ":");
uwef6641642007-05-09 10:17:44 +0000287 tempstr2 = strtok(NULL, ":");
ollie6a600992005-11-26 21:55:36 +0000288 if (tempstr2) {
uwef6641642007-05-09 10:17:44 +0000289 lb_vendor = tempstr;
290 lb_part = tempstr2;
ollie6a600992005-11-26 21:55:36 +0000291 } else {
292 printf("warning: ignored wrong format of"
uwef6641642007-05-09 10:17:44 +0000293 " mainboard: %s\n", tempstr);
ollie6a600992005-11-26 21:55:36 +0000294 }
295 break;
296 case 'f':
uwef6641642007-05-09 10:17:44 +0000297 force = 1;
ollie6a600992005-11-26 21:55:36 +0000298 break;
299 case 'l':
uwef6641642007-05-09 10:17:44 +0000300 tempstr = strdup(optarg);
stepan14566ee2007-04-14 16:32:59 +0000301 if (read_romlayout(tempstr))
302 exit(1);
ollie6a600992005-11-26 21:55:36 +0000303 break;
304 case 'i':
uwef6641642007-05-09 10:17:44 +0000305 tempstr = strdup(optarg);
ollie6a600992005-11-26 21:55:36 +0000306 find_romentry(tempstr);
307 break;
308 case 'h':
ollie5672ac62004-03-17 22:22:08 +0000309 default:
310 usage(argv[0]);
311 break;
312 }
313 }
yhlu5d4383a2004-10-20 05:07:16 +0000314
ollie5672ac62004-03-17 22:22:08 +0000315 if (read_it && write_it) {
316 printf("-r and -w are mutually exclusive\n");
317 usage(argv[0]);
318 }
rminnich8d3ff912003-10-25 17:01:29 +0000319
ollie5672ac62004-03-17 22:22:08 +0000320 if (optind < argc)
321 filename = argv[optind++];
rminnich8d3ff912003-10-25 17:01:29 +0000322
uwef6641642007-05-09 10:17:44 +0000323 /* First get full io access */
stepan927d4e22007-04-04 22:45:58 +0000324#if defined (__sun) && (defined(__i386) || defined(__amd64))
uwef6641642007-05-09 10:17:44 +0000325 if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) {
stepan927d4e22007-04-04 22:45:58 +0000326#else
327 if (iopl(3) != 0) {
328#endif
uwef6641642007-05-09 10:17:44 +0000329 fprintf(stderr, "ERROR: iopl failed: \"%s\"\n",
330 strerror(errno));
stepan927d4e22007-04-04 22:45:58 +0000331 exit(1);
332 }
333
uwef6641642007-05-09 10:17:44 +0000334 /* Initialize PCI access for flash enables */
stepan927d4e22007-04-04 22:45:58 +0000335 pacc = pci_alloc(); /* Get the pci_access structure */
336 /* Set all options you want -- here we stick with the defaults */
337 pci_init(pacc); /* Initialize the PCI library */
338 pci_scan_bus(pacc); /* We want to get the list of devices */
339
stepan782fb172007-04-06 11:58:03 +0000340 /* Open the memory device. A lot of functions need it */
341 if ((fd_mem = open(MEM_DEV, O_RDWR)) < 0) {
uwef6641642007-05-09 10:17:44 +0000342 perror("Error: Can not access memory using " MEM_DEV
343 ". You need to be root.");
stepan782fb172007-04-06 11:58:03 +0000344 exit(1);
345 }
346
ollie5672ac62004-03-17 22:22:08 +0000347 myusec_calibrate_delay();
ollie6a600992005-11-26 21:55:36 +0000348
349 /* We look at the lbtable first to see if we need a
350 * mainboard specific flash enable sequence.
351 */
352 linuxbios_init();
rminnich8d3ff912003-10-25 17:01:29 +0000353
ollie5672ac62004-03-17 22:22:08 +0000354 /* try to enable it. Failure IS an option, since not all motherboards
ollie6a600992005-11-26 21:55:36 +0000355 * really need this to be done, etc., etc.
ollie5672ac62004-03-17 22:22:08 +0000356 */
uwef6641642007-05-09 10:17:44 +0000357 ret = chipset_flash_enable();
358 if (ret == -2) {
359 printf("WARNING: No chipset found. Flash detection "
360 "will most likely fail.\n");
361 }
stepan927d4e22007-04-04 22:45:58 +0000362
uwef6641642007-05-09 10:17:44 +0000363 board_flash_enable(lb_vendor, lb_part);
ollie5b621572004-03-20 16:46:10 +0000364
365 if ((flash = probe_flash(flashchips)) == NULL) {
ollie6a600992005-11-26 21:55:36 +0000366 printf("No EEPROM/flash device found.\n");
ollie5672ac62004-03-17 22:22:08 +0000367 exit(1);
368 }
rminnich8d3ff912003-10-25 17:01:29 +0000369
stepan603f9552006-10-07 00:23:51 +0000370 printf("Flash part is %s (%d KB)\n", flash->name, flash->total_size);
ollie6a600992005-11-26 21:55:36 +0000371
ollie0eb62d62004-12-08 20:10:01 +0000372 if (!filename && !erase_it) {
ollie6a600992005-11-26 21:55:36 +0000373 // FIXME: Do we really want this feature implicitly?
374 printf("OK, only ENABLING flash write, but NOT FLASHING.\n");
ollie5672ac62004-03-17 22:22:08 +0000375 return 0;
376 }
ollie5672ac62004-03-17 22:22:08 +0000377
ollie6a600992005-11-26 21:55:36 +0000378 size = flash->total_size * 1024;
379 buf = (uint8_t *) calloc(size, sizeof(char));
uwef6641642007-05-09 10:17:44 +0000380
ollie0eb62d62004-12-08 20:10:01 +0000381 if (erase_it) {
382 printf("Erasing flash chip\n");
383 flash->erase(flash);
uwef6641642007-05-09 10:17:44 +0000384 exit(0);
ollie0eb62d62004-12-08 20:10:01 +0000385 } else if (read_it) {
ollie5b621572004-03-20 16:46:10 +0000386 if ((image = fopen(filename, "w")) == NULL) {
ollie5672ac62004-03-17 22:22:08 +0000387 perror(filename);
388 exit(1);
389 }
390 printf("Reading Flash...");
olliea3def632004-03-19 22:10:07 +0000391 if (flash->read == NULL)
stepan7cd945e2007-05-23 17:20:56 +0000392 memcpy(buf, (const char *)flash->virtual_memory, size);
ollie5672ac62004-03-17 22:22:08 +0000393 else
ollie5b621572004-03-20 16:46:10 +0000394 flash->read(flash, buf);
yhlu5d4383a2004-10-20 05:07:16 +0000395
olliea4302802004-12-07 03:15:51 +0000396 if (exclude_end_position - exclude_start_position > 0)
uwef6641642007-05-09 10:17:44 +0000397 memset(buf + exclude_start_position, 0,
398 exclude_end_position - exclude_start_position);
yhlu5d4383a2004-10-20 05:07:16 +0000399
ollie5672ac62004-03-17 22:22:08 +0000400 fwrite(buf, sizeof(char), size, image);
401 fclose(image);
402 printf("done\n");
403 } else {
stepan1da96c02006-11-21 23:48:51 +0000404 struct stat image_stat;
405
ollie5b621572004-03-20 16:46:10 +0000406 if ((image = fopen(filename, "r")) == NULL) {
ollie5672ac62004-03-17 22:22:08 +0000407 perror(filename);
408 exit(1);
409 }
stepan1da96c02006-11-21 23:48:51 +0000410 if (fstat(fileno(image), &image_stat) != 0) {
411 perror(filename);
412 exit(1);
413 }
uwef6641642007-05-09 10:17:44 +0000414 if (image_stat.st_size != flash->total_size * 1024) {
stepan6ef87752007-03-22 14:51:45 +0000415 fprintf(stderr, "Error: Image size doesnt match\n");
stepan1da96c02006-11-21 23:48:51 +0000416 exit(1);
417 }
418
ollie5b621572004-03-20 16:46:10 +0000419 fread(buf, sizeof(char), size, image);
ollie6a600992005-11-26 21:55:36 +0000420 show_id(buf, size);
ollie5672ac62004-03-17 22:22:08 +0000421 fclose(image);
422 }
423
ollie6a600992005-11-26 21:55:36 +0000424 /* exclude range stuff. Nice idea, but at the moment it is only
425 * supported in hardware by the pm49fl004 chips.
426 * Instead of implementing this for all chips I suggest advancing
427 * it to the rom layout feature below and drop exclude range
428 * completely once all flash chips can do rom layouts. stepan
429 */
uwef6641642007-05-09 10:17:44 +0000430
ollie6a600992005-11-26 21:55:36 +0000431 // ////////////////////////////////////////////////////////////
olliea4302802004-12-07 03:15:51 +0000432 if (exclude_end_position - exclude_start_position > 0)
uwef6641642007-05-09 10:17:44 +0000433 memcpy(buf + exclude_start_position,
stepan7cd945e2007-05-23 17:20:56 +0000434 (const char *)flash->virtual_memory + exclude_start_position,
uwef6641642007-05-09 10:17:44 +0000435 exclude_end_position - exclude_start_position);
olliea4302802004-12-07 03:15:51 +0000436
uwef6641642007-05-09 10:17:44 +0000437 exclude_start_page = exclude_start_position / flash->page_size;
438 if ((exclude_start_position % flash->page_size) != 0) {
olliea4302802004-12-07 03:15:51 +0000439 exclude_start_page++;
440 }
uwef6641642007-05-09 10:17:44 +0000441 exclude_end_page = exclude_end_position / flash->page_size;
ollie6a600992005-11-26 21:55:36 +0000442 // ////////////////////////////////////////////////////////////
yhlu5d4383a2004-10-20 05:07:16 +0000443
ollie6a600992005-11-26 21:55:36 +0000444 // This should be moved into each flash part's code to do it
445 // cleanly. This does the job.
stepan7cd945e2007-05-23 17:20:56 +0000446 handle_romentries(buf, (uint8_t *) flash->virtual_memory);
uwef6641642007-05-09 10:17:44 +0000447
ollie6a600992005-11-26 21:55:36 +0000448 // ////////////////////////////////////////////////////////////
uwef6641642007-05-09 10:17:44 +0000449
ollie6a600992005-11-26 21:55:36 +0000450 if (write_it)
stepan83eca252006-01-04 16:42:57 +0000451 ret |= flash->write(flash, buf);
ollie6a600992005-11-26 21:55:36 +0000452
ollie5672ac62004-03-17 22:22:08 +0000453 if (verify_it)
stepan83eca252006-01-04 16:42:57 +0000454 ret |= verify_flash(flash, buf);
ollie6a600992005-11-26 21:55:36 +0000455
stepan83eca252006-01-04 16:42:57 +0000456 return ret;
rminnich8d3ff912003-10-25 17:01:29 +0000457}