From 702218d030d14ddb5029ac816f45ca2b51ebdd12 Mon Sep 17 00:00:00 2001 From: Carl-Daniel Hailfinger Date: Fri, 8 May 2009 17:43:22 +0000 Subject: Add external flasher support - Read/write accesses through function pointers - Command line parameter for internal/external flasher - Board and chipset setup moved to internal init function - Shutdown stuff moved to internal shutdown function As a side benefit, this will allow us to undo chipset write enable during shutdown. Tested by Uwe on real hardware. Corresponding to flashrom svn r476. Signed-off-by: Carl-Daniel Hailfinger Acked-by: Uwe Hermann --- Makefile | 2 +- flash.h | 58 +++++++++++++++++++---- flashrom.c | 110 ++++++++++++------------------------------- internal.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 233 insertions(+), 91 deletions(-) create mode 100644 internal.c diff --git a/Makefile b/Makefile index 8c42343..ecaef6c 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ OBJS = chipset_enable.o board_enable.o udelay.o jedec.o stm50flw0x0x.o \ w49f002u.o 82802ab.o pm49fl00x.o sst49lf040.o en29f002a.o \ sst49lfxxxc.o sst_fwhub.o layout.o cbtable.o flashchips.o physmap.o \ flashrom.o w39v080fa.o sharplhf00l04.o w29ee011.o spi.o it87spi.o \ - ichspi.o w39v040c.o sb600spi.o wbsio_spi.o m29f002.o + ichspi.o w39v040c.o sb600spi.o wbsio_spi.o m29f002.o internal.o all: pciutils dep $(PROGRAM) diff --git a/flash.h b/flash.h index f5dea55..ef9ae6e 100644 --- a/flash.h +++ b/flash.h @@ -76,34 +76,64 @@ #endif #endif -static inline void chip_writeb(uint8_t b, volatile void *addr) +extern int programmer; +#define PROGRAMMER_INTERNAL 0x00 + +struct programmer_entry { + const char *vendor; + const char *name; + + int (*init) (void); + int (*shutdown) (void); + + void (*chip_writeb) (uint8_t val, volatile void *addr); + void (*chip_writew) (uint16_t val, volatile void *addr); + void (*chip_writel) (uint32_t val, volatile void *addr); + uint8_t (*chip_readb) (const volatile void *addr); + uint16_t (*chip_readw) (const volatile void *addr); + uint32_t (*chip_readl) (const volatile void *addr); +}; + +extern const struct programmer_entry programmer_table[]; + +static inline int programmer_init(void) { - *(volatile uint8_t *) addr = b; + return programmer_table[programmer].init(); } -static inline void chip_writew(uint16_t b, volatile void *addr) +static inline int programmer_shutdown(void) { - *(volatile uint16_t *) addr = b; + return programmer_table[programmer].shutdown(); } -static inline void chip_writel(uint32_t b, volatile void *addr) +static inline void chip_writeb(uint8_t val, volatile void *addr) { - *(volatile uint32_t *) addr = b; + programmer_table[programmer].chip_writeb(val, addr); +} + +static inline void chip_writew(uint16_t val, volatile void *addr) +{ + programmer_table[programmer].chip_writew(val, addr); +} + +static inline void chip_writel(uint32_t val, volatile void *addr) +{ + programmer_table[programmer].chip_writel(val, addr); } static inline uint8_t chip_readb(const volatile void *addr) { - return *(volatile uint8_t *) addr; + return programmer_table[programmer].chip_readb(addr); } static inline uint16_t chip_readw(const volatile void *addr) { - return *(volatile uint16_t *) addr; + return programmer_table[programmer].chip_readw(addr); } static inline uint32_t chip_readl(const volatile void *addr) { - return *(volatile uint32_t *) addr; + return programmer_table[programmer].chip_readl(addr); } #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) @@ -535,6 +565,16 @@ extern void *spibar; void *physmap(const char *descr, unsigned long phys_addr, size_t len); void physunmap(void *virt_addr, size_t len); +/* internal.c */ +int internal_init(void); +int internal_shutdown(void); +void internal_chip_writeb(uint8_t val, volatile void *addr); +void internal_chip_writew(uint16_t val, volatile void *addr); +void internal_chip_writel(uint32_t val, volatile void *addr); +uint8_t internal_chip_readb(const volatile void *addr); +uint16_t internal_chip_readw(const volatile void *addr); +uint32_t internal_chip_readl(const volatile void *addr); + /* flashrom.c */ extern int verbose; #define printf_debug(x...) { if (verbose) printf(x); } diff --git a/flashrom.c b/flashrom.c index d60ffe5..7222d7f 100644 --- a/flashrom.c +++ b/flashrom.c @@ -21,7 +21,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include #include #include @@ -30,51 +29,27 @@ #include #include #include -#include #include "flash.h" char *chip_to_probe = NULL; -struct pci_access *pacc; /* For board and chipset_enable */ int exclude_start_page, exclude_end_page; int verbose = 0; - -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, PCI_SUBSYSTEM_VENDOR_ID)) - && (card_device == - pci_read_word(temp, PCI_SUBSYSTEM_ID))) - return temp; - } - - return NULL; -} +int programmer = PROGRAMMER_INTERNAL; + +const struct programmer_entry programmer_table[] = { + { + .init = internal_init, + .shutdown = internal_shutdown, + .chip_readb = internal_chip_readb, + .chip_readw = internal_chip_readw, + .chip_readl = internal_chip_readl, + .chip_writeb = internal_chip_writeb, + .chip_writew = internal_chip_writew, + .chip_writel = internal_chip_writel, + }, + + {}, +}; void map_flash_registers(struct flashchip *flash) { @@ -362,9 +337,6 @@ int main(int argc, char *argv[]) int force = 0; int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0; int ret = 0, i; -#if defined(__FreeBSD__) || defined(__DragonFly__) - int io_fd; -#endif static struct option long_options[] = { {"read", 0, 0, 'r'}, @@ -380,6 +352,7 @@ int main(int argc, char *argv[]) {"layout", 1, 0, 'l'}, {"image", 1, 0, 'i'}, {"list-supported", 0, 0, 'L'}, + {"programmer", 1, 0, 'p'}, {"help", 0, 0, 'h'}, {"version", 0, 0, 'R'}, {0, 0, 0, 0} @@ -401,7 +374,7 @@ int main(int argc, char *argv[]) } setbuf(stdout, NULL); - while ((opt = getopt_long(argc, argv, "rRwvVEfc:s:e:m:l:i:Lh", + while ((opt = getopt_long(argc, argv, "rRwvVEfc:s:e:m:l:i:p:Lh", long_options, &option_index)) != EOF) { switch (opt) { case 'r': @@ -460,6 +433,14 @@ int main(int argc, char *argv[]) print_supported_boards(); exit(0); break; + case 'p': + if (strncmp(optarg, "internal", 8) == 0) { + programmer = PROGRAMMER_INTERNAL; + } else { + printf("Error: Unknown programmer.\n"); + exit(1); + } + break; case 'R': /* print_version() is always called during startup. */ exit(0); @@ -479,42 +460,10 @@ int main(int argc, char *argv[]) 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) { -#elif defined(__FreeBSD__) || defined (__DragonFly__) - if ((io_fd = open("/dev/io", O_RDWR)) < 0) { -#else - if (iopl(3) != 0) { -#endif - fprintf(stderr, "ERROR: Could not get IO privileges (%s).\nYou need to be root.\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 */ + ret = programmer_init(); myusec_calibrate_delay(); - /* We look at the lbtable first to see if we need a - * mainboard specific flash enable sequence. - */ - coreboot_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); - for (i = 0; i < ARRAY_SIZE(flashes); i++) { flashes[i] = probe_flash(i ? flashes[i - 1] + 1 : flashchips, 0); @@ -704,8 +653,7 @@ int main(int argc, char *argv[]) if (verify_it) ret |= verify_flash(flash, buf); -#ifdef __FreeBSD__ - close(io_fd); -#endif + programmer_shutdown(); + return ret; } diff --git a/internal.c b/internal.c new file mode 100644 index 0000000..aa1fd9c --- /dev/null +++ b/internal.c @@ -0,0 +1,154 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2009 Carl-Daniel Hailfinger + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "flash.h" + +#if defined(__FreeBSD__) || defined(__DragonFly__) +int io_fd; +#endif + +struct pci_access *pacc; /* For board and chipset_enable */ + +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, PCI_SUBSYSTEM_VENDOR_ID)) + && (card_device == + pci_read_word(temp, PCI_SUBSYSTEM_ID))) + return temp; + } + + return NULL; +} + +int internal_init(void) +{ + int ret = 0; + + /* First get full io access */ +#if defined (__sun) && (defined(__i386) || defined(__amd64)) + if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) { +#elif defined(__FreeBSD__) || defined (__DragonFly__) + if ((io_fd = open("/dev/io", O_RDWR)) < 0) { +#else + if (iopl(3) != 0) { +#endif + fprintf(stderr, "ERROR: Could not get IO privileges (%s).\nYou need to be root.\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 */ + + /* We look at the lbtable first to see if we need a + * mainboard specific flash enable sequence. + */ + coreboot_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); + + return ret; +} + +int internal_shutdown(void) +{ +#if defined(__FreeBSD__) || defined(__DragonFly__) + close(io_fd); +#endif + + return 0; +} + +void internal_chip_writeb(uint8_t val, volatile void *addr) +{ + *(volatile uint8_t *) addr = val; +} + +void internal_chip_writew(uint16_t val, volatile void *addr) +{ + *(volatile uint16_t *) addr = val; +} + +void internal_chip_writel(uint32_t val, volatile void *addr) +{ + *(volatile uint32_t *) addr = val; +} + +uint8_t internal_chip_readb(const volatile void *addr) +{ + return *(volatile uint8_t *) addr; +} + +uint16_t internal_chip_readw(const volatile void *addr) +{ + return *(volatile uint16_t *) addr; +} + +uint32_t internal_chip_readl(const volatile void *addr) +{ + return *(volatile uint32_t *) addr; +} + -- cgit v1.1