2 * flashrom.c: Flash programming utility
4 * Copyright 2000 Silicon Integrated System Corporation
5 * Copyright 2004 Tyan Corp
6 * yhlu yhlu@tyan.com add exclude start and end option
7 * Copyright 2005-2007 coresystems GmbH
8 * 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.
12 * 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.
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.
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.
31 #include <sys/types.h>
41 #if defined (__sun) && (defined(__i386) || defined(__amd64))
43 #include <sys/sysi86.h>
45 #include <asm/sunddi.h>
53 char *chip_to_probe = NULL;
54 struct pci_access *pacc; /* For board and chipset_enable */
55 int exclude_start_page, exclude_end_page;
56 int force = 0, verbose = 0;
63 struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
66 struct pci_filter filter;
68 pci_filter_init(NULL, &filter);
69 filter.vendor = vendor;
70 filter.device = device;
72 for (temp = pacc->devices; temp; temp = temp->next)
73 if (pci_filter_match(&filter, temp))
82 struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
83 uint16_t card_vendor, uint16_t card_device)
86 struct pci_filter filter;
88 pci_filter_init(NULL, &filter);
89 filter.vendor = vendor;
90 filter.device = device;
92 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)))
102 int map_flash_registers(struct flashchip *flash)
104 volatile uint8_t *registers;
105 size_t size = flash->total_size * 1024;
107 registers = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
108 fd_mem, (off_t) (0xFFFFFFFF - 0x400000 - size + 1));
110 if (registers == MAP_FAILED) {
111 perror("Can't mmap registers using " MEM_DEV);
114 flash->virtual_registers = registers;
119 struct flashchip *probe_flash(struct flashchip *flash)
121 volatile uint8_t *bios;
122 unsigned long flash_baseaddr, size;
124 while (flash->name != NULL) {
125 if (chip_to_probe && strcmp(flash->name, chip_to_probe) != 0) {
129 printf_debug("Probing for %s, %d KB\n",
130 flash->name, flash->total_size);
132 size = flash->total_size * 1024;
135 // FIXME: Wrong place for this decision
136 // FIXME: This should be autodetected. It is trivial.
137 flash_baseaddr = 0x9400000;
139 flash_baseaddr = (0xffffffff - size + 1);
142 /* If getpagesize() > size ->
143 * "Can't mmap memory using /dev/mem: Invalid argument"
144 * This should never happen as we don't support any flash chips
145 * smaller than 4k or 8k (yet).
148 if (getpagesize() > size) {
149 size = getpagesize();
150 printf("WARNING: size: %d -> %ld (page size)\n",
151 flash->total_size * 1024, (unsigned long)size);
154 bios = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
155 fd_mem, (off_t) flash_baseaddr);
156 if (bios == MAP_FAILED) {
157 perror("Can't mmap memory using " MEM_DEV);
160 flash->virtual_memory = bios;
162 if (flash->probe(flash) == 1) {
163 printf("%s found at physical address: 0x%lx\n",
164 flash->name, flash_baseaddr);
167 munmap((void *)bios, size);
174 int verify_flash(struct flashchip *flash, uint8_t *buf)
177 int total_size = flash->total_size * 1024;
178 volatile uint8_t *bios = flash->virtual_memory;
180 printf("Verifying flash ");
183 printf("address: 0x00000000\b\b\b\b\b\b\b\b\b\b");
185 for (idx = 0; idx < total_size; idx++) {
186 if (verbose && ((idx & 0xfff) == 0xfff))
187 printf("0x%08x", idx);
189 if (*(bios + idx) != *(buf + idx)) {
191 printf("0x%08x ", idx);
193 printf("- FAILED\n");
197 if (verbose && ((idx & 0xfff) == 0xfff))
198 printf("\b\b\b\b\b\b\b\b\b\b");
201 printf("\b\b\b\b\b\b\b\b\b\b ");
203 printf("- VERIFIED \n");
207 void usage(const char *name)
209 printf("usage: %s [-rwvEVfh] [-c chipname] [-s exclude_start]\n", name);
210 printf(" [-e exclude_end] [-m vendor:part] [-l file.layout] [-i imagename] [file]\n");
212 (" -r | --read: read flash and save into file\n"
213 " -w | --write: write file into flash (default when\n"
214 " file is specified)\n"
215 " -v | --verify: verify flash against file\n"
216 " -E | --erase: erase flash device\n"
217 " -V | --verbose: more verbose output\n"
218 " -c | --chip <chipname>: probe only for specified flash chip\n"
219 " -s | --estart <addr>: exclude start position\n"
220 " -e | --eend <addr>: exclude end postion\n"
221 " -m | --mainboard <vendor:part>: override mainboard settings\n"
222 " -f | --force: force write without checking image\n"
223 " -l | --layout <file.layout>: read rom layout from file\n"
224 " -i | --image <name>: only flash image name from flash layout\n"
225 "\n" " If no file is specified, then all that happens\n"
226 " is that flash info is dumped.\n\n");
230 int main(int argc, char *argv[])
235 struct flashchip *flash;
237 int option_index = 0;
238 int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0;
241 static struct option long_options[] = {
243 {"write", 0, 0, 'w'},
244 {"erase", 0, 0, 'E'},
245 {"verify", 0, 0, 'v'},
247 {"estart", 1, 0, 's'},
249 {"mainboard", 1, 0, 'm'},
250 {"verbose", 0, 0, 'V'},
251 {"force", 0, 0, 'f'},
252 {"layout", 1, 0, 'l'},
253 {"image", 1, 0, 'i'},
258 char *filename = NULL;
260 unsigned int exclude_start_position = 0, exclude_end_position = 0; // [x,y)
261 char *tempstr = NULL, *tempstr2 = NULL;
264 /* Yes, print them. */
266 printf_debug("The arguments are:\n");
267 for (i = 1; i < argc; ++i)
268 printf_debug("%s\n", argv[i]);
271 setbuf(stdout, NULL);
272 while ((opt = getopt_long(argc, argv, "rwvVEfc:s:e:m:l:i:h",
273 long_options, &option_index)) != EOF) {
285 chip_to_probe = strdup(optarg);
294 tempstr = strdup(optarg);
295 sscanf(tempstr, "%x", &exclude_start_position);
298 tempstr = strdup(optarg);
299 sscanf(tempstr, "%x", &exclude_end_position);
302 tempstr = strdup(optarg);
303 strtok(tempstr, ":");
304 tempstr2 = strtok(NULL, ":");
309 printf("warning: ignored wrong format of"
310 " mainboard: %s\n", tempstr);
317 tempstr = strdup(optarg);
318 if (read_romlayout(tempstr))
322 tempstr = strdup(optarg);
323 find_romentry(tempstr);
332 if (read_it && write_it) {
333 printf("-r and -w are mutually exclusive\n");
338 filename = argv[optind++];
340 /* First get full io access */
341 #if defined (__sun) && (defined(__i386) || defined(__amd64))
342 if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) {
346 fprintf(stderr, "ERROR: iopl failed: \"%s\"\n",
351 /* Initialize PCI access for flash enables */
352 pacc = pci_alloc(); /* Get the pci_access structure */
353 /* Set all options you want -- here we stick with the defaults */
354 pci_init(pacc); /* Initialize the PCI library */
355 pci_scan_bus(pacc); /* We want to get the list of devices */
357 /* Open the memory device. A lot of functions need it */
358 if ((fd_mem = open(MEM_DEV, O_RDWR)) < 0) {
359 perror("Error: Can not access memory using " MEM_DEV
360 ". You need to be root.");
364 myusec_calibrate_delay();
366 /* We look at the lbtable first to see if we need a
367 * mainboard specific flash enable sequence.
371 /* try to enable it. Failure IS an option, since not all motherboards
372 * really need this to be done, etc., etc.
374 ret = chipset_flash_enable();
376 printf("WARNING: No chipset found. Flash detection "
377 "will most likely fail.\n");
380 board_flash_enable(lb_vendor, lb_part);
382 if ((flash = probe_flash(flashchips)) == NULL) {
383 printf("No EEPROM/flash device found.\n");
387 printf("Flash part is %s (%d KB)\n", flash->name, flash->total_size);
389 if (!filename && !erase_it) {
390 // FIXME: Do we really want this feature implicitly?
391 printf("OK, only ENABLING flash write, but NOT FLASHING.\n");
395 size = flash->total_size * 1024;
396 buf = (uint8_t *) calloc(size, sizeof(char));
399 printf("Erasing flash chip\n");
402 } else if (read_it) {
403 if ((image = fopen(filename, "w")) == NULL) {
407 printf("Reading Flash...");
408 if (flash->read == NULL)
409 memcpy(buf, (const char *)flash->virtual_memory, size);
411 flash->read(flash, buf);
413 if (exclude_end_position - exclude_start_position > 0)
414 memset(buf + exclude_start_position, 0,
415 exclude_end_position - exclude_start_position);
417 fwrite(buf, sizeof(char), size, image);
421 struct stat image_stat;
423 if ((image = fopen(filename, "r")) == NULL) {
427 if (fstat(fileno(image), &image_stat) != 0) {
431 if (image_stat.st_size != flash->total_size * 1024) {
432 fprintf(stderr, "Error: Image size doesnt match\n");
436 fread(buf, sizeof(char), size, image);
441 /* exclude range stuff. Nice idea, but at the moment it is only
442 * supported in hardware by the pm49fl004 chips.
443 * Instead of implementing this for all chips I suggest advancing
444 * it to the rom layout feature below and drop exclude range
445 * completely once all flash chips can do rom layouts. stepan
448 // ////////////////////////////////////////////////////////////
449 if (exclude_end_position - exclude_start_position > 0)
450 memcpy(buf + exclude_start_position,
451 (const char *)flash->virtual_memory + exclude_start_position,
452 exclude_end_position - exclude_start_position);
454 exclude_start_page = exclude_start_position / flash->page_size;
455 if ((exclude_start_position % flash->page_size) != 0) {
456 exclude_start_page++;
458 exclude_end_page = exclude_end_position / flash->page_size;
459 // ////////////////////////////////////////////////////////////
461 // This should be moved into each flash part's code to do it
462 // cleanly. This does the job.
463 handle_romentries(buf, (uint8_t *) flash->virtual_memory);
465 // ////////////////////////////////////////////////////////////
468 ret |= flash->write(flash, buf);
471 ret |= verify_flash(flash, buf);