From b8c64378112fd61a698d545562dfbafaa353243d Mon Sep 17 00:00:00 2001 From: Luc Verhaegen Date: Wed, 4 Apr 2007 22:45:58 +0000 Subject: [PATCH] flashrom: split flash_enable.c into chipset_enable.c and board_enable.c This splits up the ROM Write enable code into chipset specific and board specific parts. This of course means that a lot of code is plainly moved about. * Allows for linuxbios name matching and pci-subsystem id matching. The latter uses a double set to properly distuinguish boards despite of some known vendors being lax about it. * Fixes GPIO15 being raised on every VT8235 southbridge, regardless of what that line actually controls; rom on EPIA-M, backlight on mitac 8999 laptop. * Adds flashrom support for Asus A7V400-MX (KM400 + VT8235) * Island aruma was renamed agami aruma, the board specific code now got adjusted. A set of pci-ids was retrieved from source code. Signed-off-by: Luc Verhaegen Acked-by: Stefan Reinauer git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2581 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- util/flashrom/Makefile | 9 +- util/flashrom/board_enable.c | 299 ++++++++++++++++++ .../{flash_enable.c => chipset_enable.c} | 272 +++++----------- util/flashrom/flash.h | 12 +- util/flashrom/flash_rom.c | 84 ++++- 5 files changed, 466 insertions(+), 210 deletions(-) create mode 100644 util/flashrom/board_enable.c rename util/flashrom/{flash_enable.c => chipset_enable.c} (63%) diff --git a/util/flashrom/Makefile b/util/flashrom/Makefile index a6b389f27d..bb460c5962 100644 --- a/util/flashrom/Makefile +++ b/util/flashrom/Makefile @@ -20,10 +20,11 @@ LDFLAGS = -lpci -lz -static STRIP_ARGS = -s endif -OBJS = flash_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 sharplhf00l04.o +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 \ + sharplhf00l04.o all: pciutils dep $(PROGRAM) diff --git a/util/flashrom/board_enable.c b/util/flashrom/board_enable.c new file mode 100644 index 0000000000..ac8de9f40e --- /dev/null +++ b/util/flashrom/board_enable.c @@ -0,0 +1,299 @@ +/* + * flash rom utility: enable flash writes (board specific) + * + * Copyright (C) 2005-2007 coresystems GmbH + * Copyright (C) 2006 Uwe Hermann + * Copyright (C) 2007 Luc Verhaegen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +/* + * Contains the board specific flash enables. + */ + +#include +#include +#include +#include + +#include "flash.h" +#include "debug.h" + +/* + * Match on pci-ids, no report received, just data from the mainboard + * specific code: + * main: 0x1022:0x746B, which is the SMBUS controller. + * card: 0x1022:0x36C0... + */ + +static int board_agami_aruma(char *name) +{ + /* Extended function index register, either 0x2e or 0x4e */ +#define EFIR 0x2e + /* Extended function data register, one plus the index reg. */ +#define EFDR EFIR + 1 + char b; + + /* Disable the flash write protect. The flash write protect is + * connected to the WinBond w83627hf GPIO 24. + */ + outb(0x87, EFIR); /* sequence to unlock extended functions */ + outb(0x87, EFIR); + + outb(0x20, EFIR); /* SIO device ID register */ + b = inb(EFDR); + printf_debug("\nW83627HF device ID = 0x%x\n",b); + + if (b != 0x52) { + fprintf(stderr, "\nIncorrect device ID, aborting write protect disable\n"); + return -1; + } + + outb(0x2b, EFIR); /* GPIO multiplexed pin reg. */ + b = inb(EFDR) | 0x10; + outb(0x2b, EFIR); + outb(b, EFDR); /* select GPIO 24 instead of WDTO */ + + outb(0x7, EFIR); /* logical device select */ + outb(0x8, EFDR); /* point to device 8, GPIO port 2 */ + + outb(0x30, EFIR); /* logic device activation control */ + outb(0x1, EFDR); /* activate */ + + outb(0xf0, EFIR); /* GPIO 20-27 I/O selection register */ + b = inb(EFDR) & ~0x10; + outb(0xf0, EFIR); + outb(b, EFDR); /* set GPIO 24 as an output */ + + outb(0xf1, EFIR); /* GPIO 20-27 data register */ + b = inb(EFDR) | 0x10; + outb(0xf1, EFIR); + outb(b, EFDR); /* set GPIO 24 */ + + outb(0xaa, EFIR); /* command to exit extended functions */ + + return 0; +} + +/* + * Suited for VIAs EPIA M and MII, and maybe other CLE266 based EPIAs. + * + * We don't need to do this when using linuxbios, GPIO15 is never lowered there. + */ + +static int board_via_epia_m(char *name) +{ + struct pci_dev *dev; + unsigned int base; + uint8_t val; + + dev = pci_dev_find(0x1106, 0x3177); /* VT8235 ISA bridge */ + if (!dev) { + fprintf(stderr, "\nERROR: VT8235 ISA Bridge not found.\n"); + return -1; + } + + /* GPIO12-15 -> output */ + val = pci_read_byte(dev, 0xE4); + val |= 0x10; + pci_write_byte(dev, 0xE4, val); + + /* Get Power Management IO address. */ + base = pci_read_word(dev, 0x88) & 0xFF80; + + /* enable GPIO15 which is connected to write protect. */ + val = inb(base + 0x4D); + val |= 0x80; + outb(val, base + 0x4D); + + return 0; +} + +/* + * Winbond LPC super IO. + * + * Raises the ROM MEMW# line. + */ + +static void w83697_rom_memw_enable(void) +{ + uint8_t val; + + outb(0x87, 0x2E); /* enable extended functions */ + outb(0x87, 0x2E); + + outb(0x24, 0x2E); /* rom bits live here */ + + val = inb(0x2F); + if (!(val & 0x02)) /* flash rom enabled? */ + outb(val | 0x08, 0x2F); /* enable MEMW# */ + + outb(0xAA, 0x2E); /* disable extended functions */ +} + +/* + * Suited for Asus A7V8X-MX SE and A7V400-MX. + * + */ + +static int board_asus_a7v8x_mx(char *name) +{ + struct pci_dev *dev; + uint8_t val; + + dev = pci_dev_find(0x1106, 0x3177); /* VT8235 ISA bridge */ + if (!dev) { + fprintf(stderr, "\nERROR: VT8235 ISA Bridge not found.\n"); + return -1; + } + + /* This bit is marked reserved actually */ + val = pci_read_byte(dev, 0x59); + val &= 0x7F; + pci_write_byte(dev, 0x59, val); + + w83697_rom_memw_enable(); + + return 0; +} + +/* + * We use 2 sets of ids here, you're free to choose which is which. This + * to provide a very high degree of certainty when matching a board on + * the basis of Subsystem/card ids. As not every vendor handles + * subsystem/card ids in a sane manner. + * + * Keep the second set nulled if it should be ignored. + * + */ + +struct board_pciid_enable { + /* Any device, but make it sensible, like the isa bridge. */ + uint16_t first_vendor; + uint16_t first_device; + uint16_t first_card_vendor; + uint16_t first_card_device; + + /* Any device, but make it sensible, like + * the host bridge. May be NULL + */ + uint16_t second_vendor; + uint16_t second_device; + uint16_t second_card_vendor; + uint16_t second_card_device; + + /* From linuxbios table */ + char *lb_vendor; + char *lb_part; + + char *name; + int (*enable)(char *name); +}; + +struct board_pciid_enable board_pciid_enables[] = { + { 0x1022, 0x746B, 0x1022, 0x36C0, 0x0000, 0x0000, 0x0000, 0x0000, + "AGAMI", "ARUMA", "Agami Aruma", board_agami_aruma }, + { 0x1106, 0x3177, 0x1106, 0xAA01, 0x1106, 0x3123, 0x1106, 0xAA01, + NULL, NULL, "VIA EPIA M/MII/...", board_via_epia_m }, + { 0x1106, 0x3177, 0x1043, 0x80A1, 0x1106, 0x3205, 0x1043, 0x8118, + NULL, NULL, "Asus A7V8-MX SE", board_asus_a7v8x_mx }, + { 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL } /* Keep this */ + +}; + +/* + * Match boards on linuxbios table gathered vendor and part name. + * Require main pci-ids to match too as extra safety. + * + */ +static struct board_pciid_enable * +board_match_linuxbios_name(char *vendor, char *part) +{ + struct board_pciid_enable *board = board_pciid_enables; + + for (; board->name; board++) { + if (!board->lb_vendor || strcmp(board->lb_vendor, vendor)) + continue; + + if (!board->lb_part || strcmp(board->lb_part, part)) + continue; + + if (!pci_dev_find(board->first_vendor, board->first_device)) + continue; + + if (board->second_vendor && + !pci_dev_find(board->second_vendor, board->second_device)) + continue; + return board; + } + return NULL; +} + +/* + * Match boards on pci ids and subsystem ids. + * Second set of ids can be main only or missing completely. + */ +static struct board_pciid_enable *board_match_pci_card_ids(void) +{ + struct board_pciid_enable *board = board_pciid_enables; + + for (; board->name; board++) { + if (!board->first_card_vendor || !board->first_card_device) + continue; + + if (!pci_card_find(board->first_vendor, board->first_device, + board->first_card_vendor, + board->first_card_device)) + continue; + + if (board->second_vendor) { + if (board->second_card_vendor) { + if (!pci_card_find(board->second_vendor, + board->second_device, + board->second_card_vendor, + board->second_card_device)) + continue; + } else { + if (!pci_dev_find(board->second_vendor, + board->second_device)) + continue; + } + } + + return board; + } + + return NULL; +} + +/* + * + */ +int board_flash_enable(char *vendor, char *part) +{ + struct board_pciid_enable *board = NULL; + int ret = 0; + + if (vendor && part) + board = board_match_linuxbios_name(vendor, part); + + if (!board) + board = board_match_pci_card_ids(); + + if (board) { + printf("Found board \"%s\": Enabling flash write... ", + board->name); + + ret = board->enable(board->name); + if (ret) + printf("Failed!\n"); + else + printf("OK.\n"); + } + + return ret; +} diff --git a/util/flashrom/flash_enable.c b/util/flashrom/chipset_enable.c similarity index 63% rename from util/flashrom/flash_enable.c rename to util/flashrom/chipset_enable.c index 9dd066489c..8add4d9de0 100644 --- a/util/flashrom/flash_enable.c +++ b/util/flashrom/chipset_enable.c @@ -1,8 +1,8 @@ /* * flash rom utility: enable flash writes * - * Copyright (C) 2000-2004 ??? - * Copyright (C) 2005 coresystems GmbH + * Copyright (C) 2000 Silicon Integrated System Corporation + * Copyright (C) 2005-2007 coresystems GmbH * Copyright (C) 2006 Uwe Hermann * * This program is free software; you can redistribute it and/or @@ -14,20 +14,9 @@ #include #include #include -#include -#include -#if defined (__sun) && (defined(__i386) || defined(__amd64)) -#include -#include -#include -#include -#endif -#include "flash.h" -#include "lbtable.h" -#include "debug.h" -// We keep this for the others. -static struct pci_access *pacc; +#include "flash.h" +#include "debug.h" static int enable_flash_sis630(struct pci_dev *dev, char *name) { @@ -120,15 +109,15 @@ static int enable_flash_ich(struct pci_dev *dev, char *name, int bios_cntl) uint8_t old, new; /* if it fails, it fails. There are so many variations of broken mobos - * that it is hard to argue that we should quit at this point. + * that it is hard to argue that we should quit at this point. */ /* Note: the ICH0-ICH5 BIOS_CNTL register is actually 16 bit wide, but - * just treating it as 8 bit wide seems to work fine in practice. + * just treating it as 8 bit wide seems to work fine in practice. */ /* see ie. page 375 of "Intel ICH7 External Design Specification" - * http://download.intel.com/design/chipsets/datashts/30701302.pdf + * http://download.intel.com/design/chipsets/datashts/30701302.pdf */ old = pci_read_byte(dev, bios_cntl); @@ -158,10 +147,13 @@ static int enable_flash_ich_dc(struct pci_dev *dev, char *name) return enable_flash_ich(dev, name, 0xdc); } -static int enable_flash_vt823x(struct pci_dev *dev, char *name) +/* + * + */ +static int +enable_flash_vt823x(struct pci_dev *dev, char *name) { uint8_t val; - int ret = 0; /* ROM Write enable */ val = pci_read_byte(dev, 0x40); @@ -169,38 +161,12 @@ static int enable_flash_vt823x(struct pci_dev *dev, char *name) pci_write_byte(dev, 0x40, val); if (pci_read_byte(dev, 0x40) != val) { - printf("Warning: Failed to enable ROM Write on %s\n", name); - ret = -1; + printf("\nWARNING: Failed to enable ROM Write on \"%s\"\n", + name); + return -1; } - if (dev->device_id == 0x3177) { /* VT8235 */ - if (!iopl(3)) { /* enable full IO access */ - unsigned int base; - - /* GPIO12-15 -> output */ - val = pci_read_byte(dev, 0xE4); - val |= 0x38; - pci_write_byte(dev, 0xE4, val); - - /* Get Power Management IO address. */ - base = pci_read_word(dev, 0x88) & 0xFF80; - - /* enable GPIO15 which is connected to write protect. */ - val = inb(base + 0x4d); - val |= 0xFF; - outb(val, base + 0x4d); - - val = inb(base + 0x4E); - val |= 0x0F; - outb(val, base + 0x4E); - } else { - printf("Warning; Failed to disable Write Protect" - " on %s (iopl failed)\n", name); - return -1; - } - } - - return ret; + return 0; } static int enable_flash_cs5530(struct pci_dev *dev, char *name) @@ -216,10 +182,10 @@ static int enable_flash_cs5530(struct pci_dev *dev, char *name) 0x52, new, name); return -1; } - + new = pci_read_byte(dev, 0x5b) | 0x20; pci_write_byte(dev, 0x5b, new); - + return 0; } @@ -268,7 +234,7 @@ static int enable_flash_amd8111(struct pci_dev *dev, char *name) /* register 4e.b gets or'ed with one */ uint8_t old, new; /* if it fails, it fails. There are so many variations of broken mobos - * that it is hard to argue that we should quit at this point. + * that it is hard to argue that we should quit at this point. */ /* enable decoding at 0xffb00000 to 0xffffffff */ @@ -296,17 +262,16 @@ static int enable_flash_amd8111(struct pci_dev *dev, char *name) return 0; } -//By yhlu static int enable_flash_ck804(struct pci_dev *dev, char *name) { /* register 4e.b gets or'ed with one */ uint8_t old, new; /* if it fails, it fails. There are so many variations of broken mobos - * that it is hard to argue that we should quit at this point. + * that it is hard to argue that we should quit at this point. */ - //dump_pci_device(dev); - + /* dump_pci_device(dev); */ + old = pci_read_byte(dev, 0x88); new = old | 0xc0; if (new != old) { @@ -342,29 +307,29 @@ static int enable_flash_sb400(struct pci_dev *dev, char *name) pci_filter_init((struct pci_access *) 0, &f); f.vendor = 0x1002; f.device = 0x4372; - + for (smbusdev = pacc->devices; smbusdev; smbusdev = smbusdev->next) { if (pci_filter_match(&f, smbusdev)) { break; } } - + if(!smbusdev) { - perror("smbus device not found. aborting\n"); + fprintf(stderr, "ERROR: SMBus device not found. aborting\n"); exit(1); } - - // enable some smbus stuff + + /* enable some smbus stuff */ tmp=pci_read_byte(smbusdev, 0x79); tmp|=0x01; pci_write_byte(smbusdev, 0x79, tmp); - // change southbridge + /* change southbridge */ tmp=pci_read_byte(dev, 0x48); tmp|=0x21; pci_write_byte(dev, 0x48, tmp); - // now become a bit silly. + /* now become a bit silly. */ tmp=inb(0xc6f); outb(tmp,0xeb); outb(tmp, 0xeb); @@ -376,30 +341,29 @@ static int enable_flash_sb400(struct pci_dev *dev, char *name) return 0; } -//By yhlu static int enable_flash_mcp55(struct pci_dev *dev, char *name) { /* register 4e.b gets or'ed with one */ unsigned char old, new, byte; unsigned short word; - + /* if it fails, it fails. There are so many variations of broken mobos - * that it is hard to argue that we should quit at this point. + * that it is hard to argue that we should quit at this point. */ - //dump_pci_device(dev); + /* dump_pci_device(dev); */ /* Set the 4MB enable bit bit */ byte = pci_read_byte(dev, 0x88); - byte |= 0xff; //256K + byte |= 0xff; /* 256K */ pci_write_byte(dev, 0x88, byte); byte = pci_read_byte(dev, 0x8c); - byte |= 0xff; //1M + byte |= 0xff; /* 1M */ pci_write_byte(dev, 0x8c, byte); word = pci_read_word(dev, 0x90); - word |= 0x7fff; //15M + word |= 0x7fff; /* 15M */ pci_write_word(dev, 0x90, word); - + old = pci_read_byte(dev, 0x6d); new = old | 0x01; if (new == old) @@ -451,147 +415,55 @@ static FLASH_ENABLE enables[] = { {0x100b, 0x0510, "SC1100", enable_flash_sc1100}, {0x1039, 0x0008, "SIS5595", enable_flash_sis5595}, {0x1022, 0x7468, "AMD8111", enable_flash_amd8111}, - // this fallthrough looks broken. - {0x10de, 0x0050, "NVIDIA CK804", enable_flash_ck804}, // LPC - {0x10de, 0x0051, "NVIDIA CK804", enable_flash_ck804}, // Pro - {0x10de, 0x00d3, "NVIDIA CK804", enable_flash_ck804}, // Slave, should not be here, to fix known bug for A01. + /* this fallthrough looks broken. */ + {0x10de, 0x0050, "NVIDIA CK804", enable_flash_ck804}, /* LPC */ + {0x10de, 0x0051, "NVIDIA CK804", enable_flash_ck804}, /* Pro */ + {0x10de, 0x00d3, "NVIDIA CK804", enable_flash_ck804}, /* Slave, should not be here, to fix known bug for A01. */ {0x10de, 0x0260, "NVidia MCP51", enable_flash_ck804}, {0x10de, 0x0261, "NVidia MCP51", enable_flash_ck804}, {0x10de, 0x0262, "NVidia MCP51", enable_flash_ck804}, {0x10de, 0x0263, "NVidia MCP51", enable_flash_ck804}, - {0x10de, 0x0360, "NVIDIA MCP55", enable_flash_mcp55}, // Gigabyte m57sli-s4 - {0x10de, 0x0361, "NVIDIA MCP55", enable_flash_mcp55}, // LPC - {0x10de, 0x0362, "NVIDIA MCP55", enable_flash_mcp55}, // LPC - {0x10de, 0x0363, "NVIDIA MCP55", enable_flash_mcp55}, // LPC - {0x10de, 0x0364, "NVIDIA MCP55", enable_flash_mcp55}, // LPC - {0x10de, 0x0365, "NVIDIA MCP55", enable_flash_mcp55}, // LPC - {0x10de, 0x0366, "NVIDIA MCP55", enable_flash_mcp55}, // LPC - {0x10de, 0x0367, "NVIDIA MCP55", enable_flash_mcp55}, // Pro + {0x10de, 0x0360, "NVIDIA MCP55", enable_flash_mcp55}, /* Gigabyte m57sli-s4 */ + {0x10de, 0x0361, "NVIDIA MCP55", enable_flash_mcp55}, /* LPC */ + {0x10de, 0x0362, "NVIDIA MCP55", enable_flash_mcp55}, /* LPC */ + {0x10de, 0x0363, "NVIDIA MCP55", enable_flash_mcp55}, /* LPC */ + {0x10de, 0x0364, "NVIDIA MCP55", enable_flash_mcp55}, /* LPC */ + {0x10de, 0x0365, "NVIDIA MCP55", enable_flash_mcp55}, /* LPC */ + {0x10de, 0x0366, "NVIDIA MCP55", enable_flash_mcp55}, /* LPC */ + {0x10de, 0x0367, "NVIDIA MCP55", enable_flash_mcp55}, /* Pro */ - {0x1002, 0x4377, "ATI SB400", enable_flash_sb400}, // ATI Technologies Inc IXP SB400 PCI-ISA Bridge (rev 80) + {0x1002, 0x4377, "ATI SB400", enable_flash_sb400}, /* ATI Technologies Inc IXP SB400 PCI-ISA Bridge (rev 80) */ }; -static int mbenable_island_aruma(void) -{ -#define EFIR 0x2e /* Extended function index register, either 0x2e or 0x4e */ -#define EFDR EFIR + 1 /* Extended function data register, one plus the index reg. */ - char b; - -/* Disable the flash write protect. The flash write protect is - * connected to the WinBond w83627hf GPIO 24. +/* + * */ - - printf("Disabling mainboard flash write protection.\n"); - - outb(0x87, EFIR); // sequence to unlock extended functions - outb(0x87, EFIR); - - outb(0x20, EFIR); // SIO device ID register - b = inb(EFDR); - printf_debug("W83627HF device ID = 0x%x\n",b); - - if (b != 0x52) { - perror("Incorrect device ID, aborting write protect disable\n"); - exit(1); - } - - outb(0x2b, EFIR); // GPIO multiplexed pin reg. - b = inb(EFDR) | 0x10; - outb(0x2b, EFIR); - outb(b, EFDR); // select GPIO 24 instead of WDTO - - outb(0x7, EFIR); // logical device select - outb(0x8, EFDR); // point to device 8, GPIO port 2 - - outb(0x30, EFIR); // logic device activation control - outb(0x1, EFDR); // activate - - outb(0xf0, EFIR); // GPIO 20-27 I/O selection register - b = inb(EFDR) & ~0x10; - outb(0xf0, EFIR); - outb(b, EFDR); // set GPIO 24 as an output - - outb(0xf1, EFIR); // GPIO 20-27 data register - b = inb(EFDR) | 0x10; - outb(0xf1, EFIR); - outb(b, EFDR); // set GPIO 24 - - outb(0xaa, EFIR); // command to exit extended functions - - return 0; -} - -typedef struct mbenable { - char *vendor, *part; - int (*doit)(void); -} MAINBOARD_ENABLE; - -static MAINBOARD_ENABLE mbenables[] = { - { "ISLAND", "ARUMA", mbenable_island_aruma }, -}; - -int enable_flash_write() +int +chipset_flash_enable(void) { - int i; - struct pci_dev *dev = 0; - FLASH_ENABLE *enable = 0; + struct pci_dev *dev = 0; + int ret = -2; /* nothing! */ + int i; - /* get io privilege access PCI configuration space */ -#if defined (__sun) && (defined(__i386) || defined(__amd64)) - if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0){ -#else - if (iopl(3) != 0) { -#endif - perror("Can not set io privilege"); - exit(1); - } - - - /* Initialize PCI access */ - 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 */ - - - /* First look whether we have to do something for this - * motherboard. - */ - for (i = 0; i < sizeof(mbenables) / sizeof(mbenables[0]); i++) { - if(lb_vendor && !strcmp(mbenables[i].vendor, lb_vendor) && - lb_part && !strcmp(mbenables[i].part, lb_part)) { - mbenables[i].doit(); - break; - } - } - /* now let's try to find the chipset we have ... */ - for (i = 0; i < sizeof(enables) / sizeof(enables[0]) && (!dev); - i++) { - struct pci_filter f; - struct pci_dev *z; - /* the first param is unused. */ - pci_filter_init((struct pci_access *) 0, &f); - f.vendor = enables[i].vendor; - f.device = enables[i].device; - for (z = pacc->devices; z; z = z->next) - if (pci_filter_match(&f, z)) { - enable = &enables[i]; - dev = z; - } + for (i = 0; i < sizeof(enables) / sizeof(enables[0]); i++) { + dev = pci_dev_find(enables[i].vendor, enables[i].device); + if (dev) + break; + } + + if (dev) { + printf("Found chipset \"%s\": Enabling flash write... ", + enables[i].name); + + ret = enables[i].doit(dev, enables[i].name); + if (ret) + printf("Failed!\n"); + else + printf("OK.\n"); } - if (!enable) { - printf("Warning: Unknown system. Flash detection " - "will most likely fail.\n"); - return 1; - } - - /* now do the deed. */ - printf("Enabling flash write on %s...", enable->name); - if (enable->doit(dev, enable->name) == 0) - printf("OK\n"); - return 0; + return ret; } diff --git a/util/flashrom/flash.h b/util/flashrom/flash.h index 3167fd602a..9f743ddc35 100644 --- a/util/flashrom/flash.h +++ b/util/flashrom/flash.h @@ -3,7 +3,7 @@ * * Copyright 2000 Silicon Integrated System Corporation * Copyright 2000 Ronald G. Minnich - * Copyright 2005 coresystems GmbH + * Copyright 2005-2007 coresystems GmbH * * 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 @@ -128,7 +128,15 @@ extern struct flashchip flashchips[]; extern void myusec_delay(int time); extern void myusec_calibrate_delay(); -extern int enable_flash_write(void); + +/* pci handling for board/chipset_enable */ +extern struct pci_access *pacc; /* For board and chipset_enable */ +extern struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device); +extern struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device, + uint16_t card_vendor, uint16_t card_device); + +extern int board_flash_enable(char *vendor, char *part); /* board_enable.c */ +extern int chipset_flash_enable(void); /* chipset_enable.c */ /* physical memory mapping device */ diff --git a/util/flashrom/flash_rom.c b/util/flashrom/flash_rom.c index 8d04b92a61..ba391cba90 100644 --- a/util/flashrom/flash_rom.c +++ b/util/flashrom/flash_rom.c @@ -35,6 +35,15 @@ #include #include #include +#include + +/* for iopl */ +#if defined (__sun) && (defined(__i386) || defined(__amd64)) +#include +#include +#include +#include +#endif #include "flash.h" #include "lbtable.h" @@ -42,10 +51,54 @@ #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; +/* + * + */ +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) { int fd_mem; @@ -72,10 +125,11 @@ struct flashchip *probe_flash(struct flashchip *flash) __FUNCTION__, flash->total_size * 1024, (unsigned long) size); } + bios = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd_mem, (off_t) (0xffffffff - size + 1)); if (bios == MAP_FAILED) { - perror("Error: Can't mmap /dev/mem."); + perror("Error: Can't mmap " MEM_DEV "."); exit(1); } flash->virt_addr = bios; @@ -92,7 +146,7 @@ struct flashchip *probe_flash(struct flashchip *flash) bios = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd_mem, (off_t) (0x9400000)); if (bios == MAP_FAILED) { - perror("Error: Can't mmap /dev/mem."); + perror("Error: Can't mmap " MEM_DEV "."); exit(1); } flash->virt_addr = bios; @@ -281,6 +335,22 @@ 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){ +#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 */ + printf("Calibrating delay loop... "); myusec_calibrate_delay(); printf("ok\n"); @@ -293,7 +363,13 @@ int main(int argc, char *argv[]) /* try to enable it. Failure IS an option, since not all motherboards * really need this to be done, etc., etc. */ - (void) enable_flash_write(); + 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");