Author: stepan Date: 2007-04-12 01:31:45 +0200 (Thu, 12 Apr 2007) New Revision: 2603
Added: trunk/LinuxBIOSv2/util/flashrom/flashrom.c Removed: trunk/LinuxBIOSv2/util/flashrom/flash_rom.c Modified: trunk/LinuxBIOSv2/util/flashrom/Makefile Log: Rename flash_rom.c to flashrom.c. The tool is called 'flashrom' after all.
Signed-off-by: Uwe Hermann uwe@hermann-uwe.de Acked-by: Stefan Reinauer stepan@coresystems.de
Modified: trunk/LinuxBIOSv2/util/flashrom/Makefile =================================================================== --- trunk/LinuxBIOSv2/util/flashrom/Makefile 2007-04-11 18:44:42 UTC (rev 2602) +++ trunk/LinuxBIOSv2/util/flashrom/Makefile 2007-04-11 23:31:45 UTC (rev 2603) @@ -1,5 +1,5 @@ # -# Makefile for flash_rom +# Makefile for flashrom utility # # redone by Stefan Reinauer stepan@openbios.org # @@ -23,7 +23,7 @@ OBJS = chipset_enable.o board_enable.o udelay.o jedec.o sst28sf040.o \ am29f040b.o mx29f002.o sst39sf020.o m29f400bt.o w49f002u.o \ 82802ab.o msys_doc.o pm49fl004.o sst49lf040.o sst49lfxxxc.o \ - sst_fwhub.o layout.o lbtable.o flashchips.o flash_rom.o \ + sst_fwhub.o layout.o lbtable.o flashchips.o flashrom.o \ sharplhf00l04.o
all: pciutils dep $(PROGRAM)
Deleted: trunk/LinuxBIOSv2/util/flashrom/flash_rom.c =================================================================== --- trunk/LinuxBIOSv2/util/flashrom/flash_rom.c 2007-04-11 18:44:42 UTC (rev 2602) +++ trunk/LinuxBIOSv2/util/flashrom/flash_rom.c 2007-04-11 23:31:45 UTC (rev 2603) @@ -1,459 +0,0 @@ -/* - * flash_rom.c: Flash programming utility - * - * Copyright 2000 Silicon Integrated System Corporation - * Copyright 2004 Tyan Corp - * yhlu yhlu@tyan.com add exclude start and end option - * Copyright 2005-2007 coresystems GmbH - * Stefan Reinauer stepan@coresystems.de added rom layout - * support, and checking for suitable rom image, various fixes - * support for flashing the Technologic Systems 5300. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <errno.h> -#include <fcntl.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <getopt.h> -#include <pci/pci.h> - -/* for iopl */ -#if defined (__sun) && (defined(__i386) || defined(__amd64)) -#include <strings.h> -#include <sys/sysi86.h> -#include <sys/psw.h> -#include <asm/sunddi.h> -#endif - -#include "flash.h" -#include "lbtable.h" -#include "layout.h" -#include "debug.h" - -char *chip_to_probe = NULL; -struct pci_access *pacc; /* For board and chipset_enable */ -int exclude_start_page, exclude_end_page; -int force=0, verbose=0; - -int fd_mem; - -/* - * - */ -struct pci_dev * -pci_dev_find(uint16_t vendor, uint16_t device) -{ - struct pci_dev *temp; - struct pci_filter filter; - - pci_filter_init(NULL, &filter); - filter.vendor = vendor; - filter.device = device; - - for (temp = pacc->devices; temp; temp = temp->next) - if (pci_filter_match(&filter, temp)) - return temp; - - return NULL; -} - -/* - * - */ -struct pci_dev * -pci_card_find(uint16_t vendor, uint16_t device, - uint16_t card_vendor, uint16_t card_device) -{ - struct pci_dev *temp; - struct pci_filter filter; - - pci_filter_init(NULL, &filter); - filter.vendor = vendor; - filter.device = device; - - for (temp = pacc->devices; temp; temp = temp->next) - if (pci_filter_match(&filter, temp)) { - if ((card_vendor == pci_read_word(temp, 0x2C)) && - (card_device == pci_read_word(temp, 0x2E))) - return temp; - } - - return NULL; -} - -struct flashchip *probe_flash(struct flashchip *flash) -{ - volatile uint8_t *bios; - unsigned long flash_baseaddr, size; - - while (flash->name != NULL) { - if (chip_to_probe && strcmp(flash->name, chip_to_probe) != 0) { - flash++; - continue; - } - printf_debug("Probing for %s, %d KB\n", - flash->name, flash->total_size); - - size = flash->total_size * 1024; - -#ifdef TS5300 - // FIXME: Wrong place for this decision - flash_baseaddr = 0x9400000; -#else - flash_baseaddr = (0xffffffff - size + 1); -#endif - - /* If getpagesize() > size -> - * `Error MMAP /dev/mem: Invalid argument' - * This should never happen as we don't support any flash chips - * smaller than 4k or 8k yet. - */ - - if (getpagesize() > size) { - size = getpagesize(); - printf("WARNING: size: %d -> %ld (page size)\n", - flash->total_size * 1024, (unsigned long) size); - } - - bios = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED, - fd_mem, (off_t)flash_baseaddr ); - if (bios == MAP_FAILED) { - perror("Error: Can't mmap " MEM_DEV "."); - exit(1); - } - flash->virt_addr = bios; - - if (flash->probe(flash) == 1) { - printf("%s found at physical address: 0x%lx\n", - flash->name, flash_baseaddr); - return flash; - } - munmap((void *) bios, size); - - flash++; - } - return NULL; -} - -int verify_flash(struct flashchip *flash, uint8_t *buf) -{ - int idx; - int total_size = flash->total_size * 1024; - volatile uint8_t *bios = flash->virt_addr; - - printf("Verifying flash "); - - if(verbose) printf("address: 0x00000000\b\b\b\b\b\b\b\b\b\b"); - - for (idx = 0; idx < total_size; idx++) { - if (verbose && ( (idx & 0xfff) == 0xfff )) - printf("0x%08x", idx); - - if (*(bios + idx) != *(buf + idx)) { - if (verbose) { - printf("0x%08x ", idx); - } - printf("- FAILED\n"); - return 1; - } - - if (verbose && ( (idx & 0xfff) == 0xfff )) - printf("\b\b\b\b\b\b\b\b\b\b"); - } - if (verbose) - printf("\b\b\b\b\b\b\b\b\b\b "); - - printf("- VERIFIED \n"); - return 0; -} - - -void usage(const char *name) -{ - printf("usage: %s [-rwvEVfh] [-c chipname] [-s exclude_start]\n", name); - printf(" [-e exclude_end] [-m vendor:part] [-l file.layout] [-i imagename] [file]\n"); - printf(" -r | --read: read flash and save into file\n" - " -w | --write: write file into flash (default when\n" - " file is specified)\n" - " -v | --verify: verify flash against file\n" - " -E | --erase: erase flash device\n" - " -V | --verbose: more verbose output\n" - " -c | --chip <chipname>: probe only for specified flash chip\n" - " -s | --estart <addr>: exclude start position\n" - " -e | --eend <addr>: exclude end postion\n" - " -m | --mainboard vendor:part: override mainboard settings\n" - " -f | --force: force write without checking image\n" - " -l | --layout <file.layout>: read rom layout from file\n" - " -i | --image <name>: only flash image name from flash layout\n" - "\n" - " If no file is specified, then all that happens\n" - " is that flash info is dumped.\n\n"); - exit(1); -} - -int main(int argc, char *argv[]) -{ - uint8_t *buf; - unsigned long size; - FILE *image; - struct flashchip *flash; - int opt; - int option_index = 0; - int read_it = 0, - write_it = 0, - erase_it = 0, - verify_it = 0; - int ret = 0; - - static struct option long_options[]= { - { "read", 0, 0, 'r' }, - { "write", 0, 0, 'w' }, - { "erase", 0, 0, 'E' }, - { "verify", 0, 0, 'v' }, - { "chip", 1, 0, 'c' }, - { "estart", 1, 0, 's' }, - { "eend", 1, 0, 'e' }, - { "mainboard", 1, 0, 'm' }, - { "verbose", 0, 0, 'V' }, - { "force", 0, 0, 'f' }, - { "layout", 1, 0, 'l' }, - { "image", 1, 0, 'i' }, - { "help", 0, 0, 'h' }, - { 0, 0, 0, 0 } - }; - - char *filename = NULL; - - - unsigned int exclude_start_position=0, exclude_end_position=0; // [x,y) - char *tempstr=NULL, *tempstr2=NULL; - - if (argc > 1) { - /* Yes, print them. */ - int i; - printf_debug ("The arguments are:\n"); - for (i = 1; i < argc; ++i) - printf_debug ("%s\n", argv[i]); - } - - setbuf(stdout, NULL); - while ((opt = getopt_long(argc, argv, "rwvVEfc:s:e:m:l:i:h", long_options, - &option_index)) != EOF) { - switch (opt) { - case 'r': - read_it = 1; - break; - case 'w': - write_it = 1; - break; - case 'v': - verify_it = 1; - break; - case 'c': - chip_to_probe = strdup(optarg); - break; - case 'V': - verbose = 1; - break; - case 'E': - erase_it = 1; - break; - case 's': - tempstr = strdup(optarg); - sscanf(tempstr,"%x",&exclude_start_position); - break; - case 'e': - tempstr = strdup(optarg); - sscanf(tempstr,"%x",&exclude_end_position); - break; - case 'm': - tempstr = strdup(optarg); - strtok(tempstr, ":"); - tempstr2=strtok(NULL, ":"); - if (tempstr2) { - lb_vendor=tempstr; - lb_part=tempstr2; - } else { - printf("warning: ignored wrong format of" - " mainboard: %s\n", tempstr); - } - break; - case 'f': - force=1; - break; - case 'l': - tempstr=strdup(optarg); - read_romlayout(tempstr); - break; - case 'i': - tempstr=strdup(optarg); - find_romentry(tempstr); - break; - case 'h': - default: - usage(argv[0]); - break; - } - } - - if (read_it && write_it) { - printf("-r and -w are mutually exclusive\n"); - usage(argv[0]); - } - - if (optind < argc) - filename = argv[optind++]; - - /* First get full io access */ -#if defined (__sun) && (defined(__i386) || defined(__amd64)) - if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0){ -#else - if (iopl(3) != 0) { -#endif - fprintf(stderr, "ERROR: iopl failed: "%s"\n", strerror(errno)); - exit(1); - } - - /* Initialize PCI access for flash enables */ - pacc = pci_alloc(); /* Get the pci_access structure */ - /* Set all options you want -- here we stick with the defaults */ - pci_init(pacc); /* Initialize the PCI library */ - pci_scan_bus(pacc); /* We want to get the list of devices */ - - /* Open the memory device. A lot of functions need it */ - if ((fd_mem = open(MEM_DEV, O_RDWR)) < 0) { - perror("Error: Can not access memory using " MEM_DEV ". You need to be root."); - exit(1); - } - - myusec_calibrate_delay(); - - /* We look at the lbtable first to see if we need a - * mainboard specific flash enable sequence. - */ - linuxbios_init(); - - /* try to enable it. Failure IS an option, since not all motherboards - * really need this to be done, etc., etc. - */ - ret = chipset_flash_enable(); - if (ret == -2) - printf("WARNING: No chipset found. Flash detection " - "will most likely fail.\n"); - - board_flash_enable(lb_vendor, lb_part); - - - if ((flash = probe_flash(flashchips)) == NULL) { - printf("No EEPROM/flash device found.\n"); - exit(1); - } - - printf("Flash part is %s (%d KB)\n", flash->name, flash->total_size); - - if (!filename && !erase_it) { - // FIXME: Do we really want this feature implicitly? - printf("OK, only ENABLING flash write, but NOT FLASHING.\n"); - return 0; - } - - size = flash->total_size * 1024; - buf = (uint8_t *) calloc(size, sizeof(char)); - - if (erase_it) { - printf("Erasing flash chip\n"); - flash->erase(flash); - exit(0); - } else if (read_it) { - if ((image = fopen(filename, "w")) == NULL) { - perror(filename); - exit(1); - } - printf("Reading Flash..."); - if (flash->read == NULL) - memcpy(buf, (const char *) flash->virt_addr, size); - else - flash->read(flash, buf); - - if (exclude_end_position - exclude_start_position > 0) - memset(buf+exclude_start_position, 0, - exclude_end_position-exclude_start_position); - - fwrite(buf, sizeof(char), size, image); - fclose(image); - printf("done\n"); - } else { - struct stat image_stat; - - if ((image = fopen(filename, "r")) == NULL) { - perror(filename); - exit(1); - } - if (fstat(fileno(image), &image_stat) != 0) { - perror(filename); - exit(1); - } - if(image_stat.st_size!=flash->total_size*1024) { - fprintf(stderr, "Error: Image size doesnt match\n"); - exit(1); - } - - fread(buf, sizeof(char), size, image); - show_id(buf, size); - fclose(image); - } - - /* exclude range stuff. Nice idea, but at the moment it is only - * supported in hardware by the pm49fl004 chips. - * Instead of implementing this for all chips I suggest advancing - * it to the rom layout feature below and drop exclude range - * completely once all flash chips can do rom layouts. stepan - */ - - // //////////////////////////////////////////////////////////// - if (exclude_end_position - exclude_start_position > 0) - memcpy(buf+exclude_start_position, - (const char *) flash->virt_addr+exclude_start_position, - exclude_end_position-exclude_start_position); - - exclude_start_page = exclude_start_position/flash->page_size; - if ((exclude_start_position%flash->page_size) != 0) { - exclude_start_page++; - } - exclude_end_page = exclude_end_position/flash->page_size; - // //////////////////////////////////////////////////////////// - - // This should be moved into each flash part's code to do it - // cleanly. This does the job. - handle_romentries(buf, (uint8_t *)flash->virt_addr); - - // //////////////////////////////////////////////////////////// - - if (write_it) - ret |= flash->write(flash, buf); - - if (verify_it) - ret |= verify_flash(flash, buf); - - return ret; -}
Copied: trunk/LinuxBIOSv2/util/flashrom/flashrom.c (from rev 2602, trunk/LinuxBIOSv2/util/flashrom/flash_rom.c) =================================================================== --- trunk/LinuxBIOSv2/util/flashrom/flashrom.c (rev 0) +++ trunk/LinuxBIOSv2/util/flashrom/flashrom.c 2007-04-11 23:31:45 UTC (rev 2603) @@ -0,0 +1,459 @@ +/* + * flashrom.c: Flash programming utility + * + * Copyright 2000 Silicon Integrated System Corporation + * Copyright 2004 Tyan Corp + * yhlu yhlu@tyan.com add exclude start and end option + * Copyright 2005-2007 coresystems GmbH + * Stefan Reinauer stepan@coresystems.de added rom layout + * support, and checking for suitable rom image, various fixes + * support for flashing the Technologic Systems 5300. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <errno.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> +#include <pci/pci.h> + +/* for iopl */ +#if defined (__sun) && (defined(__i386) || defined(__amd64)) +#include <strings.h> +#include <sys/sysi86.h> +#include <sys/psw.h> +#include <asm/sunddi.h> +#endif + +#include "flash.h" +#include "lbtable.h" +#include "layout.h" +#include "debug.h" + +char *chip_to_probe = NULL; +struct pci_access *pacc; /* For board and chipset_enable */ +int exclude_start_page, exclude_end_page; +int force=0, verbose=0; + +int fd_mem; + +/* + * + */ +struct pci_dev * +pci_dev_find(uint16_t vendor, uint16_t device) +{ + struct pci_dev *temp; + struct pci_filter filter; + + pci_filter_init(NULL, &filter); + filter.vendor = vendor; + filter.device = device; + + for (temp = pacc->devices; temp; temp = temp->next) + if (pci_filter_match(&filter, temp)) + return temp; + + return NULL; +} + +/* + * + */ +struct pci_dev * +pci_card_find(uint16_t vendor, uint16_t device, + uint16_t card_vendor, uint16_t card_device) +{ + struct pci_dev *temp; + struct pci_filter filter; + + pci_filter_init(NULL, &filter); + filter.vendor = vendor; + filter.device = device; + + for (temp = pacc->devices; temp; temp = temp->next) + if (pci_filter_match(&filter, temp)) { + if ((card_vendor == pci_read_word(temp, 0x2C)) && + (card_device == pci_read_word(temp, 0x2E))) + return temp; + } + + return NULL; +} + +struct flashchip *probe_flash(struct flashchip *flash) +{ + volatile uint8_t *bios; + unsigned long flash_baseaddr, size; + + while (flash->name != NULL) { + if (chip_to_probe && strcmp(flash->name, chip_to_probe) != 0) { + flash++; + continue; + } + printf_debug("Probing for %s, %d KB\n", + flash->name, flash->total_size); + + size = flash->total_size * 1024; + +#ifdef TS5300 + // FIXME: Wrong place for this decision + flash_baseaddr = 0x9400000; +#else + flash_baseaddr = (0xffffffff - size + 1); +#endif + + /* If getpagesize() > size -> + * `Error MMAP /dev/mem: Invalid argument' + * This should never happen as we don't support any flash chips + * smaller than 4k or 8k yet. + */ + + if (getpagesize() > size) { + size = getpagesize(); + printf("WARNING: size: %d -> %ld (page size)\n", + flash->total_size * 1024, (unsigned long) size); + } + + bios = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED, + fd_mem, (off_t)flash_baseaddr ); + if (bios == MAP_FAILED) { + perror("Error: Can't mmap " MEM_DEV "."); + exit(1); + } + flash->virt_addr = bios; + + if (flash->probe(flash) == 1) { + printf("%s found at physical address: 0x%lx\n", + flash->name, flash_baseaddr); + return flash; + } + munmap((void *) bios, size); + + flash++; + } + return NULL; +} + +int verify_flash(struct flashchip *flash, uint8_t *buf) +{ + int idx; + int total_size = flash->total_size * 1024; + volatile uint8_t *bios = flash->virt_addr; + + printf("Verifying flash "); + + if(verbose) printf("address: 0x00000000\b\b\b\b\b\b\b\b\b\b"); + + for (idx = 0; idx < total_size; idx++) { + if (verbose && ( (idx & 0xfff) == 0xfff )) + printf("0x%08x", idx); + + if (*(bios + idx) != *(buf + idx)) { + if (verbose) { + printf("0x%08x ", idx); + } + printf("- FAILED\n"); + return 1; + } + + if (verbose && ( (idx & 0xfff) == 0xfff )) + printf("\b\b\b\b\b\b\b\b\b\b"); + } + if (verbose) + printf("\b\b\b\b\b\b\b\b\b\b "); + + printf("- VERIFIED \n"); + return 0; +} + + +void usage(const char *name) +{ + printf("usage: %s [-rwvEVfh] [-c chipname] [-s exclude_start]\n", name); + printf(" [-e exclude_end] [-m vendor:part] [-l file.layout] [-i imagename] [file]\n"); + printf(" -r | --read: read flash and save into file\n" + " -w | --write: write file into flash (default when\n" + " file is specified)\n" + " -v | --verify: verify flash against file\n" + " -E | --erase: erase flash device\n" + " -V | --verbose: more verbose output\n" + " -c | --chip <chipname>: probe only for specified flash chip\n" + " -s | --estart <addr>: exclude start position\n" + " -e | --eend <addr>: exclude end postion\n" + " -m | --mainboard vendor:part: override mainboard settings\n" + " -f | --force: force write without checking image\n" + " -l | --layout <file.layout>: read rom layout from file\n" + " -i | --image <name>: only flash image name from flash layout\n" + "\n" + " If no file is specified, then all that happens\n" + " is that flash info is dumped.\n\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + uint8_t *buf; + unsigned long size; + FILE *image; + struct flashchip *flash; + int opt; + int option_index = 0; + int read_it = 0, + write_it = 0, + erase_it = 0, + verify_it = 0; + int ret = 0; + + static struct option long_options[]= { + { "read", 0, 0, 'r' }, + { "write", 0, 0, 'w' }, + { "erase", 0, 0, 'E' }, + { "verify", 0, 0, 'v' }, + { "chip", 1, 0, 'c' }, + { "estart", 1, 0, 's' }, + { "eend", 1, 0, 'e' }, + { "mainboard", 1, 0, 'm' }, + { "verbose", 0, 0, 'V' }, + { "force", 0, 0, 'f' }, + { "layout", 1, 0, 'l' }, + { "image", 1, 0, 'i' }, + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } + }; + + char *filename = NULL; + + + unsigned int exclude_start_position=0, exclude_end_position=0; // [x,y) + char *tempstr=NULL, *tempstr2=NULL; + + if (argc > 1) { + /* Yes, print them. */ + int i; + printf_debug ("The arguments are:\n"); + for (i = 1; i < argc; ++i) + printf_debug ("%s\n", argv[i]); + } + + setbuf(stdout, NULL); + while ((opt = getopt_long(argc, argv, "rwvVEfc:s:e:m:l:i:h", long_options, + &option_index)) != EOF) { + switch (opt) { + case 'r': + read_it = 1; + break; + case 'w': + write_it = 1; + break; + case 'v': + verify_it = 1; + break; + case 'c': + chip_to_probe = strdup(optarg); + break; + case 'V': + verbose = 1; + break; + case 'E': + erase_it = 1; + break; + case 's': + tempstr = strdup(optarg); + sscanf(tempstr,"%x",&exclude_start_position); + break; + case 'e': + tempstr = strdup(optarg); + sscanf(tempstr,"%x",&exclude_end_position); + break; + case 'm': + tempstr = strdup(optarg); + strtok(tempstr, ":"); + tempstr2=strtok(NULL, ":"); + if (tempstr2) { + lb_vendor=tempstr; + lb_part=tempstr2; + } else { + printf("warning: ignored wrong format of" + " mainboard: %s\n", tempstr); + } + break; + case 'f': + force=1; + break; + case 'l': + tempstr=strdup(optarg); + read_romlayout(tempstr); + break; + case 'i': + tempstr=strdup(optarg); + find_romentry(tempstr); + break; + case 'h': + default: + usage(argv[0]); + break; + } + } + + if (read_it && write_it) { + printf("-r and -w are mutually exclusive\n"); + usage(argv[0]); + } + + if (optind < argc) + filename = argv[optind++]; + + /* First get full io access */ +#if defined (__sun) && (defined(__i386) || defined(__amd64)) + if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0){ +#else + if (iopl(3) != 0) { +#endif + fprintf(stderr, "ERROR: iopl failed: "%s"\n", strerror(errno)); + exit(1); + } + + /* Initialize PCI access for flash enables */ + pacc = pci_alloc(); /* Get the pci_access structure */ + /* Set all options you want -- here we stick with the defaults */ + pci_init(pacc); /* Initialize the PCI library */ + pci_scan_bus(pacc); /* We want to get the list of devices */ + + /* Open the memory device. A lot of functions need it */ + if ((fd_mem = open(MEM_DEV, O_RDWR)) < 0) { + perror("Error: Can not access memory using " MEM_DEV ". You need to be root."); + exit(1); + } + + myusec_calibrate_delay(); + + /* We look at the lbtable first to see if we need a + * mainboard specific flash enable sequence. + */ + linuxbios_init(); + + /* try to enable it. Failure IS an option, since not all motherboards + * really need this to be done, etc., etc. + */ + ret = chipset_flash_enable(); + if (ret == -2) + printf("WARNING: No chipset found. Flash detection " + "will most likely fail.\n"); + + board_flash_enable(lb_vendor, lb_part); + + + if ((flash = probe_flash(flashchips)) == NULL) { + printf("No EEPROM/flash device found.\n"); + exit(1); + } + + printf("Flash part is %s (%d KB)\n", flash->name, flash->total_size); + + if (!filename && !erase_it) { + // FIXME: Do we really want this feature implicitly? + printf("OK, only ENABLING flash write, but NOT FLASHING.\n"); + return 0; + } + + size = flash->total_size * 1024; + buf = (uint8_t *) calloc(size, sizeof(char)); + + if (erase_it) { + printf("Erasing flash chip\n"); + flash->erase(flash); + exit(0); + } else if (read_it) { + if ((image = fopen(filename, "w")) == NULL) { + perror(filename); + exit(1); + } + printf("Reading Flash..."); + if (flash->read == NULL) + memcpy(buf, (const char *) flash->virt_addr, size); + else + flash->read(flash, buf); + + if (exclude_end_position - exclude_start_position > 0) + memset(buf+exclude_start_position, 0, + exclude_end_position-exclude_start_position); + + fwrite(buf, sizeof(char), size, image); + fclose(image); + printf("done\n"); + } else { + struct stat image_stat; + + if ((image = fopen(filename, "r")) == NULL) { + perror(filename); + exit(1); + } + if (fstat(fileno(image), &image_stat) != 0) { + perror(filename); + exit(1); + } + if(image_stat.st_size!=flash->total_size*1024) { + fprintf(stderr, "Error: Image size doesnt match\n"); + exit(1); + } + + fread(buf, sizeof(char), size, image); + show_id(buf, size); + fclose(image); + } + + /* exclude range stuff. Nice idea, but at the moment it is only + * supported in hardware by the pm49fl004 chips. + * Instead of implementing this for all chips I suggest advancing + * it to the rom layout feature below and drop exclude range + * completely once all flash chips can do rom layouts. stepan + */ + + // //////////////////////////////////////////////////////////// + if (exclude_end_position - exclude_start_position > 0) + memcpy(buf+exclude_start_position, + (const char *) flash->virt_addr+exclude_start_position, + exclude_end_position-exclude_start_position); + + exclude_start_page = exclude_start_position/flash->page_size; + if ((exclude_start_position%flash->page_size) != 0) { + exclude_start_page++; + } + exclude_end_page = exclude_end_position/flash->page_size; + // //////////////////////////////////////////////////////////// + + // This should be moved into each flash part's code to do it + // cleanly. This does the job. + handle_romentries(buf, (uint8_t *)flash->virt_addr); + + // //////////////////////////////////////////////////////////// + + if (write_it) + ret |= flash->write(flash, buf); + + if (verify_it) + ret |= verify_flash(flash, buf); + + return ret; +}