2 * This file is part of the flashrom project.
4 * Copyright (C) 2000 Silicon Integrated System Corporation
5 * Copyright (C) 2004 Tyan Corp <yhlu@tyan.com>
6 * Copyright (C) 2005-2007 coresystems GmbH
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.
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.
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
26 #include <sys/types.h>
35 #if defined (__sun) && (defined(__i386) || defined(__amd64))
37 #include <sys/sysi86.h>
39 #include <asm/sunddi.h>
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 force = 0, verbose = 0;
49 struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
52 struct pci_filter filter;
54 pci_filter_init(NULL, &filter);
55 filter.vendor = vendor;
56 filter.device = device;
58 for (temp = pacc->devices; temp; temp = temp->next)
59 if (pci_filter_match(&filter, temp))
65 struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
66 uint16_t card_vendor, uint16_t card_device)
69 struct pci_filter filter;
71 pci_filter_init(NULL, &filter);
72 filter.vendor = vendor;
73 filter.device = device;
75 for (temp = pacc->devices; temp; temp = temp->next)
76 if (pci_filter_match(&filter, temp)) {
77 if ((card_vendor == pci_read_word(temp, 0x2C)) &&
78 (card_device == pci_read_word(temp, 0x2E)))
85 int map_flash_registers(struct flashchip *flash)
87 volatile uint8_t *registers;
88 size_t size = flash->total_size * 1024;
90 registers = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
91 fd_mem, (off_t) (0xFFFFFFFF - 0x400000 - size + 1));
93 if (registers == MAP_FAILED) {
94 perror("Can't mmap registers using " MEM_DEV);
97 flash->virtual_registers = registers;
102 struct flashchip *probe_flash(struct flashchip *flash)
104 volatile uint8_t *bios;
105 unsigned long flash_baseaddr, size;
107 while (flash->name != NULL) {
108 if (chip_to_probe && strcmp(flash->name, chip_to_probe) != 0) {
112 printf_debug("Probing for %s, %d KB\n",
113 flash->name, flash->total_size);
115 size = flash->total_size * 1024;
118 // FIXME: Wrong place for this decision
119 // FIXME: This should be autodetected. It is trivial.
120 flash_baseaddr = 0x9400000;
122 flash_baseaddr = (0xffffffff - size + 1);
125 /* If getpagesize() > size ->
126 * "Can't mmap memory using /dev/mem: Invalid argument"
127 * This should never happen as we don't support any flash chips
128 * smaller than 4k or 8k (yet).
131 if (getpagesize() > size) {
132 size = getpagesize();
133 printf("WARNING: size: %d -> %ld (page size)\n",
134 flash->total_size * 1024, (unsigned long)size);
137 bios = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
138 fd_mem, (off_t) flash_baseaddr);
139 if (bios == MAP_FAILED) {
140 perror("Can't mmap memory using " MEM_DEV);
143 flash->virtual_memory = bios;
145 if (flash->probe(flash) == 1) {
146 printf("%s found at physical address 0x%lx.\n",
147 flash->name, flash_baseaddr);
150 munmap((void *)bios, size);
158 int verify_flash(struct flashchip *flash, uint8_t *buf)
161 int total_size = flash->total_size * 1024;
162 volatile uint8_t *bios = flash->virtual_memory;
164 printf("Verifying flash... ");
167 printf("address: 0x00000000\b\b\b\b\b\b\b\b\b\b");
169 for (idx = 0; idx < total_size; idx++) {
170 if (verbose && ((idx & 0xfff) == 0xfff))
171 printf("0x%08x", idx);
173 if (*(bios + idx) != *(buf + idx)) {
175 printf("0x%08x ", idx);
181 if (verbose && ((idx & 0xfff) == 0xfff))
182 printf("\b\b\b\b\b\b\b\b\b\b");
185 printf("\b\b\b\b\b\b\b\b\b\b ");
187 printf("VERIFIED. \n");
192 void usage(const char *name)
194 printf("usage: %s [-rwvEVfhR] [-c chipname] [-s exclude_start]\n", name);
195 printf(" [-e exclude_end] [-m vendor:part] [-l file.layout] [-i imagename] [file]\n");
197 (" -r | --read: read flash and save into file\n"
198 " -w | --write: write file into flash\n"
199 " -v | --verify: verify flash against file\n"
200 " -E | --erase: erase flash device\n"
201 " -V | --verbose: more verbose output\n"
202 " -c | --chip <chipname>: probe only for specified flash chip\n"
203 " -s | --estart <addr>: exclude start position\n"
204 " -e | --eend <addr>: exclude end postion\n"
205 " -m | --mainboard <vendor:part>: override mainboard settings\n"
206 " -f | --force: force write without checking image\n"
207 " -l | --layout <file.layout>: read rom layout from file\n"
208 " -i | --image <name>: only flash image name from flash layout\n"
209 " -R | --version: print the version (release)\n"
210 "\n" " If no file is specified, then all that happens"
211 " is that flash info is dumped.\n\n");
215 void print_version(void)
217 printf("flashrom r%s\n", FLASHROM_VERSION);
220 int main(int argc, char *argv[])
225 struct flashchip *flash;
227 int option_index = 0;
228 int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0;
231 static struct option long_options[] = {
233 {"write", 0, 0, 'w'},
234 {"erase", 0, 0, 'E'},
235 {"verify", 0, 0, 'v'},
237 {"estart", 1, 0, 's'},
239 {"mainboard", 1, 0, 'm'},
240 {"verbose", 0, 0, 'V'},
241 {"force", 0, 0, 'f'},
242 {"layout", 1, 0, 'l'},
243 {"image", 1, 0, 'i'},
245 {"version", 0, 0, 'R'},
249 char *filename = NULL;
251 unsigned int exclude_start_position = 0, exclude_end_position = 0; // [x,y)
252 char *tempstr = NULL, *tempstr2 = NULL;
255 /* Yes, print them. */
257 printf_debug("The arguments are:\n");
258 for (i = 1; i < argc; ++i)
259 printf_debug("%s\n", argv[i]);
262 setbuf(stdout, NULL);
263 while ((opt = getopt_long(argc, argv, "rRwvVEfc:s:e:m:l:i:h",
264 long_options, &option_index)) != EOF) {
276 chip_to_probe = strdup(optarg);
285 tempstr = strdup(optarg);
286 sscanf(tempstr, "%x", &exclude_start_position);
289 tempstr = strdup(optarg);
290 sscanf(tempstr, "%x", &exclude_end_position);
293 tempstr = strdup(optarg);
294 strtok(tempstr, ":");
295 tempstr2 = strtok(NULL, ":");
300 printf("warning: ignored wrong format of"
301 " mainboard: %s\n", tempstr);
308 tempstr = strdup(optarg);
309 if (read_romlayout(tempstr))
313 tempstr = strdup(optarg);
314 find_romentry(tempstr);
327 if (read_it && write_it) {
328 printf("-r and -w are mutually exclusive\n");
333 filename = argv[optind++];
335 /* First get full io access */
336 #if defined (__sun) && (defined(__i386) || defined(__amd64))
337 if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) {
341 fprintf(stderr, "ERROR: iopl failed: \"%s\"\n",
346 /* Initialize PCI access for flash enables */
347 pacc = pci_alloc(); /* Get the pci_access structure */
348 /* Set all options you want -- here we stick with the defaults */
349 pci_init(pacc); /* Initialize the PCI library */
350 pci_scan_bus(pacc); /* We want to get the list of devices */
352 /* Open the memory device. A lot of functions need it */
353 if ((fd_mem = open(MEM_DEV, O_RDWR)) < 0) {
354 perror("Error: Can not access memory using " MEM_DEV
355 ". You need to be root.");
359 myusec_calibrate_delay();
361 /* We look at the lbtable first to see if we need a
362 * mainboard specific flash enable sequence.
366 /* try to enable it. Failure IS an option, since not all motherboards
367 * really need this to be done, etc., etc.
369 ret = chipset_flash_enable();
371 printf("WARNING: No chipset found. Flash detection "
372 "will most likely fail.\n");
375 board_flash_enable(lb_vendor, lb_part);
377 if ((flash = probe_flash(flashchips)) == NULL) {
378 printf("No EEPROM/flash device found.\n");
379 // FIXME: flash writes stay enabled!
383 printf("Flash part is %s (%d KB).\n", flash->name, flash->total_size);
385 if (!(read_it | write_it | verify_it | erase_it)) {
386 printf("No operations were specified.\n");
387 // FIXME: flash writes stay enabled!
391 if (!filename && !erase_it) {
392 printf("Error: No filename specified.\n");
393 // FIXME: flash writes stay enabled!
397 size = flash->total_size * 1024;
398 buf = (uint8_t *) calloc(size, sizeof(char));
401 printf("Erasing flash chip\n");
404 } else if (read_it) {
405 if ((image = fopen(filename, "w")) == NULL) {
409 printf("Reading Flash...");
410 if (flash->read == NULL)
411 memcpy(buf, (const char *)flash->virtual_memory, size);
413 flash->read(flash, buf);
415 if (exclude_end_position - exclude_start_position > 0)
416 memset(buf + exclude_start_position, 0,
417 exclude_end_position - exclude_start_position);
419 fwrite(buf, sizeof(char), size, image);
423 struct stat image_stat;
425 if ((image = fopen(filename, "r")) == NULL) {
429 if (fstat(fileno(image), &image_stat) != 0) {
433 if (image_stat.st_size != flash->total_size * 1024) {
434 fprintf(stderr, "Error: Image size doesnt match\n");
438 fread(buf, sizeof(char), size, image);
443 /* exclude range stuff. Nice idea, but at the moment it is only
444 * supported in hardware by the pm49fl004 chips.
445 * Instead of implementing this for all chips I suggest advancing
446 * it to the rom layout feature below and drop exclude range
447 * completely once all flash chips can do rom layouts. stepan
450 // ////////////////////////////////////////////////////////////
451 if (exclude_end_position - exclude_start_position > 0)
452 memcpy(buf + exclude_start_position,
453 (const char *)flash->virtual_memory +
454 exclude_start_position,
455 exclude_end_position - exclude_start_position);
457 exclude_start_page = exclude_start_position / flash->page_size;
458 if ((exclude_start_position % flash->page_size) != 0) {
459 exclude_start_page++;
461 exclude_end_page = exclude_end_position / flash->page_size;
462 // ////////////////////////////////////////////////////////////
464 // This should be moved into each flash part's code to do it
465 // cleanly. This does the job.
466 handle_romentries(buf, (uint8_t *) flash->virtual_memory);
468 // ////////////////////////////////////////////////////////////
471 ret |= flash->write(flash, buf);
474 ret |= verify_flash(flash, buf);