├── .reviewboardrc ├── util ├── ich_descriptors_tool │ ├── TODO │ ├── Makefile │ └── ich_descriptors_tool.c ├── list_yet_unsupported_chips.sh └── z60_flashrom.rules ├── Android.mk ├── arch.h ├── sst49lfxxxc.c ├── serprog.h ├── helpers.c ├── os.h ├── opaque.c ├── stm50.c ├── w29ee011.c ├── processor_enable.c ├── en29lv640b.c ├── sst_fwhub.c ├── it8212.c ├── cli_output.c ├── atahpt.c ├── drkaiser.c ├── sst28sf040.c ├── amd_imc.c ├── nicnatsemi.c ├── nicintel.c ├── nicrealtek.c ├── gfxnvidia.c ├── ogp_spi.c ├── cli_common.c ├── satasii.c ├── programmer.c ├── nic3com.c ├── spi.h ├── coreboot_tables.h ├── bitbang_spi.c ├── mcp6x_spi.c ├── Documentation ├── serprog-protocol.txt └── mysteries_intel.txt ├── pony_spi.c ├── linux_spi.c ├── README ├── udelay.c ├── spi.c ├── atavia.c ├── nicintel_spi.c ├── usbblaster_spi.c ├── w39.c ├── satamv.c ├── wbsio_spi.c ├── 82802ab.c └── rayer_spi.c /.reviewboardrc: -------------------------------------------------------------------------------- 1 | REVIEWBOARD_URL = 'https://reviews.leaflabs.com/' 2 | REPOSITORY = 'flashrom' 3 | GUESS_FIELDS = 'auto' 4 | TARGET_GROUPS = 'ara-firmware' 5 | -------------------------------------------------------------------------------- /util/ich_descriptors_tool/TODO: -------------------------------------------------------------------------------- 1 | - reverse the path: assemble a descriptormode image from various 2 | blobs (BIOS, GbE, ME, OEM) and a description (xml? custom config? 3 | sane defaults and cmd-line switches?) 4 | - dump 256 OEM bytes 5 | - deal with the various possible locations of mac address(es?) 6 | /* mazzoo said: from what I've seen, the MAC address is the 1st or 7 | * 2nd 6 bytes in the GbE region. It seems the PXE-OpROM and/or the 8 | * intel EEUPDATE-tool copies the MAC address to the 2nd part. 9 | */ 10 | - add descriptions for the missing chipsets 11 | -------------------------------------------------------------------------------- /util/list_yet_unsupported_chips.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | scriptname=$(readlink -f "$0") 2>/dev/null 4 | path=$(dirname "$scriptname")/.. 2>/dev/null 5 | if [ ! -e "$path/flashchips.c" -o ! -e "$path/flashchips.h" ]; then 6 | echo "Warning: could not calculate flashchips.[ch]'s directory. Trying current..." 7 | path="." 8 | if [ ! -e "$path/flashchips.c" -o ! -e "$path/flashchips.h" ]; then 9 | echo "Nope, sorry!" 10 | exit 1 11 | fi 12 | fi 13 | 14 | chips=$(sed -re '/#define [A-Z]/ !d' -e '/_ID\s/d' -e 's/\s*#define\s+([[:alnum:]_]+)\s+.*/\1/' "$path/flashchips.h") 15 | for c in $chips ; do 16 | if ! grep "$c" "$path/flashchips.c" >/dev/null ; then 17 | if [ -n "$1" ]; then 18 | grep -o "$c.*" "$path/flashchips.h" 19 | else 20 | echo "$c" 21 | fi 22 | fi 23 | done 24 | -------------------------------------------------------------------------------- /Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | include $(CLEAR_VARS) 3 | 4 | SVNVERSION := $(shell $(LOCAL_PATH)/util/getrevision.sh -u) 5 | 6 | RELEASE := 0.9.7 7 | VERSION := $(RELEASE)-$(SVNVERSION) 8 | RELEASENAME ?= $(VERSION) 9 | 10 | LOCAL_MODULE := flashrom 11 | LOCAL_MODULE_TAGS := optional 12 | # FIXME Should add arm64 support in hwaccess.h instead of doing that 13 | LOCAL_CFLAGS += -D'FLASHROM_VERSION="$(VERSION)"' 14 | LOCAL_CFLAGS += -D'CONFIG_DEFAULT_PROGRAMMER=PROGRAMMER_INVALID' 15 | LOCAL_CFLAGS += -D'CONFIG_DEFAULT_PROGRAMMER_ARGS=""' 16 | # We only need linux_spi programmer 17 | LOCAL_CFLAGS += -D'CONFIG_LINUX_SPI=1' 18 | 19 | # Flashrom sources 20 | LOCAL_SRC_FILES := cli_classic.c cli_output.c print.c flashrom.c cli_common.c \ 21 | helpers.c layout.c udelay.c 22 | # Memory drivers 23 | LOCAL_SRC_FILES += flashchips.c jedec.c spi25.c opaque.c w39.c spi.c at45db.c \ 24 | en29lv640b.c sfdp.c 82802ab.c sst_fwhub.c spi25_statusreg.c \ 25 | stm50.c sst49lfxxxc.c sst28sf040.c w29ee011.c 26 | # Programmers 27 | LOCAL_SRC_FILES += linux_spi.c programmer.c 28 | 29 | LOCAL_LIBRARIES += libstdc++ libc libm 30 | 31 | include $(BUILD_EXECUTABLE) 32 | 33 | -------------------------------------------------------------------------------- /arch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2011 Carl-Daniel Hailfinger 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | /* 21 | * Header file for CPU architecture checking. 22 | */ 23 | 24 | #if defined (__i386__) || defined (__x86_64__) 25 | #define __FLASHROM_ARCH__ "x86" 26 | #elif defined (__mips) || defined (__mips__) || defined (_mips) || defined (mips) 27 | #define __FLASHROM_ARCH__ "mips" 28 | #elif defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || defined(__ppc64__) 29 | #define __FLASHROM_ARCH__ "ppc" 30 | #elif defined(__arm__) 31 | #define __FLASHROM_ARCH__ "arm" 32 | #endif 33 | __FLASHROM_ARCH__ 34 | -------------------------------------------------------------------------------- /sst49lfxxxc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2000 Silicon Integrated System Corporation 5 | * Copyright (C) 2005-2007 coresystems GmbH 6 | * Copyright (C) 2009 Sean Nelson 7 | * 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. 12 | * 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. 17 | * 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 21 | */ 22 | 23 | #include "flash.h" 24 | #include "chipdrivers.h" 25 | 26 | int erase_sector_49lfxxxc(struct flashctx *flash, unsigned int address, 27 | unsigned int sector_size) 28 | { 29 | uint8_t status; 30 | chipaddr bios = flash->virtual_memory; 31 | 32 | chip_writeb(flash, 0x30, bios); 33 | chip_writeb(flash, 0xD0, bios + address); 34 | 35 | status = wait_82802ab(flash); 36 | print_status_82802ab(status); 37 | 38 | /* FIXME: Check the status register for errors. */ 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /serprog.h: -------------------------------------------------------------------------------- 1 | /* According to Serial Flasher Protocol Specification - version 1 */ 2 | #define S_ACK 0x06 3 | #define S_NAK 0x15 4 | #define S_CMD_NOP 0x00 /* No operation */ 5 | #define S_CMD_Q_IFACE 0x01 /* Query interface version */ 6 | #define S_CMD_Q_CMDMAP 0x02 /* Query supported commands bitmap */ 7 | #define S_CMD_Q_PGMNAME 0x03 /* Query programmer name */ 8 | #define S_CMD_Q_SERBUF 0x04 /* Query Serial Buffer Size */ 9 | #define S_CMD_Q_BUSTYPE 0x05 /* Query supported bustypes */ 10 | #define S_CMD_Q_CHIPSIZE 0x06 /* Query supported chipsize (2^n format) */ 11 | #define S_CMD_Q_OPBUF 0x07 /* Query operation buffer size */ 12 | #define S_CMD_Q_WRNMAXLEN 0x08 /* Query Write to opbuf: Write-N maximum length */ 13 | #define S_CMD_R_BYTE 0x09 /* Read a single byte */ 14 | #define S_CMD_R_NBYTES 0x0A /* Read n bytes */ 15 | #define S_CMD_O_INIT 0x0B /* Initialize operation buffer */ 16 | #define S_CMD_O_WRITEB 0x0C /* Write opbuf: Write byte with address */ 17 | #define S_CMD_O_WRITEN 0x0D /* Write to opbuf: Write-N */ 18 | #define S_CMD_O_DELAY 0x0E /* Write opbuf: udelay */ 19 | #define S_CMD_O_EXEC 0x0F /* Execute operation buffer */ 20 | #define S_CMD_SYNCNOP 0x10 /* Special no-operation that returns NAK+ACK */ 21 | #define S_CMD_Q_RDNMAXLEN 0x11 /* Query read-n maximum length */ 22 | #define S_CMD_S_BUSTYPE 0x12 /* Set used bustype(s). */ 23 | #define S_CMD_O_SPIOP 0x13 /* Perform SPI operation. */ 24 | #define S_CMD_S_SPI_FREQ 0x14 /* Set SPI clock frequency */ 25 | #define S_CMD_S_PIN_STATE 0x15 /* Enable/disable output drivers */ 26 | -------------------------------------------------------------------------------- /helpers.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2009-2010 Carl-Daniel Hailfinger 5 | * Copyright (C) 2013 Stefan Tauner 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include "flash.h" 26 | 27 | /* Returns the minimum number of bits needed to represent the given address. 28 | * FIXME: use mind-blowing implementation. */ 29 | uint32_t address_to_bits(uint32_t addr) 30 | { 31 | unsigned int lzb = 0; 32 | while (((1 << (31 - lzb)) & ~addr) != 0) 33 | lzb++; 34 | return 32 - lzb; 35 | } 36 | 37 | int bitcount(unsigned long a) 38 | { 39 | int i = 0; 40 | for (; a != 0; a >>= 1) 41 | if (a & 1) 42 | i++; 43 | return i; 44 | } 45 | 46 | int max(int a, int b) 47 | { 48 | return (a > b) ? a : b; 49 | } 50 | 51 | int min(int a, int b) 52 | { 53 | return (a < b) ? a : b; 54 | } 55 | 56 | char *strcat_realloc(char *dest, const char *src) 57 | { 58 | dest = realloc(dest, strlen(dest) + strlen(src) + 1); 59 | if (!dest) { 60 | msg_gerr("Out of memory!\n"); 61 | return NULL; 62 | } 63 | strcat(dest, src); 64 | return dest; 65 | } 66 | 67 | void tolower_string(char *str) 68 | { 69 | for (; *str != '\0'; str++) 70 | *str = (char)tolower((unsigned char)*str); 71 | } 72 | 73 | -------------------------------------------------------------------------------- /util/ich_descriptors_tool/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This file is part of the flashrom project. 3 | # 4 | # This Makefile works standalone, but it is usually called from the main 5 | # Makefile in the flashrom directory. 6 | 7 | PROGRAM=ich_descriptors_tool 8 | EXTRAINCDIRS = ../../ . 9 | DEPPATH = .dep 10 | OBJATH = .obj 11 | SHAREDSRC = ich_descriptors.c 12 | SHAREDSRCDIR = ../.. 13 | # If your compiler spits out excessive warnings, run make WARNERROR=no 14 | # You shouldn't have to change this flag. 15 | WARNERROR ?= yes 16 | 17 | SRC = $(wildcard *.c) 18 | 19 | CC ?= gcc 20 | 21 | # If the user has specified custom CFLAGS, all CFLAGS settings below will be 22 | # completely ignored by gnumake. 23 | CFLAGS ?= -Os -Wall -Wshadow 24 | ifeq ($(TARGET_OS), DOS) 25 | # DJGPP has odd uint*_t definitions which cause lots of format string warnings. 26 | CFLAGS += -Wno-format 27 | endif 28 | ifeq ($(WARNERROR), yes) 29 | CFLAGS += -Werror 30 | endif 31 | 32 | 33 | FLASHROM_CFLAGS += -MMD -MP -MF $(DEPPATH)/$(@F).d 34 | # enables functions that populate the descriptor structs from plain binary dumps 35 | FLASHROM_CFLAGS += -D ICH_DESCRIPTORS_FROM_DUMP 36 | FLASHROM_CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) 37 | 38 | OBJ = $(OBJATH)/$(SRC:%.c=%.o) 39 | 40 | SHAREDOBJ = $(OBJATH)/$(notdir $(SHAREDSRC:%.c=%.o)) 41 | 42 | all:$(PROGRAM)$(EXEC_SUFFIX) 43 | 44 | $(OBJ): $(OBJATH)/%.o : %.c 45 | $(CC) $(CFLAGS) $(CPPFLAGS) $(FLASHROM_CFLAGS) -o $@ -c $< 46 | 47 | # this enables us to share source files without simultaneously sharing .o files 48 | # with flashrom, which would lead to unexpected results (w/o running make clean) 49 | $(SHAREDOBJ): $(OBJATH)/%.o : $(SHAREDSRCDIR)/%.c 50 | $(CC) $(CFLAGS) $(CPPFLAGS) $(FLASHROM_CFLAGS) -o $@ -c $< 51 | 52 | $(PROGRAM)$(EXEC_SUFFIX): $(OBJ) $(SHAREDOBJ) 53 | $(CC) $(LDFLAGS) -o $(PROGRAM)$(EXEC_SUFFIX) $(OBJ) $(SHAREDOBJ) 54 | 55 | clean: 56 | rm -f $(PROGRAM) $(PROGRAM).exe 57 | rm -rf $(DEPPATH) $(OBJATH) 58 | 59 | # Include the dependency files. 60 | -include $(shell mkdir -p $(DEPPATH) $(OBJATH) 2>/dev/null) $(wildcard $(DEPPATH)/*) 61 | 62 | .PHONY: all clean 63 | -------------------------------------------------------------------------------- /os.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2011 Carl-Daniel Hailfinger 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | /* 21 | * Header file for OS checking. 22 | */ 23 | 24 | // Solaris 25 | #if defined (__sun) && (defined(__i386) || defined(__amd64)) 26 | #define __FLASHROM_OS__ "SunOS" 27 | // OS X 28 | #elif defined(__MACH__) && defined(__APPLE__) 29 | #define __FLASHROM_OS__ "Darwin" 30 | // FreeBSD 31 | #elif defined(__FreeBSD__) 32 | #define __FLASHROM_OS__ "FreeBSD" 33 | // FreeBSD with glibc-based userspace (e.g. Debian/kFreeBSD) 34 | #elif defined(__FreeBSD_kernel__) && defined(__GLIBC__) 35 | #define __FLASHROM_OS__ "FreeBSD-glibc" 36 | // DragonFlyBSD 37 | #elif defined(__DragonFly__) 38 | #define __FLASHROM_OS__ "DragonFlyBSD" 39 | // NetBSD 40 | #elif defined(__NetBSD__) 41 | #define __FLASHROM_OS__ "NetBSD" 42 | // OpenBSD 43 | #elif defined(__OpenBSD__) 44 | #define __FLASHROM_OS__ "OpenBSD" 45 | // DJGPP 46 | #elif defined(__DJGPP__) 47 | #define __FLASHROM_OS__ "DOS" 48 | // MinGW (always has _WIN32 available) 49 | #elif defined(__MINGW32__) 50 | #define __FLASHROM_OS__ "MinGW" 51 | // Cygwin (usually without _WIN32) 52 | #elif defined( __CYGWIN__) 53 | #define __FLASHROM_OS__ "Cygwin" 54 | // libpayload 55 | #elif defined(__LIBPAYLOAD__) 56 | #define __FLASHROM_OS__ "libpayload" 57 | // Linux 58 | #elif defined(__linux__) 59 | #define __FLASHROM_OS__ "Linux" 60 | #endif 61 | __FLASHROM_OS__ 62 | -------------------------------------------------------------------------------- /opaque.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2011,2013,2014 Carl-Daniel Hailfinger 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | /* 21 | * Contains the opaque master framework. 22 | * An opaque master is a master which does not provide direct access 23 | * to the flash chip and which abstracts all flash chip properties into a 24 | * master specific interface. 25 | */ 26 | 27 | #include 28 | #include "flash.h" 29 | #include "flashchips.h" 30 | #include "chipdrivers.h" 31 | #include "programmer.h" 32 | 33 | int probe_opaque(struct flashctx *flash) 34 | { 35 | return flash->mst->opaque.probe(flash); 36 | } 37 | 38 | int read_opaque(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len) 39 | { 40 | return flash->mst->opaque.read(flash, buf, start, len); 41 | } 42 | 43 | int write_opaque(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) 44 | { 45 | return flash->mst->opaque.write(flash, buf, start, len); 46 | } 47 | 48 | int erase_opaque(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen) 49 | { 50 | return flash->mst->opaque.erase(flash, blockaddr, blocklen); 51 | } 52 | 53 | int register_opaque_master(const struct opaque_master *mst) 54 | { 55 | struct registered_master rmst; 56 | 57 | if (!mst->probe || !mst->read || !mst->write || !mst->erase) { 58 | msg_perr("%s called with incomplete master definition. " 59 | "Please report a bug at flashrom@flashrom.org\n", 60 | __func__); 61 | return ERROR_FLASHROM_BUG; 62 | } 63 | rmst.buses_supported = BUS_PROG; 64 | rmst.opaque = *mst; 65 | return register_master(&rmst); 66 | } 67 | -------------------------------------------------------------------------------- /stm50.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2008 Claus Gindhart 5 | * Copyright (C) 2009 Sean Nelson 6 | * Copyright (C) 2013 Stefan Tauner 7 | * 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. 12 | * 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. 17 | * 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 21 | */ 22 | 23 | /* 24 | * All ST M50 chips are locked on startup. Most of them have a uniform 64 kB block layout, but some have 25 | * a non-uniform block/sector segmentation which has to be handled with more care. Some of the non-uniform 26 | * chips support erasing of the 4 kB sectors with another command. 27 | */ 28 | 29 | #include "flash.h" 30 | #include "chipdrivers.h" 31 | 32 | static int stm50_erase_sector(struct flashctx *flash, unsigned int addr) 33 | { 34 | chipaddr bios = flash->virtual_memory + addr; 35 | 36 | // clear status register 37 | chip_writeb(flash, 0x50, bios); 38 | // now start it 39 | chip_writeb(flash, 0x32, bios); 40 | chip_writeb(flash, 0xd0, bios); 41 | programmer_delay(10); 42 | 43 | uint8_t status = wait_82802ab(flash); 44 | print_status_82802ab(status); 45 | 46 | return status == 0x80; 47 | } 48 | 49 | /* Some ST M50* chips do support erasing of sectors. This function will derive the erase function to use from 50 | * the length of the of the block. For calls that apparently do not address a sector (but a block) we just call 51 | * the block erase function instead. FIXME: This duplicates the behavior of the remaining erasers for blocks and 52 | * might be fixed when flashrom supports multiple functions per eraser or erasers that do erase parts of the 53 | * chip only. */ 54 | int erase_sector_stm50(struct flashctx *flash, unsigned int addr, unsigned int len) 55 | { 56 | if (len == 4096) 57 | return stm50_erase_sector(flash, addr); 58 | else 59 | return erase_block_82802ab(flash, addr, len); 60 | } 61 | -------------------------------------------------------------------------------- /w29ee011.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2007 Markus Boas 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include 22 | #include "flash.h" 23 | 24 | /* According to the Winbond W29EE011, W29EE012, W29C010M, W29C011A 25 | * datasheets this is the only valid probe function for those chips. 26 | */ 27 | int probe_w29ee011(struct flashctx *flash) 28 | { 29 | chipaddr bios = flash->virtual_memory; 30 | uint8_t id1, id2; 31 | 32 | if (!chip_to_probe || strcmp(chip_to_probe, flash->chip->name)) { 33 | msg_cdbg("Old Winbond W29* probe method disabled because " 34 | "the probing sequence puts the AMIC A49LF040A in " 35 | "a funky state. Use 'flashrom -c %s' if you " 36 | "have a board with such a chip.\n", flash->chip->name); 37 | return 0; 38 | } 39 | 40 | /* Issue JEDEC Product ID Entry command */ 41 | chip_writeb(flash, 0xAA, bios + 0x5555); 42 | programmer_delay(10); 43 | chip_writeb(flash, 0x55, bios + 0x2AAA); 44 | programmer_delay(10); 45 | chip_writeb(flash, 0x80, bios + 0x5555); 46 | programmer_delay(10); 47 | chip_writeb(flash, 0xAA, bios + 0x5555); 48 | programmer_delay(10); 49 | chip_writeb(flash, 0x55, bios + 0x2AAA); 50 | programmer_delay(10); 51 | chip_writeb(flash, 0x60, bios + 0x5555); 52 | programmer_delay(10); 53 | 54 | /* Read product ID */ 55 | id1 = chip_readb(flash, bios); 56 | id2 = chip_readb(flash, bios + 0x01); 57 | 58 | /* Issue JEDEC Product ID Exit command */ 59 | chip_writeb(flash, 0xAA, bios + 0x5555); 60 | programmer_delay(10); 61 | chip_writeb(flash, 0x55, bios + 0x2AAA); 62 | programmer_delay(10); 63 | chip_writeb(flash, 0xF0, bios + 0x5555); 64 | programmer_delay(10); 65 | 66 | msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2); 67 | 68 | if (id1 == flash->chip->manufacture_id && id2 == flash->chip->model_id) 69 | return 1; 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /processor_enable.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2010 Carl-Daniel Hailfinger 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | /* 21 | * Contains the processor specific flash enables and system settings. 22 | */ 23 | 24 | #include "flash.h" 25 | #include "programmer.h" 26 | 27 | #if defined (__MIPSEL__) && defined (__linux) 28 | #include 29 | #include 30 | #include 31 | 32 | static int is_loongson(void) 33 | { 34 | FILE *cpuinfo; 35 | cpuinfo = fopen("/proc/cpuinfo", "rb"); 36 | if (!cpuinfo) 37 | return 0; 38 | while (!feof(cpuinfo)) { 39 | char line[512], *ptr; 40 | if (fgets(line, sizeof(line), cpuinfo) == NULL) 41 | break; 42 | ptr = line; 43 | while (*ptr && isspace((unsigned char)*ptr)) 44 | ptr++; 45 | /* "cpu" part appears only with some Linux versions. */ 46 | if (strncmp(ptr, "cpu", strlen("cpu")) == 0) 47 | ptr += strlen("cpu"); 48 | while (*ptr && isspace((unsigned char)*ptr)) 49 | ptr++; 50 | if (strncmp(ptr, "model", strlen("model")) != 0) 51 | continue; 52 | ptr += strlen("model"); 53 | while (*ptr && isspace((unsigned char)*ptr)) 54 | ptr++; 55 | if (*ptr != ':') 56 | continue; 57 | ptr++; 58 | while (*ptr && isspace((unsigned char)*ptr)) 59 | ptr++; 60 | fclose(cpuinfo); 61 | return (strncmp(ptr, "ICT Loongson-2 V0.3", strlen("ICT Loongson-2 V0.3")) == 0) || 62 | (strncmp(ptr, "Godson2 V0.3 FPU V0.1", strlen("Godson2 V0.3 FPU V0.1")) == 0); 63 | } 64 | fclose(cpuinfo); 65 | return 0; 66 | } 67 | #endif 68 | 69 | int processor_flash_enable(void) 70 | { 71 | /* Default to 1 to catch not implemented architectures. */ 72 | int ret = 1; 73 | 74 | /* FIXME: detect loongson on FreeBSD and OpenBSD as well. */ 75 | #if defined (__MIPSEL__) && defined (__linux) 76 | if (is_loongson()) { 77 | flashbase = 0x1fc00000; 78 | ret = 0; 79 | } 80 | #elif defined(__i386__) || defined(__x86_64__) 81 | /* On x86, flash access is not processor specific except on 82 | * AMD Elan SC520, AMD Geode and maybe other SoC-style CPUs. 83 | * FIXME: Move enable_flash_cs5536 and get_flashbase_sc520 here. 84 | */ 85 | ret = 0; 86 | #endif 87 | return ret; 88 | } 89 | -------------------------------------------------------------------------------- /en29lv640b.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2000 Silicon Integrated System Corporation 5 | * Copyright (C) 2012 Rudolf Marek 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include "flash.h" 23 | #include "chipdrivers.h" 24 | 25 | /* 26 | * WARNING! 27 | * This chip uses the standard JEDEC addresses in 16-bit mode as word 28 | * addresses. In byte mode, 0xAAA has to be used instead of 0x555 and 29 | * 0x555 instead of 0x2AA. Do *not* blindly replace with standard JEDEC 30 | * functions. 31 | */ 32 | 33 | /* chunksize is 1 */ 34 | int write_en29lv640b(struct flashctx *flash, const uint8_t *src, unsigned int start, unsigned int len) 35 | { 36 | int i; 37 | chipaddr bios = flash->virtual_memory; 38 | chipaddr dst = flash->virtual_memory + start; 39 | 40 | for (i = 0; i < len; i += 2) { 41 | chip_writeb(flash, 0xAA, bios + 0xAAA); 42 | chip_writeb(flash, 0x55, bios + 0x555); 43 | chip_writeb(flash, 0xA0, bios + 0xAAA); 44 | 45 | /* Transfer data from source to destination. */ 46 | chip_writew(flash, (*src) | ((*(src + 1)) << 8 ), dst); 47 | toggle_ready_jedec(flash, dst); 48 | #if 0 49 | /* We only want to print something in the error case. */ 50 | msg_cerr("Value in the flash at address 0x%lx = %#x, want %#x\n", 51 | (dst - bios), chip_readb(flash, dst), *src); 52 | #endif 53 | dst += 2; 54 | src += 2; 55 | } 56 | 57 | /* FIXME: Ignore errors for now. */ 58 | return 0; 59 | } 60 | 61 | int probe_en29lv640b(struct flashctx *flash) 62 | { 63 | chipaddr bios = flash->virtual_memory; 64 | uint16_t id1, id2; 65 | 66 | chip_writeb(flash, 0xAA, bios + 0xAAA); 67 | chip_writeb(flash, 0x55, bios + 0x555); 68 | chip_writeb(flash, 0x90, bios + 0xAAA); 69 | 70 | programmer_delay(10); 71 | 72 | id1 = chip_readb(flash, bios + 0x200); 73 | id1 |= (chip_readb(flash, bios) << 8); 74 | 75 | id2 = chip_readb(flash, bios + 0x02); 76 | 77 | chip_writeb(flash, 0xF0, bios + 0xAAA); 78 | 79 | programmer_delay(10); 80 | 81 | msg_cdbg("%s: id1 0x%04x, id2 0x%04x\n", __func__, id1, id2); 82 | 83 | if (id1 == flash->chip->manufacture_id && id2 == flash->chip->model_id) 84 | return 1; 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /sst_fwhub.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2000 Silicon Integrated System Corporation 5 | * Copyright (C) 2009 Kontron Modular Computers 6 | * Copyright (C) 2009 Sean Nelson 7 | * 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. 12 | * 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. 17 | * 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 21 | */ 22 | 23 | /* Adapted from the Intel FW hub stuff for 82802ax parts. */ 24 | 25 | #include "flash.h" 26 | 27 | static int check_sst_fwhub_block_lock(struct flashctx *flash, int offset) 28 | { 29 | chipaddr registers = flash->virtual_registers; 30 | uint8_t blockstatus; 31 | 32 | blockstatus = chip_readb(flash, registers + offset + 2); 33 | msg_cdbg("Lock status for 0x%06x (size 0x%06x) is %02x, ", 34 | offset, flash->chip->page_size, blockstatus); 35 | switch (blockstatus & 0x3) { 36 | case 0x0: 37 | msg_cdbg("full access\n"); 38 | break; 39 | case 0x1: 40 | msg_cdbg("write locked\n"); 41 | break; 42 | case 0x2: 43 | msg_cdbg("locked open\n"); 44 | break; 45 | case 0x3: 46 | msg_cdbg("write locked down\n"); 47 | break; 48 | } 49 | /* Return content of the write_locked bit */ 50 | return blockstatus & 0x1; 51 | } 52 | 53 | static int clear_sst_fwhub_block_lock(struct flashctx *flash, int offset) 54 | { 55 | chipaddr registers = flash->virtual_registers; 56 | uint8_t blockstatus; 57 | 58 | blockstatus = check_sst_fwhub_block_lock(flash, offset); 59 | 60 | if (blockstatus) { 61 | msg_cdbg("Trying to clear lock for 0x%06x... ", offset); 62 | chip_writeb(flash, 0, registers + offset + 2); 63 | 64 | blockstatus = check_sst_fwhub_block_lock(flash, offset); 65 | msg_cdbg("%s\n", (blockstatus) ? "failed" : "OK"); 66 | } 67 | 68 | return blockstatus; 69 | } 70 | 71 | int printlock_sst_fwhub(struct flashctx *flash) 72 | { 73 | int i; 74 | 75 | for (i = 0; i < flash->chip->total_size * 1024; i += flash->chip->page_size) 76 | check_sst_fwhub_block_lock(flash, i); 77 | 78 | return 0; 79 | } 80 | 81 | int unlock_sst_fwhub(struct flashctx *flash) 82 | { 83 | int i, ret=0; 84 | 85 | for (i = 0; i < flash->chip->total_size * 1024; i += flash->chip->page_size) 86 | { 87 | if (clear_sst_fwhub_block_lock(flash, i)) 88 | { 89 | msg_cwarn("Warning: Unlock Failed for block 0x%06x\n", i); 90 | ret++; 91 | } 92 | } 93 | return ret; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /it8212.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2011 Carl-Daniel Hailfinger 5 | * Copyright (C) 2012 Kyösti Mälkki 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; version 2 of the License. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include 22 | #include "flash.h" 23 | #include "programmer.h" 24 | #include "hwaccess.h" 25 | 26 | static uint8_t *it8212_bar = NULL; 27 | 28 | #define PCI_VENDOR_ID_ITE 0x1283 29 | 30 | const struct dev_entry devs_it8212[] = { 31 | {PCI_VENDOR_ID_ITE, 0x8212, NT, "ITE", "8212F PATA RAID"}, 32 | 33 | {}, 34 | }; 35 | 36 | #define IT8212_MEMMAP_SIZE (128 * 1024) 37 | #define IT8212_MEMMAP_MASK (IT8212_MEMMAP_SIZE - 1) 38 | 39 | static void it8212_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr); 40 | static uint8_t it8212_chip_readb(const struct flashctx *flash, const chipaddr addr); 41 | static const struct par_master par_master_it8212 = { 42 | .chip_readb = it8212_chip_readb, 43 | .chip_readw = fallback_chip_readw, 44 | .chip_readl = fallback_chip_readl, 45 | .chip_readn = fallback_chip_readn, 46 | .chip_writeb = it8212_chip_writeb, 47 | .chip_writew = fallback_chip_writew, 48 | .chip_writel = fallback_chip_writel, 49 | .chip_writen = fallback_chip_writen, 50 | }; 51 | 52 | int it8212_init(void) 53 | { 54 | if (rget_io_perms()) 55 | return 1; 56 | 57 | struct pci_dev *dev = pcidev_init(devs_it8212, PCI_ROM_ADDRESS); 58 | if (!dev) 59 | return 1; 60 | 61 | /* Bit 0 is address decode enable, 17-31 the base address, everything else reserved/zero. */ 62 | uint32_t io_base_addr = pcidev_readbar(dev, PCI_ROM_ADDRESS) & 0xFFFFFFFE; 63 | if (!io_base_addr) 64 | return 1; 65 | 66 | it8212_bar = rphysmap("IT8212F flash", io_base_addr, IT8212_MEMMAP_SIZE); 67 | if (it8212_bar == ERROR_PTR) 68 | return 1; 69 | 70 | /* Restore ROM BAR decode state automatically at shutdown. */ 71 | rpci_write_long(dev, PCI_ROM_ADDRESS, io_base_addr | 0x01); 72 | 73 | max_rom_decode.parallel = IT8212_MEMMAP_SIZE; 74 | register_par_master(&par_master_it8212, BUS_PARALLEL); 75 | return 0; 76 | } 77 | 78 | static void it8212_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr) 79 | { 80 | pci_mmio_writeb(val, it8212_bar + (addr & IT8212_MEMMAP_MASK)); 81 | } 82 | 83 | static uint8_t it8212_chip_readb(const struct flashctx *flash, const chipaddr addr) 84 | { 85 | return pci_mmio_readb(it8212_bar + (addr & IT8212_MEMMAP_MASK)); 86 | } 87 | -------------------------------------------------------------------------------- /cli_output.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2009 Sean Nelson 5 | * Copyright (C) 2011 Carl-Daniel Hailfinger 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "flash.h" 27 | 28 | int verbose_screen = MSG_INFO; 29 | int verbose_logfile = MSG_DEBUG2; 30 | 31 | #ifndef STANDALONE 32 | static FILE *logfile = NULL; 33 | 34 | int close_logfile(void) 35 | { 36 | if (!logfile) 37 | return 0; 38 | /* No need to call fflush() explicitly, fclose() already does that. */ 39 | if (fclose(logfile)) { 40 | /* fclose returned an error. Stop writing to be safe. */ 41 | logfile = NULL; 42 | msg_gerr("Closing the log file returned error %s\n", strerror(errno)); 43 | return 1; 44 | } 45 | logfile = NULL; 46 | return 0; 47 | } 48 | 49 | int open_logfile(const char * const filename) 50 | { 51 | if (!filename) { 52 | msg_gerr("No logfile name specified.\n"); 53 | return 1; 54 | } 55 | if ((logfile = fopen(filename, "w")) == NULL) { 56 | msg_gerr("Error: opening log file \"%s\" failed: %s\n", filename, strerror(errno)); 57 | return 1; 58 | } 59 | return 0; 60 | } 61 | 62 | void start_logging(void) 63 | { 64 | enum msglevel oldverbose_screen = verbose_screen; 65 | 66 | /* Shut up the console. */ 67 | verbose_screen = MSG_ERROR; 68 | print_version(); 69 | verbose_screen = oldverbose_screen; 70 | } 71 | #endif /* !STANDALONE */ 72 | 73 | /* Please note that level is the verbosity, not the importance of the message. */ 74 | int print(enum msglevel level, const char *fmt, ...) 75 | { 76 | va_list ap; 77 | int ret = 0; 78 | FILE *output_type = stdout; 79 | 80 | if (level < MSG_INFO) 81 | output_type = stderr; 82 | 83 | if (level <= verbose_screen) { 84 | va_start(ap, fmt); 85 | ret = vfprintf(output_type, fmt, ap); 86 | va_end(ap); 87 | /* msg_*spew often happens inside chip accessors in possibly 88 | * time-critical operations. Don't slow them down by flushing. */ 89 | if (level != MSG_SPEW) 90 | fflush(output_type); 91 | } 92 | #ifndef STANDALONE 93 | if ((level <= verbose_logfile) && logfile) { 94 | va_start(ap, fmt); 95 | ret = vfprintf(logfile, fmt, ap); 96 | va_end(ap); 97 | if (level != MSG_SPEW) 98 | fflush(logfile); 99 | } 100 | #endif /* !STANDALONE */ 101 | return ret; 102 | } 103 | -------------------------------------------------------------------------------- /atahpt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2010 Uwe Hermann 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #if defined(__i386__) || defined(__x86_64__) 22 | 23 | #include 24 | #include 25 | #include "flash.h" 26 | #include "programmer.h" 27 | #include "hwaccess.h" 28 | 29 | #define BIOS_ROM_ADDR 0x90 30 | #define BIOS_ROM_DATA 0x94 31 | 32 | #define REG_FLASH_ACCESS 0x58 33 | 34 | #define PCI_VENDOR_ID_HPT 0x1103 35 | 36 | static uint32_t io_base_addr = 0; 37 | 38 | const struct dev_entry ata_hpt[] = { 39 | {0x1103, 0x0004, NT, "Highpoint", "HPT366/368/370/370A/372/372N"}, 40 | {0x1103, 0x0005, NT, "Highpoint", "HPT372A/372N"}, 41 | {0x1103, 0x0006, NT, "Highpoint", "HPT302/302N"}, 42 | 43 | {0}, 44 | }; 45 | 46 | static void atahpt_chip_writeb(const struct flashctx *flash, uint8_t val, 47 | chipaddr addr); 48 | static uint8_t atahpt_chip_readb(const struct flashctx *flash, 49 | const chipaddr addr); 50 | static const struct par_master par_master_atahpt = { 51 | .chip_readb = atahpt_chip_readb, 52 | .chip_readw = fallback_chip_readw, 53 | .chip_readl = fallback_chip_readl, 54 | .chip_readn = fallback_chip_readn, 55 | .chip_writeb = atahpt_chip_writeb, 56 | .chip_writew = fallback_chip_writew, 57 | .chip_writel = fallback_chip_writel, 58 | .chip_writen = fallback_chip_writen, 59 | }; 60 | 61 | int atahpt_init(void) 62 | { 63 | struct pci_dev *dev = NULL; 64 | uint32_t reg32; 65 | 66 | if (rget_io_perms()) 67 | return 1; 68 | 69 | dev = pcidev_init(ata_hpt, PCI_BASE_ADDRESS_4); 70 | if (!dev) 71 | return 1; 72 | 73 | io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_4); 74 | if (!io_base_addr) 75 | return 1; 76 | 77 | /* Enable flash access. */ 78 | reg32 = pci_read_long(dev, REG_FLASH_ACCESS); 79 | reg32 |= (1 << 24); 80 | rpci_write_long(dev, REG_FLASH_ACCESS, reg32); 81 | 82 | register_par_master(&par_master_atahpt, BUS_PARALLEL); 83 | 84 | return 0; 85 | } 86 | 87 | static void atahpt_chip_writeb(const struct flashctx *flash, uint8_t val, 88 | chipaddr addr) 89 | { 90 | OUTL((uint32_t)addr, io_base_addr + BIOS_ROM_ADDR); 91 | OUTB(val, io_base_addr + BIOS_ROM_DATA); 92 | } 93 | 94 | static uint8_t atahpt_chip_readb(const struct flashctx *flash, 95 | const chipaddr addr) 96 | { 97 | OUTL((uint32_t)addr, io_base_addr + BIOS_ROM_ADDR); 98 | return INB(io_base_addr + BIOS_ROM_DATA); 99 | } 100 | 101 | #else 102 | #error PCI port I/O access is not supported on this architecture yet. 103 | #endif 104 | -------------------------------------------------------------------------------- /drkaiser.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2009 Joerg Fischer 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include 22 | #include "flash.h" 23 | #include "programmer.h" 24 | #include "hwaccess.h" 25 | 26 | #define PCI_VENDOR_ID_DRKAISER 0x1803 27 | 28 | #define PCI_MAGIC_DRKAISER_ADDR 0x50 29 | #define PCI_MAGIC_DRKAISER_VALUE 0xa971 30 | 31 | #define DRKAISER_MEMMAP_SIZE (1024 * 128) 32 | 33 | /* Mask to restrict flash accesses to the 128kB memory window. */ 34 | #define DRKAISER_MEMMAP_MASK ((1 << 17) - 1) 35 | 36 | const struct dev_entry drkaiser_pcidev[] = { 37 | {0x1803, 0x5057, OK, "Dr. Kaiser", "PC-Waechter (Actel FPGA)"}, 38 | 39 | {0}, 40 | }; 41 | 42 | static uint8_t *drkaiser_bar; 43 | 44 | static void drkaiser_chip_writeb(const struct flashctx *flash, uint8_t val, 45 | chipaddr addr); 46 | static uint8_t drkaiser_chip_readb(const struct flashctx *flash, 47 | const chipaddr addr); 48 | static const struct par_master par_master_drkaiser = { 49 | .chip_readb = drkaiser_chip_readb, 50 | .chip_readw = fallback_chip_readw, 51 | .chip_readl = fallback_chip_readl, 52 | .chip_readn = fallback_chip_readn, 53 | .chip_writeb = drkaiser_chip_writeb, 54 | .chip_writew = fallback_chip_writew, 55 | .chip_writel = fallback_chip_writel, 56 | .chip_writen = fallback_chip_writen, 57 | }; 58 | 59 | int drkaiser_init(void) 60 | { 61 | struct pci_dev *dev = NULL; 62 | uint32_t addr; 63 | 64 | if (rget_io_perms()) 65 | return 1; 66 | 67 | dev = pcidev_init(drkaiser_pcidev, PCI_BASE_ADDRESS_2); 68 | if (!dev) 69 | return 1; 70 | 71 | addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_2); 72 | if (!addr) 73 | return 1; 74 | 75 | /* Write magic register to enable flash write. */ 76 | rpci_write_word(dev, PCI_MAGIC_DRKAISER_ADDR, PCI_MAGIC_DRKAISER_VALUE); 77 | 78 | /* Map 128kB flash memory window. */ 79 | drkaiser_bar = rphysmap("Dr. Kaiser PC-Waechter flash memory", addr, DRKAISER_MEMMAP_SIZE); 80 | if (drkaiser_bar == ERROR_PTR) 81 | return 1; 82 | 83 | max_rom_decode.parallel = 128 * 1024; 84 | register_par_master(&par_master_drkaiser, BUS_PARALLEL); 85 | 86 | return 0; 87 | } 88 | 89 | static void drkaiser_chip_writeb(const struct flashctx *flash, uint8_t val, 90 | chipaddr addr) 91 | { 92 | pci_mmio_writeb(val, drkaiser_bar + (addr & DRKAISER_MEMMAP_MASK)); 93 | } 94 | 95 | static uint8_t drkaiser_chip_readb(const struct flashctx *flash, 96 | const chipaddr addr) 97 | { 98 | return pci_mmio_readb(drkaiser_bar + (addr & DRKAISER_MEMMAP_MASK)); 99 | } 100 | -------------------------------------------------------------------------------- /util/z60_flashrom.rules: -------------------------------------------------------------------------------- 1 | ## 2 | ## This file is part of the flashrom project. 3 | ## 4 | ## Copyright (C) 2010 Uwe Hermann 5 | ## 6 | ## This program is free software; you can redistribute it and/or modify 7 | ## it under the terms of the GNU General Public License as published by 8 | ## the Free Software Foundation; either version 2 of the License, or 9 | ## (at your option) any later version. 10 | ## 11 | ## This program is distributed in the hope that it will be useful, 12 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ## GNU General Public License for more details. 15 | ## 16 | ## You should have received a copy of the GNU General Public License 17 | ## along with this program; if not, write to the Free Software 18 | ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | ## 20 | 21 | ## 22 | ## Please keep this list sorted alphabetically by vendor/device name. 23 | ## 24 | 25 | ## 26 | ## This is tested on udev version 154, other versions may need small fixes. 27 | ## 28 | ## Note that you might want to change the "plugdev" group to whatever is 29 | ## suitable for your respective distribution. 30 | ## 31 | 32 | ACTION!="add|change", GOTO="flashrom_rules_end" 33 | SUBSYSTEM!="usb|usb_device", GOTO="flashrom_rules_end" 34 | 35 | # Amontec JTAGkey(2) 36 | # http://www.amontec.com/jtagkey.shtml 37 | ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="664", GROUP="plugdev" 38 | 39 | # Buspirate 40 | # http://dangerousprototypes.com/2009/10/08/bus-pirate-raw-spi-mode/ 41 | ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="664", GROUP="plugdev" 42 | 43 | # Dediprog SF100 44 | # http://www.dediprog.com/SPI-flash-in-circuit-programming/SF100 45 | ATTRS{idVendor}=="0483", ATTRS{idProduct}=="dada", MODE="664", GROUP="plugdev" 46 | 47 | # DLP Design DLP-USB1232H 48 | # http://www.dlpdesign.com/usb/usb1232h.shtml 49 | ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="664", GROUP="plugdev" 50 | 51 | # FIC OpenMoko Neo1973 Debug board (V2+) 52 | # http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v2 53 | ATTRS{idVendor}=="1457", ATTRS{idProduct}=="5118", MODE="664", GROUP="plugdev" 54 | 55 | # FTDI FT4232H Mini-Module 56 | # http://www.ftdichip.com/Products/EvaluationKits/FT4232H_MiniModule.htm 57 | ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", MODE="664", GROUP="plugdev" 58 | 59 | # GOEPEL PicoTAP 60 | # http://www.goepel.com/jtagboundary-scan/hardware/picotap.html 61 | ATTRS{idVendor}=="096c", ATTRS{idProduct}=="1449", MODE="664", GROUP="plugdev" 62 | 63 | # Olimex ARM-USB-OCD 64 | # http://olimex.com/dev/arm-usb-ocd.html 65 | ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0003", MODE="664", GROUP="plugdev" 66 | 67 | # Olimex ARM-USB-OCD-H 68 | # http://olimex.com/dev/arm-usb-ocd-h.html 69 | ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002b", MODE="664", GROUP="plugdev" 70 | 71 | # Olimex ARM-USB-TINY 72 | # http://olimex.com/dev/arm-usb-tiny.html 73 | ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0004", MODE="664", GROUP="plugdev" 74 | 75 | # Olimex ARM-USB-TINY-H 76 | # http://olimex.com/dev/arm-usb-tiny-h.html 77 | ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002a", MODE="664", GROUP="plugdev" 78 | 79 | # TIAO/DIYGADGET USB Multi-Protocol Adapter (TUMPA) 80 | # http://www.diygadget.com/tiao-usb-multi-protocol-adapter-jtag-spi-i2c-serial.html 81 | ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a98", MODE="664", GROUP="plugdev" 82 | 83 | # TIAO/DIYGADGET USB Multi-Protocol Adapter (TUMPA) Lite 84 | # http://www.tiaowiki.com/w/TIAO_USB_Multi_Protocol_Adapter_Lite_User's_Manual 85 | ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a99", MODE="664", GROUP="plugdev" 86 | 87 | LABEL="flashrom_rules_end" 88 | -------------------------------------------------------------------------------- /sst28sf040.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2000 Silicon Integrated System Corporation 5 | * Copyright (C) 2005 coresystems GmbH 6 | * Copyright (C) 2009 Sean Nelson 7 | * 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. 12 | * 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. 17 | * 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 21 | */ 22 | 23 | #include "flash.h" 24 | #include "chipdrivers.h" 25 | 26 | #define AUTO_PG_ERASE1 0x20 27 | #define AUTO_PG_ERASE2 0xD0 28 | #define AUTO_PGRM 0x10 29 | #define CHIP_ERASE 0x30 30 | #define RESET 0xFF 31 | #define READ_ID 0x90 32 | 33 | int protect_28sf040(struct flashctx *flash) 34 | { 35 | chipaddr bios = flash->virtual_memory; 36 | 37 | chip_readb(flash, bios + 0x1823); 38 | chip_readb(flash, bios + 0x1820); 39 | chip_readb(flash, bios + 0x1822); 40 | chip_readb(flash, bios + 0x0418); 41 | chip_readb(flash, bios + 0x041B); 42 | chip_readb(flash, bios + 0x0419); 43 | chip_readb(flash, bios + 0x040A); 44 | 45 | return 0; 46 | } 47 | 48 | int unprotect_28sf040(struct flashctx *flash) 49 | { 50 | chipaddr bios = flash->virtual_memory; 51 | 52 | chip_readb(flash, bios + 0x1823); 53 | chip_readb(flash, bios + 0x1820); 54 | chip_readb(flash, bios + 0x1822); 55 | chip_readb(flash, bios + 0x0418); 56 | chip_readb(flash, bios + 0x041B); 57 | chip_readb(flash, bios + 0x0419); 58 | chip_readb(flash, bios + 0x041A); 59 | 60 | return 0; 61 | } 62 | 63 | int erase_sector_28sf040(struct flashctx *flash, unsigned int address, 64 | unsigned int sector_size) 65 | { 66 | chipaddr bios = flash->virtual_memory; 67 | 68 | /* This command sequence is very similar to erase_block_82802ab. */ 69 | chip_writeb(flash, AUTO_PG_ERASE1, bios); 70 | chip_writeb(flash, AUTO_PG_ERASE2, bios + address); 71 | 72 | /* wait for Toggle bit ready */ 73 | toggle_ready_jedec(flash, bios); 74 | 75 | /* FIXME: Check the status register for errors. */ 76 | return 0; 77 | } 78 | 79 | /* chunksize is 1 */ 80 | int write_28sf040(struct flashctx *flash, const uint8_t *src, unsigned int start, unsigned int len) 81 | { 82 | int i; 83 | chipaddr bios = flash->virtual_memory; 84 | chipaddr dst = flash->virtual_memory + start; 85 | 86 | for (i = 0; i < len; i++) { 87 | /* transfer data from source to destination */ 88 | if (*src == 0xFF) { 89 | dst++, src++; 90 | /* If the data is 0xFF, don't program it */ 91 | continue; 92 | } 93 | /*issue AUTO PROGRAM command */ 94 | chip_writeb(flash, AUTO_PGRM, dst); 95 | chip_writeb(flash, *src++, dst++); 96 | 97 | /* wait for Toggle bit ready */ 98 | toggle_ready_jedec(flash, bios); 99 | } 100 | 101 | return 0; 102 | } 103 | 104 | static int erase_28sf040(struct flashctx *flash) 105 | { 106 | chipaddr bios = flash->virtual_memory; 107 | 108 | chip_writeb(flash, CHIP_ERASE, bios); 109 | chip_writeb(flash, CHIP_ERASE, bios); 110 | 111 | programmer_delay(10); 112 | toggle_ready_jedec(flash, bios); 113 | 114 | /* FIXME: Check the status register for errors. */ 115 | return 0; 116 | } 117 | 118 | int erase_chip_28sf040(struct flashctx *flash, unsigned int addr, 119 | unsigned int blocklen) 120 | { 121 | if ((addr != 0) || (blocklen != flash->chip->total_size * 1024)) { 122 | msg_cerr("%s called with incorrect arguments\n", 123 | __func__); 124 | return -1; 125 | } 126 | return erase_28sf040(flash); 127 | } 128 | -------------------------------------------------------------------------------- /amd_imc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2013 Rudolf Marek 5 | * Copyright (C) 2013 Stefan Tauner 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #if defined(__i386__) || defined(__x86_64__) 23 | 24 | #include "flash.h" 25 | #include "programmer.h" 26 | #include "hwaccess.h" 27 | #include "spi.h" 28 | 29 | /* same as serverengines */ 30 | static void enter_conf_mode_ec(uint16_t port) 31 | { 32 | OUTB(0x5a, port); 33 | } 34 | 35 | static void exit_conf_mode_ec(uint16_t port) 36 | { 37 | OUTB(0xa5, port); 38 | } 39 | 40 | static uint16_t get_sio_port(struct pci_dev *dev) 41 | { 42 | uint16_t ec_port; 43 | 44 | if (!dev) { 45 | return 0; 46 | } 47 | 48 | ec_port = pci_read_word(dev, 0xa4); 49 | 50 | /* EcPortActive? */ 51 | if (!(ec_port & 0x1)) 52 | return 0; 53 | 54 | ec_port &= ~0x1; 55 | 56 | return ec_port; 57 | } 58 | 59 | /* Wait for up to 10 ms for a response. */ 60 | static int mbox_wait_ack(uint16_t mbox_port) 61 | { 62 | int i = 10; 63 | while (sio_read(mbox_port, 0x82) != 0xfa) { 64 | if (--i == 0) { 65 | msg_pwarn("IMC MBOX: Timeout!\n"); 66 | return 1; 67 | } 68 | programmer_delay(1000); 69 | } 70 | return 0; 71 | } 72 | 73 | static uint16_t mbox_get_port(uint16_t sio_port) 74 | { 75 | uint16_t mbox_port; 76 | 77 | enter_conf_mode_ec(sio_port); 78 | 79 | /* Go to LDN 9, mailbox */ 80 | sio_write(sio_port, 7, 9); 81 | 82 | /* MBOX inactive? */ 83 | if ((sio_read(sio_port, 0x30) & 1) == 0) { 84 | exit_conf_mode_ec(sio_port); 85 | return 0; 86 | } 87 | 88 | mbox_port = sio_read(sio_port, 0x60) << 8; 89 | mbox_port |= sio_read(sio_port, 0x61); 90 | 91 | exit_conf_mode_ec(sio_port); 92 | return mbox_port; 93 | } 94 | 95 | /* Returns negative values when IMC is inactive, positive values on errors */ 96 | static int imc_send_cmd(struct pci_dev *dev, uint8_t cmd) 97 | { 98 | uint16_t sio_port; 99 | uint16_t mbox_port; 100 | 101 | /* IntegratedEcPresent? */ 102 | if (!(pci_read_byte(dev, 0x40) & (1 << 7))) 103 | return -1; 104 | 105 | sio_port = get_sio_port(dev); 106 | if (!sio_port) 107 | return -1; 108 | 109 | msg_pdbg2("IMC SIO is at 0x%x.\n", sio_port); 110 | mbox_port = mbox_get_port(sio_port); 111 | if (!mbox_port) 112 | return -1; 113 | msg_pdbg2("IMC MBOX is at 0x%x.\n", mbox_port); 114 | 115 | sio_write(mbox_port, 0x82, 0x0); 116 | sio_write(mbox_port, 0x83, cmd); 117 | sio_write(mbox_port, 0x84, 0x0); 118 | /* trigger transfer 0x96 with subcommand cmd */ 119 | sio_write(mbox_port, 0x80, 0x96); 120 | 121 | return mbox_wait_ack(mbox_port); 122 | } 123 | 124 | static int imc_resume(void *data) 125 | { 126 | struct pci_dev *dev = data; 127 | int ret = imc_send_cmd(dev, 0xb5); 128 | 129 | if (ret != 0) 130 | msg_pinfo("Resuming IMC failed)\n"); 131 | else 132 | msg_pdbg2("IMC resumed.\n"); 133 | return ret; 134 | } 135 | 136 | int amd_imc_shutdown(struct pci_dev *dev) 137 | { 138 | /* Try to put IMC to sleep */ 139 | int ret = imc_send_cmd(dev, 0xb4); 140 | 141 | /* No IMC activity detectable, assume we are fine */ 142 | if (ret < 0) { 143 | msg_pdbg2("No IMC found.\n"); 144 | return 0; 145 | } 146 | 147 | if (ret != 0) { 148 | msg_perr("Shutting down IMC failed.\n"); 149 | return ret; 150 | } 151 | msg_pdbg2("Shutting down IMC successful.\n"); 152 | 153 | if (register_shutdown(imc_resume, dev)) 154 | return 1; 155 | 156 | return ret; 157 | } 158 | 159 | #endif 160 | -------------------------------------------------------------------------------- /nicnatsemi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2010 Andrew Morgan 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #if defined(__i386__) || defined(__x86_64__) 22 | 23 | #include 24 | #include "flash.h" 25 | #include "programmer.h" 26 | #include "hwaccess.h" 27 | 28 | #define PCI_VENDOR_ID_NATSEMI 0x100b 29 | 30 | #define BOOT_ROM_ADDR 0x50 31 | #define BOOT_ROM_DATA 0x54 32 | 33 | static uint32_t io_base_addr = 0; 34 | const struct dev_entry nics_natsemi[] = { 35 | {0x100b, 0x0020, NT, "National Semiconductor", "DP83815/DP83816"}, 36 | {0x100b, 0x0022, NT, "National Semiconductor", "DP83820"}, 37 | 38 | {0}, 39 | }; 40 | 41 | static void nicnatsemi_chip_writeb(const struct flashctx *flash, uint8_t val, 42 | chipaddr addr); 43 | static uint8_t nicnatsemi_chip_readb(const struct flashctx *flash, 44 | const chipaddr addr); 45 | static const struct par_master par_master_nicnatsemi = { 46 | .chip_readb = nicnatsemi_chip_readb, 47 | .chip_readw = fallback_chip_readw, 48 | .chip_readl = fallback_chip_readl, 49 | .chip_readn = fallback_chip_readn, 50 | .chip_writeb = nicnatsemi_chip_writeb, 51 | .chip_writew = fallback_chip_writew, 52 | .chip_writel = fallback_chip_writel, 53 | .chip_writen = fallback_chip_writen, 54 | }; 55 | 56 | int nicnatsemi_init(void) 57 | { 58 | struct pci_dev *dev = NULL; 59 | 60 | if (rget_io_perms()) 61 | return 1; 62 | 63 | dev = pcidev_init(nics_natsemi, PCI_BASE_ADDRESS_0); 64 | if (!dev) 65 | return 1; 66 | 67 | io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); 68 | if (!io_base_addr) 69 | return 1; 70 | 71 | /* The datasheet shows address lines MA0-MA16 in one place and MA0-MA15 72 | * in another. My NIC has MA16 connected to A16 on the boot ROM socket 73 | * so I'm assuming it is accessible. If not then next line wants to be 74 | * max_rom_decode.parallel = 65536; and the mask in the read/write 75 | * functions below wants to be 0x0000FFFF. 76 | */ 77 | max_rom_decode.parallel = 131072; 78 | register_par_master(&par_master_nicnatsemi, BUS_PARALLEL); 79 | 80 | return 0; 81 | } 82 | 83 | static void nicnatsemi_chip_writeb(const struct flashctx *flash, uint8_t val, 84 | chipaddr addr) 85 | { 86 | OUTL((uint32_t)addr & 0x0001FFFF, io_base_addr + BOOT_ROM_ADDR); 87 | /* 88 | * The datasheet requires 32 bit accesses to this register, but it seems 89 | * that requirement might only apply if the register is memory mapped. 90 | * Bits 8-31 of this register are apparently don't care, and if this 91 | * register is I/O port mapped, 8 bit accesses to the lowest byte of the 92 | * register seem to work fine. Due to that, we ignore the advice in the 93 | * data sheet. 94 | */ 95 | OUTB(val, io_base_addr + BOOT_ROM_DATA); 96 | } 97 | 98 | static uint8_t nicnatsemi_chip_readb(const struct flashctx *flash, 99 | const chipaddr addr) 100 | { 101 | OUTL(((uint32_t)addr & 0x0001FFFF), io_base_addr + BOOT_ROM_ADDR); 102 | /* 103 | * The datasheet requires 32 bit accesses to this register, but it seems 104 | * that requirement might only apply if the register is memory mapped. 105 | * Bits 8-31 of this register are apparently don't care, and if this 106 | * register is I/O port mapped, 8 bit accesses to the lowest byte of the 107 | * register seem to work fine. Due to that, we ignore the advice in the 108 | * data sheet. 109 | */ 110 | return INB(io_base_addr + BOOT_ROM_DATA); 111 | } 112 | 113 | #else 114 | #error PCI port I/O access is not supported on this architecture yet. 115 | #endif 116 | -------------------------------------------------------------------------------- /nicintel.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2011 Carl-Daniel Hailfinger 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | /* Datasheet: http://download.intel.com/design/network/datashts/82559_Fast_Ethernet_Multifunction_PCI_Cardbus_Controller_Datasheet.pdf */ 21 | 22 | #include 23 | #include "flash.h" 24 | #include "programmer.h" 25 | #include "hwaccess.h" 26 | 27 | uint8_t *nicintel_bar; 28 | uint8_t *nicintel_control_bar; 29 | 30 | const struct dev_entry nics_intel[] = { 31 | {PCI_VENDOR_ID_INTEL, 0x1209, NT, "Intel", "8255xER/82551IT Fast Ethernet Controller"}, 32 | {PCI_VENDOR_ID_INTEL, 0x1229, OK, "Intel", "82557/8/9/0/1 Ethernet Pro 100"}, 33 | 34 | {0}, 35 | }; 36 | 37 | /* Arbitrary limit, taken from the datasheet I just had lying around. 38 | * 128 kByte on the 82559 device. Or not. Depends on whom you ask. 39 | */ 40 | #define NICINTEL_MEMMAP_SIZE (128 * 1024) 41 | #define NICINTEL_MEMMAP_MASK (NICINTEL_MEMMAP_SIZE - 1) 42 | 43 | #define NICINTEL_CONTROL_MEMMAP_SIZE 0x10 44 | 45 | #define CSR_FCR 0x0c 46 | 47 | static void nicintel_chip_writeb(const struct flashctx *flash, uint8_t val, 48 | chipaddr addr); 49 | static uint8_t nicintel_chip_readb(const struct flashctx *flash, 50 | const chipaddr addr); 51 | static const struct par_master par_master_nicintel = { 52 | .chip_readb = nicintel_chip_readb, 53 | .chip_readw = fallback_chip_readw, 54 | .chip_readl = fallback_chip_readl, 55 | .chip_readn = fallback_chip_readn, 56 | .chip_writeb = nicintel_chip_writeb, 57 | .chip_writew = fallback_chip_writew, 58 | .chip_writel = fallback_chip_writel, 59 | .chip_writen = fallback_chip_writen, 60 | }; 61 | 62 | int nicintel_init(void) 63 | { 64 | struct pci_dev *dev = NULL; 65 | uintptr_t addr; 66 | 67 | /* Needed only for PCI accesses on some platforms. 68 | * FIXME: Refactor that into get_mem_perms/rget_io_perms/get_pci_perms? 69 | */ 70 | if (rget_io_perms()) 71 | return 1; 72 | 73 | /* FIXME: BAR2 is not available if the device uses the CardBus function. */ 74 | dev = pcidev_init(nics_intel, PCI_BASE_ADDRESS_2); 75 | if (!dev) 76 | return 1; 77 | 78 | addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_2); 79 | if (!addr) 80 | return 1; 81 | 82 | nicintel_bar = rphysmap("Intel NIC flash", addr, NICINTEL_MEMMAP_SIZE); 83 | if (nicintel_bar == ERROR_PTR) 84 | return 1; 85 | 86 | addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); 87 | if (!addr) 88 | return 1; 89 | 90 | nicintel_control_bar = rphysmap("Intel NIC control/status reg", addr, NICINTEL_CONTROL_MEMMAP_SIZE); 91 | if (nicintel_control_bar == ERROR_PTR) 92 | return 1; 93 | 94 | /* FIXME: This register is pretty undocumented in all publicly available 95 | * documentation from Intel. Let me quote the complete info we have: 96 | * "Flash Control Register: The Flash Control register allows the CPU to 97 | * enable writes to an external Flash. The Flash Control Register is a 98 | * 32-bit field that allows access to an external Flash device." 99 | * Ah yes, we also know where it is, but we have absolutely _no_ idea 100 | * what we should do with it. Write 0x0001 because we have nothing 101 | * better to do with our time. 102 | */ 103 | pci_rmmio_writew(0x0001, nicintel_control_bar + CSR_FCR); 104 | 105 | max_rom_decode.parallel = NICINTEL_MEMMAP_SIZE; 106 | register_par_master(&par_master_nicintel, BUS_PARALLEL); 107 | 108 | return 0; 109 | } 110 | 111 | static void nicintel_chip_writeb(const struct flashctx *flash, uint8_t val, 112 | chipaddr addr) 113 | { 114 | pci_mmio_writeb(val, nicintel_bar + (addr & NICINTEL_MEMMAP_MASK)); 115 | } 116 | 117 | static uint8_t nicintel_chip_readb(const struct flashctx *flash, 118 | const chipaddr addr) 119 | { 120 | return pci_mmio_readb(nicintel_bar + (addr & NICINTEL_MEMMAP_MASK)); 121 | } 122 | -------------------------------------------------------------------------------- /nicrealtek.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2009 Joerg Fischer 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #if defined(__i386__) || defined(__x86_64__) 22 | 23 | #include 24 | #include "flash.h" 25 | #include "programmer.h" 26 | #include "hwaccess.h" 27 | 28 | #define PCI_VENDOR_ID_REALTEK 0x10ec 29 | #define PCI_VENDOR_ID_SMC1211 0x1113 30 | 31 | static uint32_t io_base_addr = 0; 32 | static int bios_rom_addr, bios_rom_data; 33 | 34 | const struct dev_entry nics_realtek[] = { 35 | {0x10ec, 0x8139, OK, "Realtek", "RTL8139/8139C/8139C+"}, 36 | {0x10ec, 0x8169, NT, "Realtek", "RTL8169"}, 37 | {0x1113, 0x1211, OK, "SMC", "1211TX"}, /* RTL8139 clone */ 38 | 39 | {0}, 40 | }; 41 | 42 | static void nicrealtek_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr); 43 | static uint8_t nicrealtek_chip_readb(const struct flashctx *flash, const chipaddr addr); 44 | static const struct par_master par_master_nicrealtek = { 45 | .chip_readb = nicrealtek_chip_readb, 46 | .chip_readw = fallback_chip_readw, 47 | .chip_readl = fallback_chip_readl, 48 | .chip_readn = fallback_chip_readn, 49 | .chip_writeb = nicrealtek_chip_writeb, 50 | .chip_writew = fallback_chip_writew, 51 | .chip_writel = fallback_chip_writel, 52 | .chip_writen = fallback_chip_writen, 53 | }; 54 | 55 | static int nicrealtek_shutdown(void *data) 56 | { 57 | /* FIXME: We forgot to disable software access again. */ 58 | return 0; 59 | } 60 | 61 | int nicrealtek_init(void) 62 | { 63 | struct pci_dev *dev = NULL; 64 | 65 | if (rget_io_perms()) 66 | return 1; 67 | 68 | dev = pcidev_init(nics_realtek, PCI_BASE_ADDRESS_0); 69 | if (!dev) 70 | return 1; 71 | 72 | io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); 73 | if (!io_base_addr) 74 | return 1; 75 | 76 | /* Beware, this ignores the vendor ID! */ 77 | switch (dev->device_id) { 78 | case 0x8139: /* RTL8139 */ 79 | case 0x1211: /* SMC 1211TX */ 80 | default: 81 | bios_rom_addr = 0xD4; 82 | bios_rom_data = 0xD7; 83 | break; 84 | case 0x8169: /* RTL8169 */ 85 | bios_rom_addr = 0x30; 86 | bios_rom_data = 0x33; 87 | break; 88 | } 89 | 90 | if (register_shutdown(nicrealtek_shutdown, NULL)) 91 | return 1; 92 | 93 | register_par_master(&par_master_nicrealtek, BUS_PARALLEL); 94 | 95 | return 0; 96 | } 97 | 98 | static void nicrealtek_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr) 99 | { 100 | /* Output addr and data, set WE to 0, set OE to 1, set CS to 0, 101 | * enable software access. 102 | */ 103 | OUTL(((uint32_t)addr & 0x01FFFF) | 0x0A0000 | (val << 24), 104 | io_base_addr + bios_rom_addr); 105 | /* Output addr and data, set WE to 1, set OE to 1, set CS to 1, 106 | * enable software access. 107 | */ 108 | OUTL(((uint32_t)addr & 0x01FFFF) | 0x1E0000 | (val << 24), 109 | io_base_addr + bios_rom_addr); 110 | } 111 | 112 | static uint8_t nicrealtek_chip_readb(const struct flashctx *flash, const chipaddr addr) 113 | { 114 | uint8_t val; 115 | 116 | /* FIXME: Can we skip reading the old data and simply use 0? */ 117 | /* Read old data. */ 118 | val = INB(io_base_addr + bios_rom_data); 119 | /* Output new addr and old data, set WE to 1, set OE to 0, set CS to 0, 120 | * enable software access. 121 | */ 122 | OUTL(((uint32_t)addr & 0x01FFFF) | 0x060000 | (val << 24), 123 | io_base_addr + bios_rom_addr); 124 | 125 | /* Read new data. */ 126 | val = INB(io_base_addr + bios_rom_data); 127 | /* Output addr and new data, set WE to 1, set OE to 1, set CS to 1, 128 | * enable software access. 129 | */ 130 | OUTL(((uint32_t)addr & 0x01FFFF) | 0x1E0000 | (val << 24), 131 | io_base_addr + bios_rom_addr); 132 | 133 | return val; 134 | } 135 | 136 | #else 137 | #error PCI port I/O access is not supported on this architecture yet. 138 | #endif 139 | -------------------------------------------------------------------------------- /gfxnvidia.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2009 Uwe Hermann 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include 22 | #include 23 | #include "flash.h" 24 | #include "programmer.h" 25 | #include "hwaccess.h" 26 | 27 | #define PCI_VENDOR_ID_NVIDIA 0x10de 28 | 29 | /* Mask to restrict flash accesses to a 128kB memory window. 30 | * FIXME: Is this size a one-fits-all or card dependent? 31 | */ 32 | #define GFXNVIDIA_MEMMAP_MASK ((1 << 17) - 1) 33 | #define GFXNVIDIA_MEMMAP_SIZE (16 * 1024 * 1024) 34 | 35 | uint8_t *nvidia_bar; 36 | 37 | const struct dev_entry gfx_nvidia[] = { 38 | {0x10de, 0x0010, NT, "NVIDIA", "Mutara V08 [NV2]" }, 39 | {0x10de, 0x0018, NT, "NVIDIA", "RIVA 128" }, 40 | {0x10de, 0x0020, NT, "NVIDIA", "RIVA TNT" }, 41 | {0x10de, 0x0028, NT, "NVIDIA", "RIVA TNT2/TNT2 Pro" }, 42 | {0x10de, 0x0029, NT, "NVIDIA", "RIVA TNT2 Ultra" }, 43 | {0x10de, 0x002c, NT, "NVIDIA", "Vanta/Vanta LT" }, 44 | {0x10de, 0x002d, OK, "NVIDIA", "RIVA TNT2 Model 64/Model 64 Pro" }, 45 | {0x10de, 0x00a0, NT, "NVIDIA", "Aladdin TNT2" }, 46 | {0x10de, 0x0100, NT, "NVIDIA", "GeForce 256" }, 47 | {0x10de, 0x0101, NT, "NVIDIA", "GeForce DDR" }, 48 | {0x10de, 0x0103, NT, "NVIDIA", "Quadro" }, 49 | {0x10de, 0x0110, NT, "NVIDIA", "GeForce2 MX" }, 50 | {0x10de, 0x0111, NT, "NVIDIA", "GeForce2 MX" }, 51 | {0x10de, 0x0112, NT, "NVIDIA", "GeForce2 GO" }, 52 | {0x10de, 0x0113, NT, "NVIDIA", "Quadro2 MXR" }, 53 | {0x10de, 0x0150, NT, "NVIDIA", "GeForce2 GTS/Pro" }, 54 | {0x10de, 0x0151, NT, "NVIDIA", "GeForce2 GTS" }, 55 | {0x10de, 0x0152, NT, "NVIDIA", "GeForce2 Ultra" }, 56 | {0x10de, 0x0153, NT, "NVIDIA", "Quadro2 Pro" }, 57 | {0x10de, 0x0200, NT, "NVIDIA", "GeForce 3 nFX" }, 58 | {0x10de, 0x0201, NT, "NVIDIA", "GeForce 3 nFX" }, 59 | {0x10de, 0x0202, NT, "NVIDIA", "GeForce 3 nFX Ultra" }, 60 | {0x10de, 0x0203, NT, "NVIDIA", "Quadro 3 DDC" }, 61 | 62 | {0}, 63 | }; 64 | 65 | static void gfxnvidia_chip_writeb(const struct flashctx *flash, uint8_t val, 66 | chipaddr addr); 67 | static uint8_t gfxnvidia_chip_readb(const struct flashctx *flash, 68 | const chipaddr addr); 69 | static const struct par_master par_master_gfxnvidia = { 70 | .chip_readb = gfxnvidia_chip_readb, 71 | .chip_readw = fallback_chip_readw, 72 | .chip_readl = fallback_chip_readl, 73 | .chip_readn = fallback_chip_readn, 74 | .chip_writeb = gfxnvidia_chip_writeb, 75 | .chip_writew = fallback_chip_writew, 76 | .chip_writel = fallback_chip_writel, 77 | .chip_writen = fallback_chip_writen, 78 | }; 79 | 80 | int gfxnvidia_init(void) 81 | { 82 | struct pci_dev *dev = NULL; 83 | uint32_t reg32; 84 | 85 | if (rget_io_perms()) 86 | return 1; 87 | 88 | dev = pcidev_init(gfx_nvidia, PCI_BASE_ADDRESS_0); 89 | if (!dev) 90 | return 1; 91 | 92 | uint32_t io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); 93 | if (!io_base_addr) 94 | return 1; 95 | 96 | io_base_addr += 0x300000; 97 | msg_pinfo("Detected NVIDIA I/O base address: 0x%x.\n", io_base_addr); 98 | 99 | nvidia_bar = rphysmap("NVIDIA", io_base_addr, GFXNVIDIA_MEMMAP_SIZE); 100 | if (nvidia_bar == ERROR_PTR) 101 | return 1; 102 | 103 | /* Allow access to flash interface (will disable screen). */ 104 | reg32 = pci_read_long(dev, 0x50); 105 | reg32 &= ~(1 << 0); 106 | rpci_write_long(dev, 0x50, reg32); 107 | 108 | /* Write/erase doesn't work. */ 109 | programmer_may_write = 0; 110 | register_par_master(&par_master_gfxnvidia, BUS_PARALLEL); 111 | 112 | return 0; 113 | } 114 | 115 | static void gfxnvidia_chip_writeb(const struct flashctx *flash, uint8_t val, 116 | chipaddr addr) 117 | { 118 | pci_mmio_writeb(val, nvidia_bar + (addr & GFXNVIDIA_MEMMAP_MASK)); 119 | } 120 | 121 | static uint8_t gfxnvidia_chip_readb(const struct flashctx *flash, 122 | const chipaddr addr) 123 | { 124 | return pci_mmio_readb(nvidia_bar + (addr & GFXNVIDIA_MEMMAP_MASK)); 125 | } 126 | -------------------------------------------------------------------------------- /ogp_spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2010 Mark Marshall 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include "flash.h" 24 | #include "programmer.h" 25 | #include "hwaccess.h" 26 | 27 | #define PCI_VENDOR_ID_OGP 0x1227 28 | 29 | /* These are the register addresses for the OGD1 / OGA1. If they are 30 | * different for later versions of the hardware then we will need 31 | * logic to select between the different hardware versions. */ 32 | #define OGA1_XP10_BPROM_SI 0x0040 /* W */ 33 | #define OGA1_XP10_BPROM_SO 0x0040 /* R */ 34 | #define OGA1_XP10_BPROM_CE_BAR 0x0044 /* W */ 35 | #define OGA1_XP10_BPROM_SCK 0x0048 /* W */ 36 | #define OGA1_XP10_BPROM_REG_SEL 0x004C /* W */ 37 | #define OGA1_XP10_CPROM_SI 0x0050 /* W */ 38 | #define OGA1_XP10_CPROM_SO 0x0050 /* R */ 39 | #define OGA1_XP10_CPROM_CE_BAR 0x0054 /* W */ 40 | #define OGA1_XP10_CPROM_SCK 0x0058 /* W */ 41 | #define OGA1_XP10_CPROM_REG_SEL 0x005C /* W */ 42 | 43 | static uint8_t *ogp_spibar; 44 | 45 | static uint32_t ogp_reg_sel; 46 | static uint32_t ogp_reg_siso; 47 | static uint32_t ogp_reg__ce; 48 | static uint32_t ogp_reg_sck; 49 | 50 | const struct dev_entry ogp_spi[] = { 51 | {PCI_VENDOR_ID_OGP, 0x0000, OK, "Open Graphics Project", "Development Board OGD1"}, 52 | 53 | {0}, 54 | }; 55 | 56 | static void ogp_request_spibus(void) 57 | { 58 | pci_mmio_writel(1, ogp_spibar + ogp_reg_sel); 59 | } 60 | 61 | static void ogp_release_spibus(void) 62 | { 63 | pci_mmio_writel(0, ogp_spibar + ogp_reg_sel); 64 | } 65 | 66 | static void ogp_bitbang_set_cs(int val) 67 | { 68 | pci_mmio_writel(val, ogp_spibar + ogp_reg__ce); 69 | } 70 | 71 | static void ogp_bitbang_set_sck(int val) 72 | { 73 | pci_mmio_writel(val, ogp_spibar + ogp_reg_sck); 74 | } 75 | 76 | static void ogp_bitbang_set_mosi(int val) 77 | { 78 | pci_mmio_writel(val, ogp_spibar + ogp_reg_siso); 79 | } 80 | 81 | static int ogp_bitbang_get_miso(void) 82 | { 83 | uint32_t tmp; 84 | 85 | tmp = pci_mmio_readl(ogp_spibar + ogp_reg_siso); 86 | return tmp & 0x1; 87 | } 88 | 89 | static const struct bitbang_spi_master bitbang_spi_master_ogp = { 90 | .type = BITBANG_SPI_MASTER_OGP, 91 | .set_cs = ogp_bitbang_set_cs, 92 | .set_sck = ogp_bitbang_set_sck, 93 | .set_mosi = ogp_bitbang_set_mosi, 94 | .get_miso = ogp_bitbang_get_miso, 95 | .request_bus = ogp_request_spibus, 96 | .release_bus = ogp_release_spibus, 97 | .half_period = 0, 98 | }; 99 | 100 | int ogp_spi_init(void) 101 | { 102 | struct pci_dev *dev = NULL; 103 | char *type; 104 | 105 | type = extract_programmer_param("rom"); 106 | 107 | if (!type) { 108 | msg_perr("Please use flashrom -p ogp_spi:rom=... to specify " 109 | "which flashchip you want to access.\n"); 110 | return 1; 111 | } else if (!strcasecmp(type, "bprom") || !strcasecmp(type, "bios")) { 112 | ogp_reg_sel = OGA1_XP10_BPROM_REG_SEL; 113 | ogp_reg_siso = OGA1_XP10_BPROM_SI; 114 | ogp_reg__ce = OGA1_XP10_BPROM_CE_BAR; 115 | ogp_reg_sck = OGA1_XP10_BPROM_SCK; 116 | } else if (!strcasecmp(type, "cprom") || !strcasecmp(type, "s3")) { 117 | ogp_reg_sel = OGA1_XP10_CPROM_REG_SEL; 118 | ogp_reg_siso = OGA1_XP10_CPROM_SI; 119 | ogp_reg__ce = OGA1_XP10_CPROM_CE_BAR; 120 | ogp_reg_sck = OGA1_XP10_CPROM_SCK; 121 | } else { 122 | msg_perr("Invalid or missing rom= parameter.\n"); 123 | free(type); 124 | return 1; 125 | } 126 | free(type); 127 | 128 | if (rget_io_perms()) 129 | return 1; 130 | 131 | dev = pcidev_init(ogp_spi, PCI_BASE_ADDRESS_0); 132 | if (!dev) 133 | return 1; 134 | 135 | uint32_t io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); 136 | if (!io_base_addr) 137 | return 1; 138 | 139 | ogp_spibar = rphysmap("OGP registers", io_base_addr, 4096); 140 | if (ogp_spibar == ERROR_PTR) 141 | return 1; 142 | 143 | if (register_spi_bitbang_master(&bitbang_spi_master_ogp)) 144 | return 1; 145 | 146 | return 0; 147 | } 148 | -------------------------------------------------------------------------------- /cli_common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2009 Uwe Hermann 5 | * Copyright (C) 2009 Carl-Daniel Hailfinger 6 | * Copyright (C) 2011-2014 Stefan Tauner 7 | * 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. 12 | * 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. 17 | * 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 21 | */ 22 | 23 | #include 24 | #include 25 | #include "flash.h" 26 | 27 | /* 28 | * Return a string corresponding to the bustype parameter. 29 | * Memory is obtained with malloc() and must be freed with free() by the caller. 30 | */ 31 | char *flashbuses_to_text(enum chipbustype bustype) 32 | { 33 | char *ret = calloc(1, 1); 34 | /* 35 | * FIXME: Once all chipsets and flash chips have been updated, NONSPI 36 | * will cease to exist and should be eliminated here as well. 37 | */ 38 | if (bustype == BUS_NONSPI) { 39 | ret = strcat_realloc(ret, "Non-SPI, "); 40 | } else { 41 | if (bustype & BUS_PARALLEL) 42 | ret = strcat_realloc(ret, "Parallel, "); 43 | if (bustype & BUS_LPC) 44 | ret = strcat_realloc(ret, "LPC, "); 45 | if (bustype & BUS_FWH) 46 | ret = strcat_realloc(ret, "FWH, "); 47 | if (bustype & BUS_SPI) 48 | ret = strcat_realloc(ret, "SPI, "); 49 | if (bustype & BUS_PROG) 50 | ret = strcat_realloc(ret, "Programmer-specific, "); 51 | if (bustype == BUS_NONE) 52 | ret = strcat_realloc(ret, "None, "); 53 | } 54 | /* Kill last comma. */ 55 | ret[strlen(ret) - 2] = '\0'; 56 | ret = realloc(ret, strlen(ret) + 1); 57 | return ret; 58 | } 59 | 60 | 61 | void print_chip_support_status(const struct flashchip *chip) 62 | { 63 | if (chip->feature_bits & FEATURE_OTP) { 64 | msg_cdbg("This chip may contain one-time programmable memory. flashrom cannot read\n" 65 | "and may never be able to write it, hence it may not be able to completely\n" 66 | "clone the contents of this chip (see man page for details).\n"); 67 | } 68 | 69 | if ((chip->tested.erase == NA) && (chip->tested.write == NA)) { 70 | msg_cdbg("This chip's main memory can not be erased/written by design.\n"); 71 | } 72 | 73 | if ((chip->tested.probe == BAD) || (chip->tested.probe == NT) || 74 | (chip->tested.read == BAD) || (chip->tested.read == NT) || 75 | (chip->tested.erase == BAD) || (chip->tested.erase == NT) || 76 | (chip->tested.write == BAD) || (chip->tested.write == NT)){ 77 | msg_cinfo("===\n"); 78 | if ((chip->tested.probe == BAD) || 79 | (chip->tested.read == BAD) || 80 | (chip->tested.erase == BAD) || 81 | (chip->tested.write == BAD)) { 82 | msg_cinfo("This flash part has status NOT WORKING for operations:"); 83 | if (chip->tested.probe == BAD) 84 | msg_cinfo(" PROBE"); 85 | if (chip->tested.read == BAD) 86 | msg_cinfo(" READ"); 87 | if (chip->tested.erase == BAD) 88 | msg_cinfo(" ERASE"); 89 | if (chip->tested.write == BAD) 90 | msg_cinfo(" WRITE"); 91 | msg_cinfo("\n"); 92 | } 93 | if ((chip->tested.probe == NT) || 94 | (chip->tested.read == NT) || 95 | (chip->tested.erase == NT) || 96 | (chip->tested.write == NT)) { 97 | msg_cinfo("This flash part has status UNTESTED for operations:"); 98 | if (chip->tested.probe == NT) 99 | msg_cinfo(" PROBE"); 100 | if (chip->tested.read == NT) 101 | msg_cinfo(" READ"); 102 | if (chip->tested.erase == NT) 103 | msg_cinfo(" ERASE"); 104 | if (chip->tested.write == NT) 105 | msg_cinfo(" WRITE"); 106 | msg_cinfo("\n"); 107 | } 108 | msg_cinfo("The test status of this chip may have been updated in the latest development\n" 109 | "version of flashrom. If you are running the latest development version,\n" 110 | "please email a report to flashrom@flashrom.org if any of the above operations\n" 111 | "work correctly for you with this flash chip. Please include the flashrom log\n" 112 | "file for all operations you tested (see the man page for details), and mention\n" 113 | "which mainboard or programmer you tested in the subject line.\n" 114 | "Thanks for your help!\n"); 115 | } 116 | } 117 | 118 | -------------------------------------------------------------------------------- /satasii.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2009 Rudolf Marek 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* Datasheets can be found on http://www.siliconimage.com. Great thanks! */ 22 | 23 | #include "programmer.h" 24 | #include "hwaccess.h" 25 | 26 | #define PCI_VENDOR_ID_SII 0x1095 27 | 28 | #define SATASII_MEMMAP_SIZE 0x100 29 | 30 | static uint8_t *sii_bar; 31 | static uint16_t id; 32 | 33 | const struct dev_entry satas_sii[] = { 34 | {0x1095, 0x0680, OK, "Silicon Image", "PCI0680 Ultra ATA-133 Host Ctrl"}, 35 | {0x1095, 0x3112, OK, "Silicon Image", "SiI 3112 [SATALink/SATARaid] SATA Ctrl"}, 36 | {0x1095, 0x3114, OK, "Silicon Image", "SiI 3114 [SATALink/SATARaid] SATA Ctrl"}, 37 | {0x1095, 0x3124, OK, "Silicon Image", "SiI 3124 PCI-X SATA Ctrl"}, 38 | {0x1095, 0x3132, OK, "Silicon Image", "SiI 3132 SATA Raid II Ctrl"}, 39 | {0x1095, 0x3512, OK, "Silicon Image", "SiI 3512 [SATALink/SATARaid] SATA Ctrl"}, 40 | 41 | {0}, 42 | }; 43 | 44 | static void satasii_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr); 45 | static uint8_t satasii_chip_readb(const struct flashctx *flash, const chipaddr addr); 46 | static const struct par_master par_master_satasii = { 47 | .chip_readb = satasii_chip_readb, 48 | .chip_readw = fallback_chip_readw, 49 | .chip_readl = fallback_chip_readl, 50 | .chip_readn = fallback_chip_readn, 51 | .chip_writeb = satasii_chip_writeb, 52 | .chip_writew = fallback_chip_writew, 53 | .chip_writel = fallback_chip_writel, 54 | .chip_writen = fallback_chip_writen, 55 | }; 56 | 57 | static uint32_t satasii_wait_done(void) 58 | { 59 | uint32_t ctrl_reg; 60 | int i = 0; 61 | while ((ctrl_reg = pci_mmio_readl(sii_bar)) & (1 << 25)) { 62 | if (++i > 10000) { 63 | msg_perr("%s: control register stuck at %08x, ignoring.\n", 64 | __func__, pci_mmio_readl(sii_bar)); 65 | break; 66 | } 67 | } 68 | return ctrl_reg; 69 | } 70 | 71 | int satasii_init(void) 72 | { 73 | struct pci_dev *dev = NULL; 74 | uint32_t addr; 75 | uint16_t reg_offset; 76 | 77 | if (rget_io_perms()) 78 | return 1; 79 | 80 | dev = pcidev_init(satas_sii, PCI_BASE_ADDRESS_0); 81 | if (!dev) 82 | return 1; 83 | 84 | id = dev->device_id; 85 | 86 | if ((id == 0x3132) || (id == 0x3124)) { 87 | addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); 88 | if (!addr) 89 | return 1; 90 | reg_offset = 0x70; 91 | } else { 92 | addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_5); 93 | if (!addr) 94 | return 1; 95 | reg_offset = 0x50; 96 | } 97 | 98 | sii_bar = rphysmap("SATA SiI registers", addr, SATASII_MEMMAP_SIZE); 99 | if (sii_bar == ERROR_PTR) 100 | return 1; 101 | sii_bar += reg_offset; 102 | 103 | /* Check if ROM cycle are OK. */ 104 | if ((id != 0x0680) && (!(pci_mmio_readl(sii_bar) & (1 << 26)))) 105 | msg_pwarn("Warning: Flash seems unconnected.\n"); 106 | 107 | register_par_master(&par_master_satasii, BUS_PARALLEL); 108 | 109 | return 0; 110 | } 111 | 112 | static void satasii_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr) 113 | { 114 | uint32_t data_reg; 115 | uint32_t ctrl_reg = satasii_wait_done(); 116 | 117 | /* Mask out unused/reserved bits, set writes and start transaction. */ 118 | ctrl_reg &= 0xfcf80000; 119 | ctrl_reg |= (1 << 25) | (0 << 24) | ((uint32_t) addr & 0x7ffff); 120 | 121 | data_reg = (pci_mmio_readl((sii_bar + 4)) & ~0xff) | val; 122 | pci_mmio_writel(data_reg, (sii_bar + 4)); 123 | pci_mmio_writel(ctrl_reg, sii_bar); 124 | 125 | satasii_wait_done(); 126 | } 127 | 128 | static uint8_t satasii_chip_readb(const struct flashctx *flash, const chipaddr addr) 129 | { 130 | uint32_t ctrl_reg = satasii_wait_done(); 131 | 132 | /* Mask out unused/reserved bits, set reads and start transaction. */ 133 | ctrl_reg &= 0xfcf80000; 134 | ctrl_reg |= (1 << 25) | (1 << 24) | ((uint32_t) addr & 0x7ffff); 135 | 136 | pci_mmio_writel(ctrl_reg, sii_bar); 137 | 138 | satasii_wait_done(); 139 | 140 | return (pci_mmio_readl(sii_bar + 4)) & 0xff; 141 | } 142 | -------------------------------------------------------------------------------- /programmer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2009,2010,2011 Carl-Daniel Hailfinger 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include "flash.h" 22 | #include "programmer.h" 23 | 24 | /* No-op shutdown() for programmers which don't need special handling */ 25 | int noop_shutdown(void) 26 | { 27 | return 0; 28 | } 29 | 30 | /* Fallback map() for programmers which don't need special handling */ 31 | void *fallback_map(const char *descr, uintptr_t phys_addr, size_t len) 32 | { 33 | /* FIXME: Should return phys_addr. */ 34 | return NULL; 35 | } 36 | 37 | /* No-op/fallback unmap() for programmers which don't need special handling */ 38 | void fallback_unmap(void *virt_addr, size_t len) 39 | { 40 | } 41 | 42 | /* No-op chip_writeb() for parallel style drivers not supporting writes */ 43 | void noop_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr) 44 | { 45 | } 46 | 47 | /* Little-endian fallback for drivers not supporting 16 bit accesses */ 48 | void fallback_chip_writew(const struct flashctx *flash, uint16_t val, 49 | chipaddr addr) 50 | { 51 | chip_writeb(flash, val & 0xff, addr); 52 | chip_writeb(flash, (val >> 8) & 0xff, addr + 1); 53 | } 54 | 55 | /* Little-endian fallback for drivers not supporting 16 bit accesses */ 56 | uint16_t fallback_chip_readw(const struct flashctx *flash, const chipaddr addr) 57 | { 58 | uint16_t val; 59 | val = chip_readb(flash, addr); 60 | val |= chip_readb(flash, addr + 1) << 8; 61 | return val; 62 | } 63 | 64 | /* Little-endian fallback for drivers not supporting 32 bit accesses */ 65 | void fallback_chip_writel(const struct flashctx *flash, uint32_t val, 66 | chipaddr addr) 67 | { 68 | chip_writew(flash, val & 0xffff, addr); 69 | chip_writew(flash, (val >> 16) & 0xffff, addr + 2); 70 | } 71 | 72 | /* Little-endian fallback for drivers not supporting 32 bit accesses */ 73 | uint32_t fallback_chip_readl(const struct flashctx *flash, const chipaddr addr) 74 | { 75 | uint32_t val; 76 | val = chip_readw(flash, addr); 77 | val |= chip_readw(flash, addr + 2) << 16; 78 | return val; 79 | } 80 | 81 | void fallback_chip_writen(const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len) 82 | { 83 | size_t i; 84 | for (i = 0; i < len; i++) 85 | chip_writeb(flash, buf[i], addr + i); 86 | return; 87 | } 88 | 89 | void fallback_chip_readn(const struct flashctx *flash, uint8_t *buf, 90 | chipaddr addr, size_t len) 91 | { 92 | size_t i; 93 | for (i = 0; i < len; i++) 94 | buf[i] = chip_readb(flash, addr + i); 95 | return; 96 | } 97 | 98 | int register_par_master(const struct par_master *mst, 99 | const enum chipbustype buses) 100 | { 101 | struct registered_master rmst; 102 | if (!mst->chip_writeb || !mst->chip_writew || !mst->chip_writel || 103 | !mst->chip_writen || !mst->chip_readb || !mst->chip_readw || 104 | !mst->chip_readl || !mst->chip_readn) { 105 | msg_perr("%s called with incomplete master definition. " 106 | "Please report a bug at flashrom@flashrom.org\n", 107 | __func__); 108 | return ERROR_FLASHROM_BUG; 109 | } 110 | 111 | rmst.buses_supported = buses; 112 | rmst.par = *mst; 113 | return register_master(&rmst); 114 | } 115 | 116 | /* The limit of 4 is totally arbitrary. */ 117 | #define MASTERS_MAX 4 118 | struct registered_master registered_masters[MASTERS_MAX]; 119 | int registered_master_count = 0; 120 | 121 | /* This function copies the struct registered_master parameter. */ 122 | int register_master(struct registered_master *mst) 123 | { 124 | if (registered_master_count >= MASTERS_MAX) { 125 | msg_perr("Tried to register more than %i master " 126 | "interfaces.\n", MASTERS_MAX); 127 | return ERROR_FLASHROM_LIMIT; 128 | } 129 | registered_masters[registered_master_count] = *mst; 130 | registered_master_count++; 131 | 132 | return 0; 133 | } 134 | 135 | enum chipbustype get_buses_supported(void) 136 | { 137 | int i; 138 | enum chipbustype ret = BUS_NONE; 139 | 140 | for (i = 0; i < registered_master_count; i++) 141 | ret |= registered_masters[i].buses_supported; 142 | 143 | return ret; 144 | } 145 | -------------------------------------------------------------------------------- /nic3com.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2009 Uwe Hermann 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #if defined(__i386__) || defined(__x86_64__) 22 | 23 | #include 24 | #include "flash.h" 25 | #include "programmer.h" 26 | #include "hwaccess.h" 27 | 28 | #define BIOS_ROM_ADDR 0x04 29 | #define BIOS_ROM_DATA 0x08 30 | #define INT_STATUS 0x0e 31 | #define INTERNAL_CONFIG 0x00 32 | #define SELECT_REG_WINDOW 0x800 33 | 34 | #define PCI_VENDOR_ID_3COM 0x10b7 35 | 36 | static uint32_t io_base_addr = 0; 37 | static uint32_t internal_conf; 38 | static uint16_t id; 39 | 40 | const struct dev_entry nics_3com[] = { 41 | /* 3C90xB */ 42 | {0x10b7, 0x9055, OK, "3COM", "3C90xB: PCI 10/100 Mbps; shared 10BASE-T/100BASE-TX"}, 43 | {0x10b7, 0x9001, NT, "3COM", "3C90xB: PCI 10/100 Mbps; shared 10BASE-T/100BASE-T4" }, 44 | {0x10b7, 0x9004, OK, "3COM", "3C90xB: PCI 10BASE-T (TPO)" }, 45 | {0x10b7, 0x9005, NT, "3COM", "3C90xB: PCI 10BASE-T/10BASE2/AUI (COMBO)" }, 46 | {0x10b7, 0x9006, NT, "3COM", "3C90xB: PCI 10BASE-T/10BASE2 (TPC)" }, 47 | {0x10b7, 0x900a, NT, "3COM", "3C90xB: PCI 10BASE-FL" }, 48 | {0x10b7, 0x905a, NT, "3COM", "3C90xB: PCI 10BASE-FX" }, 49 | {0x10b7, 0x9058, OK, "3COM", "3C905B: Cyclone 10/100/BNC" }, 50 | 51 | /* 3C905C */ 52 | {0x10b7, 0x9200, OK, "3COM", "3C905C: EtherLink 10/100 PCI (TX)" }, 53 | 54 | /* 3C980C */ 55 | {0x10b7, 0x9805, NT, "3COM", "3C980C: EtherLink Server 10/100 PCI (TX)" }, 56 | 57 | {0}, 58 | }; 59 | 60 | static void nic3com_chip_writeb(const struct flashctx *flash, uint8_t val, 61 | chipaddr addr); 62 | static uint8_t nic3com_chip_readb(const struct flashctx *flash, 63 | const chipaddr addr); 64 | static const struct par_master par_master_nic3com = { 65 | .chip_readb = nic3com_chip_readb, 66 | .chip_readw = fallback_chip_readw, 67 | .chip_readl = fallback_chip_readl, 68 | .chip_readn = fallback_chip_readn, 69 | .chip_writeb = nic3com_chip_writeb, 70 | .chip_writew = fallback_chip_writew, 71 | .chip_writel = fallback_chip_writel, 72 | .chip_writen = fallback_chip_writen, 73 | }; 74 | 75 | static int nic3com_shutdown(void *data) 76 | { 77 | /* 3COM 3C90xB cards need a special fixup. */ 78 | if (id == 0x9055 || id == 0x9001 || id == 0x9004 || id == 0x9005 79 | || id == 0x9006 || id == 0x900a || id == 0x905a || id == 0x9058) { 80 | /* Select register window 3 and restore the receiver status. */ 81 | OUTW(SELECT_REG_WINDOW + 3, io_base_addr + INT_STATUS); 82 | OUTL(internal_conf, io_base_addr + INTERNAL_CONFIG); 83 | } 84 | 85 | return 0; 86 | } 87 | 88 | int nic3com_init(void) 89 | { 90 | struct pci_dev *dev = NULL; 91 | 92 | if (rget_io_perms()) 93 | return 1; 94 | 95 | dev = pcidev_init(nics_3com, PCI_BASE_ADDRESS_0); 96 | if (!dev) 97 | return 1; 98 | 99 | io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); 100 | if (!io_base_addr) 101 | return 1; 102 | 103 | id = dev->device_id; 104 | 105 | /* 3COM 3C90xB cards need a special fixup. */ 106 | if (id == 0x9055 || id == 0x9001 || id == 0x9004 || id == 0x9005 107 | || id == 0x9006 || id == 0x900a || id == 0x905a || id == 0x9058) { 108 | /* Select register window 3 and save the receiver status. */ 109 | OUTW(SELECT_REG_WINDOW + 3, io_base_addr + INT_STATUS); 110 | internal_conf = INL(io_base_addr + INTERNAL_CONFIG); 111 | 112 | /* Set receiver type to MII for full BIOS ROM access. */ 113 | OUTL((internal_conf & 0xf00fffff) | 0x00600000, io_base_addr); 114 | } 115 | 116 | /* 117 | * The lowest 16 bytes of the I/O mapped register space of (most) 3COM 118 | * cards form a 'register window' into one of multiple (usually 8) 119 | * register banks. For 3C90xB/3C90xC we need register window/bank 0. 120 | */ 121 | OUTW(SELECT_REG_WINDOW + 0, io_base_addr + INT_STATUS); 122 | 123 | if (register_shutdown(nic3com_shutdown, NULL)) 124 | return 1; 125 | 126 | max_rom_decode.parallel = 128 * 1024; 127 | register_par_master(&par_master_nic3com, BUS_PARALLEL); 128 | 129 | return 0; 130 | } 131 | 132 | static void nic3com_chip_writeb(const struct flashctx *flash, uint8_t val, 133 | chipaddr addr) 134 | { 135 | OUTL((uint32_t)addr, io_base_addr + BIOS_ROM_ADDR); 136 | OUTB(val, io_base_addr + BIOS_ROM_DATA); 137 | } 138 | 139 | static uint8_t nic3com_chip_readb(const struct flashctx *flash, 140 | const chipaddr addr) 141 | { 142 | OUTL((uint32_t)addr, io_base_addr + BIOS_ROM_ADDR); 143 | return INB(io_base_addr + BIOS_ROM_DATA); 144 | } 145 | 146 | #else 147 | #error PCI port I/O access is not supported on this architecture yet. 148 | #endif 149 | -------------------------------------------------------------------------------- /spi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2007, 2008 Carl-Daniel Hailfinger 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef __SPI_H__ 21 | #define __SPI_H__ 1 22 | 23 | /* 24 | * Contains the generic SPI headers 25 | */ 26 | 27 | /* Read Electronic ID */ 28 | #define JEDEC_RDID 0x9f 29 | #define JEDEC_RDID_OUTSIZE 0x01 30 | /* INSIZE may be 0x04 for some chips*/ 31 | #define JEDEC_RDID_INSIZE 0x03 32 | 33 | /* Some Atmel AT25F* models have bit 3 as don't care bit in commands */ 34 | #define AT25F_RDID 0x15 /* 0x15 or 0x1d */ 35 | #define AT25F_RDID_OUTSIZE 0x01 36 | #define AT25F_RDID_INSIZE 0x02 37 | 38 | /* Read Electronic Manufacturer Signature */ 39 | #define JEDEC_REMS 0x90 40 | #define JEDEC_REMS_OUTSIZE 0x04 41 | #define JEDEC_REMS_INSIZE 0x02 42 | 43 | /* Read Serial Flash Discoverable Parameters (SFDP) */ 44 | #define JEDEC_SFDP 0x5a 45 | #define JEDEC_SFDP_OUTSIZE 0x05 /* 8b op, 24b addr, 8b dummy */ 46 | /* JEDEC_SFDP_INSIZE : any length */ 47 | 48 | /* Read Electronic Signature */ 49 | #define JEDEC_RES 0xab 50 | #define JEDEC_RES_OUTSIZE 0x04 51 | /* INSIZE may be 0x02 for some chips*/ 52 | #define JEDEC_RES_INSIZE 0x01 53 | 54 | /* Write Enable */ 55 | #define JEDEC_WREN 0x06 56 | #define JEDEC_WREN_OUTSIZE 0x01 57 | #define JEDEC_WREN_INSIZE 0x00 58 | 59 | /* Write Disable */ 60 | #define JEDEC_WRDI 0x04 61 | #define JEDEC_WRDI_OUTSIZE 0x01 62 | #define JEDEC_WRDI_INSIZE 0x00 63 | 64 | /* Chip Erase 0x60 is supported by Macronix/SST chips. */ 65 | #define JEDEC_CE_60 0x60 66 | #define JEDEC_CE_60_OUTSIZE 0x01 67 | #define JEDEC_CE_60_INSIZE 0x00 68 | 69 | /* Chip Erase 0x62 is supported by Atmel AT25F chips. */ 70 | #define JEDEC_CE_62 0x62 71 | #define JEDEC_CE_62_OUTSIZE 0x01 72 | #define JEDEC_CE_62_INSIZE 0x00 73 | 74 | /* Chip Erase 0xc7 is supported by SST/ST/EON/Macronix chips. */ 75 | #define JEDEC_CE_C7 0xc7 76 | #define JEDEC_CE_C7_OUTSIZE 0x01 77 | #define JEDEC_CE_C7_INSIZE 0x00 78 | 79 | /* Block Erase 0x50 is supported by Atmel AT26DF chips. */ 80 | #define JEDEC_BE_50 0x50 81 | #define JEDEC_BE_50_OUTSIZE 0x04 82 | #define JEDEC_BE_50_INSIZE 0x00 83 | 84 | /* Block Erase 0x52 is supported by SST and old Atmel chips. */ 85 | #define JEDEC_BE_52 0x52 86 | #define JEDEC_BE_52_OUTSIZE 0x04 87 | #define JEDEC_BE_52_INSIZE 0x00 88 | 89 | /* Block Erase 0x81 is supported by Atmel AT26DF chips. */ 90 | #define JEDEC_BE_81 0x81 91 | #define JEDEC_BE_81_OUTSIZE 0x04 92 | #define JEDEC_BE_81_INSIZE 0x00 93 | 94 | /* Block Erase 0xc4 is supported by Micron chips. */ 95 | #define JEDEC_BE_C4 0xc4 96 | #define JEDEC_BE_C4_OUTSIZE 0x04 97 | #define JEDEC_BE_C4_INSIZE 0x00 98 | 99 | /* Block Erase 0xd8 is supported by EON/Macronix chips. */ 100 | #define JEDEC_BE_D8 0xd8 101 | #define JEDEC_BE_D8_OUTSIZE 0x04 102 | #define JEDEC_BE_D8_INSIZE 0x00 103 | 104 | /* Block Erase 0xd7 is supported by PMC chips. */ 105 | #define JEDEC_BE_D7 0xd7 106 | #define JEDEC_BE_D7_OUTSIZE 0x04 107 | #define JEDEC_BE_D7_INSIZE 0x00 108 | 109 | /* Sector Erase 0x20 is supported by Macronix/SST chips. */ 110 | #define JEDEC_SE 0x20 111 | #define JEDEC_SE_OUTSIZE 0x04 112 | #define JEDEC_SE_INSIZE 0x00 113 | 114 | /* Page Erase 0xDB */ 115 | #define JEDEC_PE 0xDB 116 | #define JEDEC_PE_OUTSIZE 0x04 117 | #define JEDEC_PE_INSIZE 0x00 118 | 119 | /* Read Status Register */ 120 | #define JEDEC_RDSR 0x05 121 | #define JEDEC_RDSR_OUTSIZE 0x01 122 | #define JEDEC_RDSR_INSIZE 0x01 123 | 124 | /* Status Register Bits */ 125 | #define SPI_SR_WIP (0x01 << 0) 126 | #define SPI_SR_WEL (0x01 << 1) 127 | #define SPI_SR_AAI (0x01 << 6) 128 | 129 | /* Write Status Enable */ 130 | #define JEDEC_EWSR 0x50 131 | #define JEDEC_EWSR_OUTSIZE 0x01 132 | #define JEDEC_EWSR_INSIZE 0x00 133 | 134 | /* Write Status Register */ 135 | #define JEDEC_WRSR 0x01 136 | #define JEDEC_WRSR_OUTSIZE 0x02 137 | #define JEDEC_WRSR_INSIZE 0x00 138 | 139 | /* Read the memory */ 140 | #define JEDEC_READ 0x03 141 | #define JEDEC_READ_OUTSIZE 0x04 142 | /* JEDEC_READ_INSIZE : any length */ 143 | 144 | /* Write memory byte */ 145 | #define JEDEC_BYTE_PROGRAM 0x02 146 | #define JEDEC_BYTE_PROGRAM_OUTSIZE 0x05 147 | #define JEDEC_BYTE_PROGRAM_INSIZE 0x00 148 | 149 | /* Write AAI word (SST25VF080B) */ 150 | #define JEDEC_AAI_WORD_PROGRAM 0xad 151 | #define JEDEC_AAI_WORD_PROGRAM_OUTSIZE 0x06 152 | #define JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE 0x03 153 | #define JEDEC_AAI_WORD_PROGRAM_INSIZE 0x00 154 | 155 | /* Error codes */ 156 | #define SPI_GENERIC_ERROR -1 157 | #define SPI_INVALID_OPCODE -2 158 | #define SPI_INVALID_ADDRESS -3 159 | #define SPI_INVALID_LENGTH -4 160 | #define SPI_FLASHROM_BUG -5 161 | #define SPI_PROGRAMMER_ERROR -6 162 | 163 | #endif /* !__SPI_H__ */ 164 | -------------------------------------------------------------------------------- /coreboot_tables.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the coreboot project. 3 | * 4 | * Copyright (C) 2002 Linux Networx 5 | * (Written by Eric Biederman for Linux Networx) 6 | * Copyright (C) 2005-2007 coresystems GmbH 7 | * 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; version 2 of the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA 20 | */ 21 | 22 | #ifndef COREBOOT_TABLES_H 23 | #define COREBOOT_TABLES_H 24 | 25 | #include 26 | 27 | /* The coreboot table information is for conveying information 28 | * from the firmware to the loaded OS image. Primarily this 29 | * is expected to be information that cannot be discovered by 30 | * other means, such as querying the hardware directly. 31 | * 32 | * All of the information should be Position Independent Data. 33 | * That is it should be safe to relocated any of the information 34 | * without it's meaning/correctness changing. For table that 35 | * can reasonably be used on multiple architectures the data 36 | * size should be fixed. This should ease the transition between 37 | * 32 bit and 64 bit architectures etc. 38 | * 39 | * The completeness test for the information in this table is: 40 | * - Can all of the hardware be detected? 41 | * - Are the per motherboard constants available? 42 | * - Is there enough to allow a kernel to run that was written before 43 | * a particular motherboard is constructed? (Assuming the kernel 44 | * has drivers for all of the hardware but it does not have 45 | * assumptions on how the hardware is connected together). 46 | * 47 | * With this test it should be straight forward to determine if a 48 | * table entry is required or not. This should remove much of the 49 | * long term compatibility burden as table entries which are 50 | * irrelevant or have been replaced by better alternatives may be 51 | * dropped. Of course it is polite and expedite to include extra 52 | * table entries and be backwards compatible, but it is not required. 53 | */ 54 | 55 | /* Since coreboot is usually compiled 32bit, gcc will align 64bit 56 | * types to 32bit boundaries. If the coreboot table is dumped on a 57 | * 64bit system, a uint64_t would be aligned to 64bit boundaries, 58 | * breaking the table format. 59 | * 60 | * lb_uint64 will keep 64bit coreboot table values aligned to 32bit 61 | * to ensure compatibility. They can be accessed with the two functions 62 | * below: unpack_lb64() and pack_lb64() 63 | * 64 | * See also: util/lbtdump/lbtdump.c 65 | */ 66 | 67 | struct lb_uint64 { 68 | uint32_t lo; 69 | uint32_t hi; 70 | }; 71 | 72 | struct lb_header { 73 | uint8_t signature[4]; /* LBIO */ 74 | uint32_t header_bytes; 75 | uint32_t header_checksum; 76 | uint32_t table_bytes; 77 | uint32_t table_checksum; 78 | uint32_t table_entries; 79 | }; 80 | 81 | /* Every entry in the boot environment list will correspond to a boot 82 | * info record. Encoding both type and size. The type is obviously 83 | * so you can tell what it is. The size allows you to skip that 84 | * boot environment record if you don't know what it easy. This allows 85 | * forward compatibility with records not yet defined. 86 | */ 87 | struct lb_record { 88 | uint32_t tag; /* tag ID */ 89 | uint32_t size; /* size of record (in bytes) */ 90 | }; 91 | 92 | #define LB_TAG_UNUSED 0x0000 93 | 94 | #define LB_TAG_MEMORY 0x0001 95 | 96 | struct lb_memory_range { 97 | struct lb_uint64 start; 98 | struct lb_uint64 size; 99 | uint32_t type; 100 | #define LB_MEM_RAM 1 /* Memory anyone can use */ 101 | #define LB_MEM_RESERVED 2 /* Don't use this memory region */ 102 | #define LB_MEM_TABLE 16 /* Ram configuration tables are kept in */ 103 | }; 104 | 105 | struct lb_memory { 106 | uint32_t tag; 107 | uint32_t size; 108 | struct lb_memory_range map[0]; 109 | }; 110 | 111 | #define LB_TAG_HWRPB 0x0002 112 | struct lb_hwrpb { 113 | uint32_t tag; 114 | uint32_t size; 115 | uint64_t hwrpb; 116 | }; 117 | 118 | #define LB_TAG_MAINBOARD 0x0003 119 | struct lb_mainboard { 120 | uint32_t tag; 121 | uint32_t size; 122 | uint8_t vendor_idx; 123 | uint8_t part_number_idx; 124 | uint8_t strings[0]; 125 | }; 126 | 127 | #define LB_TAG_VERSION 0x0004 128 | #define LB_TAG_EXTRA_VERSION 0x0005 129 | #define LB_TAG_BUILD 0x0006 130 | #define LB_TAG_COMPILE_TIME 0x0007 131 | #define LB_TAG_COMPILE_BY 0x0008 132 | #define LB_TAG_COMPILE_HOST 0x0009 133 | #define LB_TAG_COMPILE_DOMAIN 0x000a 134 | #define LB_TAG_COMPILER 0x000b 135 | #define LB_TAG_LINKER 0x000c 136 | #define LB_TAG_ASSEMBLER 0x000d 137 | struct lb_string { 138 | uint32_t tag; 139 | uint32_t size; 140 | uint8_t string[0]; 141 | }; 142 | 143 | #define LB_TAG_FORWARD 0x0011 144 | struct lb_forward { 145 | uint32_t tag; 146 | uint32_t size; 147 | uint64_t forward; 148 | }; 149 | 150 | #endif /* COREBOOT_TABLES_H */ 151 | -------------------------------------------------------------------------------- /bitbang_spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "flash.h" 25 | #include "programmer.h" 26 | #include "spi.h" 27 | 28 | /* Note that CS# is active low, so val=0 means the chip is active. */ 29 | static void bitbang_spi_set_cs(const struct bitbang_spi_master * const master, int val) 30 | { 31 | master->set_cs(val); 32 | } 33 | 34 | static void bitbang_spi_set_sck(const struct bitbang_spi_master * const master, int val) 35 | { 36 | master->set_sck(val); 37 | } 38 | 39 | static void bitbang_spi_set_mosi(const struct bitbang_spi_master * const master, int val) 40 | { 41 | master->set_mosi(val); 42 | } 43 | 44 | static int bitbang_spi_get_miso(const struct bitbang_spi_master * const master) 45 | { 46 | return master->get_miso(); 47 | } 48 | 49 | static void bitbang_spi_request_bus(const struct bitbang_spi_master * const master) 50 | { 51 | if (master->request_bus) 52 | master->request_bus(); 53 | } 54 | 55 | static void bitbang_spi_release_bus(const struct bitbang_spi_master * const master) 56 | { 57 | if (master->release_bus) 58 | master->release_bus(); 59 | } 60 | 61 | static int bitbang_spi_send_command(struct flashctx *flash, 62 | unsigned int writecnt, unsigned int readcnt, 63 | const unsigned char *writearr, 64 | unsigned char *readarr); 65 | 66 | static const struct spi_master spi_master_bitbang = { 67 | .type = SPI_CONTROLLER_BITBANG, 68 | .max_data_read = MAX_DATA_READ_UNLIMITED, 69 | .max_data_write = MAX_DATA_WRITE_UNLIMITED, 70 | .command = bitbang_spi_send_command, 71 | .multicommand = default_spi_send_multicommand, 72 | .read = default_spi_read, 73 | .write_256 = default_spi_write_256, 74 | .write_aai = default_spi_write_aai, 75 | }; 76 | 77 | #if 0 // until it is needed 78 | static int bitbang_spi_shutdown(const struct bitbang_spi_master *master) 79 | { 80 | /* FIXME: Run bitbang_spi_release_bus here or per command? */ 81 | return 0; 82 | } 83 | #endif 84 | 85 | int register_spi_bitbang_master(const struct bitbang_spi_master *master) 86 | { 87 | struct spi_master mst = spi_master_bitbang; 88 | /* BITBANG_SPI_INVALID is 0, so if someone forgot to initialize ->type, 89 | * we catch it here. Same goes for missing initialization of bitbanging 90 | * functions. 91 | */ 92 | if (!master || master->type == BITBANG_SPI_INVALID || !master->set_cs || 93 | !master->set_sck || !master->set_mosi || !master->get_miso || 94 | (master->request_bus && !master->release_bus) || 95 | (!master->request_bus && master->release_bus)) { 96 | msg_perr("Incomplete SPI bitbang master setting!\n" 97 | "Please report a bug at flashrom@flashrom.org\n"); 98 | return ERROR_FLASHROM_BUG; 99 | } 100 | 101 | mst.data = master; 102 | register_spi_master(&mst); 103 | 104 | /* Only mess with the bus if we're sure nobody else uses it. */ 105 | bitbang_spi_request_bus(master); 106 | bitbang_spi_set_cs(master, 1); 107 | bitbang_spi_set_sck(master, 0); 108 | bitbang_spi_set_mosi(master, 0); 109 | /* FIXME: Release SPI bus here and request it again for each command or 110 | * don't release it now and only release it on programmer shutdown? 111 | */ 112 | bitbang_spi_release_bus(master); 113 | return 0; 114 | } 115 | 116 | static uint8_t bitbang_spi_rw_byte(const struct bitbang_spi_master *master, 117 | uint8_t val) 118 | { 119 | uint8_t ret = 0; 120 | int i; 121 | 122 | for (i = 7; i >= 0; i--) { 123 | bitbang_spi_set_mosi(master, (val >> i) & 1); 124 | programmer_delay(master->half_period); 125 | bitbang_spi_set_sck(master, 1); 126 | ret <<= 1; 127 | ret |= bitbang_spi_get_miso(master); 128 | programmer_delay(master->half_period); 129 | bitbang_spi_set_sck(master, 0); 130 | } 131 | return ret; 132 | } 133 | 134 | static int bitbang_spi_send_command(struct flashctx *flash, 135 | unsigned int writecnt, unsigned int readcnt, 136 | const unsigned char *writearr, 137 | unsigned char *readarr) 138 | { 139 | int i; 140 | const struct bitbang_spi_master *master = flash->mst->spi.data; 141 | 142 | /* FIXME: Run bitbang_spi_request_bus here or in programmer init? 143 | * Requesting and releasing the SPI bus is handled in here to allow the 144 | * programmer to use its own SPI engine for native accesses. 145 | */ 146 | bitbang_spi_request_bus(master); 147 | bitbang_spi_set_cs(master, 0); 148 | for (i = 0; i < writecnt; i++) 149 | bitbang_spi_rw_byte(master, writearr[i]); 150 | for (i = 0; i < readcnt; i++) 151 | readarr[i] = bitbang_spi_rw_byte(master, 0); 152 | 153 | programmer_delay(master->half_period); 154 | bitbang_spi_set_cs(master, 1); 155 | programmer_delay(master->half_period); 156 | /* FIXME: Run bitbang_spi_release_bus here or in programmer init? */ 157 | bitbang_spi_release_bus(master); 158 | 159 | return 0; 160 | } 161 | -------------------------------------------------------------------------------- /mcp6x_spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2010 Carl-Daniel Hailfinger 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | /* Driver for the NVIDIA MCP6x/MCP7x MCP6X_SPI controller. 21 | * Based on clean room reverse engineered docs from 22 | * http://www.flashrom.org/pipermail/flashrom/2009-December/001180.html 23 | * created by Michael Karcher. 24 | */ 25 | 26 | #if defined(__i386__) || defined(__x86_64__) 27 | 28 | #include 29 | #include 30 | #include "flash.h" 31 | #include "programmer.h" 32 | #include "hwaccess.h" 33 | 34 | /* Bit positions for each pin. */ 35 | 36 | #define MCP6X_SPI_CS 1 37 | #define MCP6X_SPI_SCK 2 38 | #define MCP6X_SPI_MOSI 3 39 | #define MCP6X_SPI_MISO 4 40 | #define MCP6X_SPI_REQUEST 0 41 | #define MCP6X_SPI_GRANT 8 42 | 43 | void *mcp6x_spibar = NULL; 44 | 45 | /* Cached value of last GPIO state. */ 46 | static uint8_t mcp_gpiostate; 47 | 48 | static void mcp6x_request_spibus(void) 49 | { 50 | mcp_gpiostate = mmio_readb(mcp6x_spibar + 0x530); 51 | mcp_gpiostate |= 1 << MCP6X_SPI_REQUEST; 52 | mmio_writeb(mcp_gpiostate, mcp6x_spibar + 0x530); 53 | 54 | /* Wait until we are allowed to use the SPI bus. */ 55 | while (!(mmio_readw(mcp6x_spibar + 0x530) & (1 << MCP6X_SPI_GRANT))) ; 56 | 57 | /* Update the cache. */ 58 | mcp_gpiostate = mmio_readb(mcp6x_spibar + 0x530); 59 | } 60 | 61 | static void mcp6x_release_spibus(void) 62 | { 63 | mcp_gpiostate &= ~(1 << MCP6X_SPI_REQUEST); 64 | mmio_writeb(mcp_gpiostate, mcp6x_spibar + 0x530); 65 | } 66 | 67 | static void mcp6x_bitbang_set_cs(int val) 68 | { 69 | mcp_gpiostate &= ~(1 << MCP6X_SPI_CS); 70 | mcp_gpiostate |= (val << MCP6X_SPI_CS); 71 | mmio_writeb(mcp_gpiostate, mcp6x_spibar + 0x530); 72 | } 73 | 74 | static void mcp6x_bitbang_set_sck(int val) 75 | { 76 | mcp_gpiostate &= ~(1 << MCP6X_SPI_SCK); 77 | mcp_gpiostate |= (val << MCP6X_SPI_SCK); 78 | mmio_writeb(mcp_gpiostate, mcp6x_spibar + 0x530); 79 | } 80 | 81 | static void mcp6x_bitbang_set_mosi(int val) 82 | { 83 | mcp_gpiostate &= ~(1 << MCP6X_SPI_MOSI); 84 | mcp_gpiostate |= (val << MCP6X_SPI_MOSI); 85 | mmio_writeb(mcp_gpiostate, mcp6x_spibar + 0x530); 86 | } 87 | 88 | static int mcp6x_bitbang_get_miso(void) 89 | { 90 | mcp_gpiostate = mmio_readb(mcp6x_spibar + 0x530); 91 | return (mcp_gpiostate >> MCP6X_SPI_MISO) & 0x1; 92 | } 93 | 94 | static const struct bitbang_spi_master bitbang_spi_master_mcp6x = { 95 | .type = BITBANG_SPI_MASTER_MCP, 96 | .set_cs = mcp6x_bitbang_set_cs, 97 | .set_sck = mcp6x_bitbang_set_sck, 98 | .set_mosi = mcp6x_bitbang_set_mosi, 99 | .get_miso = mcp6x_bitbang_get_miso, 100 | .request_bus = mcp6x_request_spibus, 101 | .release_bus = mcp6x_release_spibus, 102 | .half_period = 0, 103 | }; 104 | 105 | int mcp6x_spi_init(int want_spi) 106 | { 107 | uint16_t status; 108 | uint32_t mcp6x_spibaraddr; 109 | struct pci_dev *smbusdev; 110 | 111 | /* Look for the SMBus device (SMBus PCI class) */ 112 | smbusdev = pci_dev_find_vendorclass(0x10de, 0x0c05); 113 | if (!smbusdev) { 114 | if (want_spi) { 115 | msg_perr("ERROR: SMBus device not found. Not enabling " 116 | "SPI.\n"); 117 | return 1; 118 | } else { 119 | msg_pinfo("Odd. SMBus device not found.\n"); 120 | return 0; 121 | } 122 | } 123 | msg_pdbg("Found SMBus device %04x:%04x at %02x:%02x:%01x\n", 124 | smbusdev->vendor_id, smbusdev->device_id, 125 | smbusdev->bus, smbusdev->dev, smbusdev->func); 126 | 127 | 128 | /* Locate the BAR where the SPI interface lives. */ 129 | mcp6x_spibaraddr = pci_read_long(smbusdev, 0x74); 130 | /* BAR size is 64k, bits 15..4 are zero, bit 3..0 declare a 131 | * 32-bit non-prefetchable memory BAR. 132 | */ 133 | mcp6x_spibaraddr &= ~0xffff; 134 | msg_pdbg("MCP SPI BAR is at 0x%08x\n", mcp6x_spibaraddr); 135 | 136 | /* Accessing a NULL pointer BAR is evil. Don't do it. */ 137 | if (!mcp6x_spibaraddr && want_spi) { 138 | msg_perr("Error: Chipset is strapped for SPI, but MCP SPI BAR is invalid.\n"); 139 | return 1; 140 | } else if (!mcp6x_spibaraddr && !want_spi) { 141 | msg_pdbg("MCP SPI is not used.\n"); 142 | return 0; 143 | } else if (mcp6x_spibaraddr && !want_spi) { 144 | msg_pdbg("Strange. MCP SPI BAR is valid, but chipset apparently doesn't have SPI enabled.\n"); 145 | /* FIXME: Should we enable SPI anyway? */ 146 | return 0; 147 | } 148 | /* Map the BAR. Bytewise/wordwise access at 0x530 and 0x540. */ 149 | mcp6x_spibar = rphysmap("NVIDIA MCP6x SPI", mcp6x_spibaraddr, 0x544); 150 | if (mcp6x_spibar == ERROR_PTR) 151 | return 1; 152 | 153 | status = mmio_readw(mcp6x_spibar + 0x530); 154 | msg_pdbg("SPI control is 0x%04x, req=%i, gnt=%i\n", 155 | status, (status >> MCP6X_SPI_REQUEST) & 0x1, 156 | (status >> MCP6X_SPI_GRANT) & 0x1); 157 | mcp_gpiostate = status & 0xff; 158 | 159 | if (register_spi_bitbang_master(&bitbang_spi_master_mcp6x)) { 160 | /* This should never happen. */ 161 | msg_perr("MCP6X bitbang SPI master init failed!\n"); 162 | return 1; 163 | } 164 | 165 | return 0; 166 | } 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /Documentation/serprog-protocol.txt: -------------------------------------------------------------------------------- 1 | Serial Flasher Protocol Specification - version 1 (0x01 return value == 1) 2 | 3 | Command And Answer Sequence - all commands give an answer. 4 | PC: COMMAND(8bit) 5 | DEV: ACK/NAK(8bit) / nothing 6 | Command 0x10 (SYNCNOP) has a special return of NAK+ACK for synchronization. 7 | 8 | ACK = 0x06 9 | NAK = 0x15 10 | 11 | All multibyte values are little-endian. Addresses and lengths are 24-bit. 12 | 13 | COMMAND Description Parameters Return Value 14 | 0x00 NOP none ACK 15 | 0x01 Query programmer iface version none ACK + 16bit version (nonzero) 16 | 0x02 Query supported commands bitmap none ACK + 32 bytes (256 bits) of supported cmds flags 17 | 0x03 Query programmer name none ACK + 16 bytes string (null padding) / NAK 18 | 0x04 Query serial buffer size none ACK + 16bit size / NAK 19 | 0x05 Query supported bustypes none ACK + 8-bit flags (as per flashrom) / NAK 20 | 0x06 Query connected address lines none ACK + 8bit line count / NAK 21 | 0x07 Query operation buffer size none ACK + 16bit size / NAK 22 | 0x08 Query maximum write-n length none ACK + 24bit length (0==2^24) / NAK 23 | 0x09 Read byte 24-bit addr ACK + BYTE / NAK 24 | 0x0A Read n bytes 24-bit addr + 24-bit length ACK + length bytes / NAK 25 | 0x0B Initialize operation buffer none ACK / NAK 26 | 0x0C Write to opbuf: Write byte 24-bit addr + 8-bit byte ACK / NAK (NOTE: takes 5 bytes in opbuf) 27 | 0x0D Write to opbuf: Write n 24-bit length + 24-bit addr + ACK / NAK (NOTE: takes 7+n bytes in opbuf) 28 | + length bytes of data 29 | 0x0E Write to opbuf: delay 32-bit usecs ACK / NAK (NOTE: takes 5 bytes in opbuf) 30 | 0x0F Execute operation buffer none ACK / NAK 31 | 0x10 Sync NOP none NAK + ACK (for synchronization) 32 | 0x11 Query maximum read-n length none ACK + 24-bit length (0==2^24) / NAK 33 | 0x12 Set used bustype 8-bit flags (as with 0x05) ACK / NAK 34 | 0x13 Perform SPI operation 24-bit slen + 24-bit rlen ACK + rlen bytes of data / NAK 35 | + slen bytes of data 36 | 0x14 Set SPI clock frequency in Hz 32-bit requested frequency ACK + 32-bit set frequency / NAK 37 | 0x15 Toggle flash chip pin drivers 8-bit (0 disable, else enable) ACK / NAK 38 | 0x?? unimplemented command - invalid. 39 | 40 | 41 | Additional information of the above commands: 42 | About unimplemented commands / startup sequence: 43 | Only commands allowed to be used without checking anything are 0x00,0x10 and 0x01 (NOP,SYNCNOP,Q_IFACE). 44 | If 0x01 doesn't return 1, dont do anything if you dont support a newer protocol. 45 | Then, check support for any other opcode (except 0x02) by using 0x02 (Q_CMDMAP). 46 | 0x02 (Q_CMDMAP): 47 | The map's bits are mapped as follows: 48 | cmd 0 support: byte 0 bit 0 49 | cmd 1 support: byte 0 bit 1 50 | cmd 7 support: byte 0 bit 7 51 | cmd 8 support: byte 1 bit 0, and so on. 52 | 0x04 (Q_SERBUF): 53 | If the programmer has a guaranteed working flow control, 54 | it should return a big bogus value - eg 0xFFFF. 55 | 0x05 (Q_BUSTYPE): 56 | The bit's are defined as follows: 57 | bit 0: PARALLEL, bit 1: LPC, bit 2: FWH, bit 3: SPI. 58 | 0x06 (Q_CHIPSIZE): 59 | Only applicable to parallel programmers. 60 | An LPC/FWH/SPI-programmer can report this as not supported in the command bitmap. 61 | 0x08 (Q_WRNMAXLEN): 62 | If a programmer reports a bigger maximum write-n length than the serial buffer size, 63 | it is assumed that the programmer can process the data fast enough to take in the 64 | reported maximum write-n without problems. 65 | 0x0F (O_EXEC): 66 | Execute operation buffer will also clear it, regardless of the return value. 67 | 0x11 (Q_RDNMAXLEN): 68 | If this command is not supported, assume return of 0 (2^24). 69 | 0x12 (S_BUSTYPE): 70 | Set's the used bustype if the programmer can support more than one flash protocol. 71 | Sending a byte with more than 1 bit set will make the programmer decide among them 72 | on it's own. Bit values as with Q_BUSTYPE. 73 | 0x13 (O_SPIOP): 74 | Send and receive bytes via SPI. 75 | Maximum slen is Q_WRNMAXLEN in case Q_BUSTYPE returns SPI only or S_BUSTYPE was used 76 | to set SPI exclusively before. Same for rlen and Q_RDNMAXLEN. 77 | This operation is immediate, meaning it doesn't use the operation buffer. 78 | 0x14 (S_SPI_FREQ): 79 | Set the SPI clock frequency. The 32-bit value indicates the 80 | requested frequency in Hertz. Value 0 is reserved and should 81 | be NAKed by the programmer. The requested frequency should be 82 | mapped by the programmer software to a supported frequency 83 | lower than the one requested. If there is no lower frequency 84 | available the lowest possible should be used. The value 85 | chosen is sent back in the reply with an ACK. 86 | 0x15 (S_CMD_S_PIN_STATE): 87 | Sets the state of the pin drivers connected to the flash chip. Disabling them allows other 88 | devices (e.g. a mainboard's chipset) to access the chip. This way the serprog controller can 89 | remain attached to the flash chip even when the board is running. The user is responsible to 90 | NOT connect VCC and other permanently externally driven signals to the programmer as needed. 91 | If the value is 0, then the drivers should be disabled, otherwise they should be enabled. 92 | About mandatory commands: 93 | The only truly mandatory commands for any device are 0x00, 0x01, 0x02 and 0x10, 94 | but one can't really do anything with these commands. 95 | Support for the following commands is necessary for flashrom to operate properly: 96 | S_CMD_Q_SERBUF, S_CMD_Q_OPBUF, S_CMD_Q_WRNMAXLEN, S_CMD_R_BYTE, 97 | S_CMD_R_NBYTES, S_CMD_O_INIT, S_CMD_O_WRITEB, S_CMD_O_WRITEN, 98 | S_CMD_O_DELAY, S_CMD_O_EXEC. 99 | In addition, support for these commands is recommended: 100 | S_CMD_Q_PGMNAME, S_CMD_Q_BUSTYPE, S_CMD_Q_CHIPSIZE (if parallel). 101 | 102 | See also serprog.h. 103 | -------------------------------------------------------------------------------- /pony_spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2012 Virgil-Adrian Teaca 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | /* Driver for serial programmers compatible with SI-Prog or AJAWe. 21 | * 22 | * See http://www.lancos.com/siprogsch.html for SI-Prog schematics and instructions. 23 | * See http://www.ajawe.pl/ajawe0208.htm for AJAWe serial programmer documentation. 24 | * 25 | * Pin layout for SI-Prog-like hardware: 26 | * 27 | * MOSI <-------< DTR 28 | * MISO >-------> CTS 29 | * SCK <---+---< RTS 30 | * +---> DSR 31 | * CS# <-------< TXD 32 | * 33 | * and for the AJAWe serial programmer: 34 | * 35 | * MOSI <-------< DTR 36 | * MISO >-------> CTS 37 | * SCK <-------< RTS 38 | * CS# <-------< TXD 39 | * 40 | * DCE >-------> DSR 41 | */ 42 | 43 | #include 44 | #include 45 | #include 46 | 47 | #include "flash.h" 48 | #include "programmer.h" 49 | 50 | enum pony_type { 51 | TYPE_SI_PROG, 52 | TYPE_SERBANG, 53 | TYPE_AJAWE 54 | }; 55 | 56 | /* Pins for master->slave direction */ 57 | static int pony_negate_cs = 1; 58 | static int pony_negate_sck = 0; 59 | static int pony_negate_mosi = 0; 60 | /* Pins for slave->master direction */ 61 | static int pony_negate_miso = 0; 62 | 63 | static void pony_bitbang_set_cs(int val) 64 | { 65 | if (pony_negate_cs) 66 | val ^= 1; 67 | 68 | sp_set_pin(PIN_TXD, val); 69 | } 70 | 71 | static void pony_bitbang_set_sck(int val) 72 | { 73 | if (pony_negate_sck) 74 | val ^= 1; 75 | 76 | sp_set_pin(PIN_RTS, val); 77 | } 78 | 79 | static void pony_bitbang_set_mosi(int val) 80 | { 81 | if (pony_negate_mosi) 82 | val ^= 1; 83 | 84 | sp_set_pin(PIN_DTR, val); 85 | } 86 | 87 | static int pony_bitbang_get_miso(void) 88 | { 89 | int tmp = sp_get_pin(PIN_CTS); 90 | 91 | if (pony_negate_miso) 92 | tmp ^= 1; 93 | 94 | return tmp; 95 | } 96 | 97 | static const struct bitbang_spi_master bitbang_spi_master_pony = { 98 | .type = BITBANG_SPI_MASTER_PONY, 99 | .set_cs = pony_bitbang_set_cs, 100 | .set_sck = pony_bitbang_set_sck, 101 | .set_mosi = pony_bitbang_set_mosi, 102 | .get_miso = pony_bitbang_get_miso, 103 | .half_period = 0, 104 | }; 105 | 106 | int pony_spi_init(void) 107 | { 108 | int i, data_out; 109 | char *arg = NULL; 110 | enum pony_type type = TYPE_SI_PROG; 111 | char *name; 112 | int have_device = 0; 113 | int have_prog = 0; 114 | 115 | /* The parameter is in format "dev=/dev/device,type=serbang" */ 116 | arg = extract_programmer_param("dev"); 117 | if (arg && strlen(arg)) { 118 | sp_fd = sp_openserport(arg, 9600); 119 | if (sp_fd == SER_INV_FD) { 120 | free(arg); 121 | return 1; 122 | } 123 | have_device++; 124 | } 125 | free(arg); 126 | 127 | if (!have_device) { 128 | msg_perr("Error: No valid device specified.\n" 129 | "Use flashrom -p pony_spi:dev=/dev/device[,type=name]\n"); 130 | return 1; 131 | } 132 | 133 | arg = extract_programmer_param("type"); 134 | if (arg && !strcasecmp(arg, "serbang")) { 135 | type = TYPE_SERBANG; 136 | } else if (arg && !strcasecmp(arg, "si_prog")) { 137 | type = TYPE_SI_PROG; 138 | } else if (arg && !strcasecmp( arg, "ajawe")) { 139 | type = TYPE_AJAWE; 140 | } else if (arg && !strlen(arg)) { 141 | msg_perr("Error: Missing argument for programmer type.\n"); 142 | free(arg); 143 | return 1; 144 | } else if (arg){ 145 | msg_perr("Error: Invalid programmer type specified.\n"); 146 | free(arg); 147 | return 1; 148 | } 149 | free(arg); 150 | 151 | /* 152 | * Configure the serial port pins, depending on the used programmer. 153 | */ 154 | switch (type) { 155 | case TYPE_AJAWE: 156 | pony_negate_cs = 1; 157 | pony_negate_sck = 1; 158 | pony_negate_mosi = 1; 159 | pony_negate_miso = 1; 160 | name = "AJAWe"; 161 | break; 162 | case TYPE_SERBANG: 163 | pony_negate_cs = 0; 164 | pony_negate_sck = 0; 165 | pony_negate_mosi = 0; 166 | pony_negate_miso = 1; 167 | name = "serbang"; 168 | break; 169 | default: 170 | case TYPE_SI_PROG: 171 | pony_negate_cs = 1; 172 | pony_negate_sck = 0; 173 | pony_negate_mosi = 0; 174 | pony_negate_miso = 0; 175 | name = "SI-Prog"; 176 | break; 177 | } 178 | msg_pdbg("Using %s programmer pinout.\n", name); 179 | 180 | /* 181 | * Detect if there is a compatible hardware programmer connected. 182 | */ 183 | pony_bitbang_set_cs(1); 184 | pony_bitbang_set_sck(1); 185 | pony_bitbang_set_mosi(1); 186 | 187 | switch (type) { 188 | case TYPE_AJAWE: 189 | have_prog = 1; 190 | break; 191 | case TYPE_SI_PROG: 192 | case TYPE_SERBANG: 193 | default: 194 | have_prog = 1; 195 | /* We toggle RTS/SCK a few times and see if DSR changes too. */ 196 | for (i = 1; i <= 10; i++) { 197 | data_out = i & 1; 198 | sp_set_pin(PIN_RTS, data_out); 199 | programmer_delay(1000); 200 | 201 | /* If DSR does not change, we are not connected to what we think */ 202 | if (data_out != sp_get_pin(PIN_DSR)) { 203 | have_prog = 0; 204 | break; 205 | } 206 | } 207 | break; 208 | } 209 | 210 | if (!have_prog) { 211 | msg_perr("No programmer compatible with %s detected.\n", name); 212 | return 1; 213 | } 214 | 215 | if (register_spi_bitbang_master(&bitbang_spi_master_pony)) { 216 | return 1; 217 | } 218 | return 0; 219 | } 220 | -------------------------------------------------------------------------------- /linux_spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2011 Sven Schnelle 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #if CONFIG_LINUX_SPI == 1 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "flash.h" 33 | #include "chipdrivers.h" 34 | #include "programmer.h" 35 | #include "spi.h" 36 | 37 | static int fd = -1; 38 | 39 | static int linux_spi_shutdown(void *data); 40 | static int linux_spi_send_command(struct flashctx *flash, unsigned int writecnt, 41 | unsigned int readcnt, 42 | const unsigned char *txbuf, 43 | unsigned char *rxbuf); 44 | static int linux_spi_read(struct flashctx *flash, uint8_t *buf, 45 | unsigned int start, unsigned int len); 46 | static int linux_spi_write_256(struct flashctx *flash, const uint8_t *buf, 47 | unsigned int start, unsigned int len); 48 | 49 | static const struct spi_master spi_master_linux = { 50 | .type = SPI_CONTROLLER_LINUX, 51 | .max_data_read = MAX_DATA_UNSPECIFIED, /* TODO? */ 52 | .max_data_write = MAX_DATA_UNSPECIFIED, /* TODO? */ 53 | .command = linux_spi_send_command, 54 | .multicommand = default_spi_send_multicommand, 55 | .read = linux_spi_read, 56 | .write_256 = linux_spi_write_256, 57 | .write_aai = default_spi_write_aai, 58 | }; 59 | 60 | int linux_spi_init(void) 61 | { 62 | char *p, *endp, *dev; 63 | uint32_t speed_hz = 0; 64 | /* FIXME: make the following configurable by CLI options. */ 65 | /* SPI mode 0 (beware this also includes: MSB first, CS active low and others */ 66 | const uint8_t mode = SPI_MODE_0; 67 | const uint8_t bits = 8; 68 | 69 | p = extract_programmer_param("spispeed"); 70 | if (p && strlen(p)) { 71 | speed_hz = (uint32_t)strtoul(p, &endp, 10) * 1000; 72 | if (p == endp) { 73 | msg_perr("%s: invalid clock: %s kHz\n", __func__, p); 74 | free(p); 75 | return 1; 76 | } 77 | } 78 | free(p); 79 | 80 | dev = extract_programmer_param("dev"); 81 | if (!dev || !strlen(dev)) { 82 | msg_perr("No SPI device given. Use flashrom -p " 83 | "linux_spi:dev=/dev/spidevX.Y\n"); 84 | free(dev); 85 | return 1; 86 | } 87 | 88 | msg_pdbg("Using device %s\n", dev); 89 | if ((fd = open(dev, O_RDWR)) == -1) { 90 | msg_perr("%s: failed to open %s: %s\n", __func__, 91 | dev, strerror(errno)); 92 | free(dev); 93 | return 1; 94 | } 95 | free(dev); 96 | 97 | if (register_shutdown(linux_spi_shutdown, NULL)) 98 | return 1; 99 | /* We rely on the shutdown function for cleanup from here on. */ 100 | 101 | if (speed_hz > 0) { 102 | if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed_hz) == -1) { 103 | msg_perr("%s: failed to set speed to %d Hz: %s\n", 104 | __func__, speed_hz, strerror(errno)); 105 | return 1; 106 | } 107 | 108 | msg_pdbg("Using %d kHz clock\n", speed_hz/1000); 109 | } 110 | 111 | if (ioctl(fd, SPI_IOC_WR_MODE, &mode) == -1) { 112 | msg_perr("%s: failed to set SPI mode to 0x%02x: %s\n", 113 | __func__, mode, strerror(errno)); 114 | return 1; 115 | } 116 | 117 | if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits) == -1) { 118 | msg_perr("%s: failed to set the number of bits per SPI word to %u: %s\n", 119 | __func__, bits == 0 ? 8 : bits, strerror(errno)); 120 | return 1; 121 | } 122 | 123 | register_spi_master(&spi_master_linux); 124 | 125 | return 0; 126 | } 127 | 128 | static int linux_spi_shutdown(void *data) 129 | { 130 | if (fd != -1) { 131 | close(fd); 132 | fd = -1; 133 | } 134 | return 0; 135 | } 136 | 137 | static int linux_spi_send_command(struct flashctx *flash, unsigned int writecnt, 138 | unsigned int readcnt, 139 | const unsigned char *txbuf, 140 | unsigned char *rxbuf) 141 | { 142 | int iocontrol_code; 143 | struct spi_ioc_transfer msg[2] = { 144 | { 145 | .tx_buf = (uint64_t)(uintptr_t)txbuf, 146 | .len = writecnt, 147 | }, 148 | { 149 | .rx_buf = (uint64_t)(uintptr_t)rxbuf, 150 | .len = readcnt, 151 | }, 152 | }; 153 | 154 | if (fd == -1) 155 | return -1; 156 | /* The implementation currently does not support requests that 157 | don't start with sending a command. */ 158 | if (writecnt == 0) 159 | return SPI_INVALID_LENGTH; 160 | 161 | /* Just submit the first (write) request in case there is nothing 162 | to read. Otherwise submit both requests. */ 163 | if (readcnt == 0) 164 | iocontrol_code = SPI_IOC_MESSAGE(1); 165 | else 166 | iocontrol_code = SPI_IOC_MESSAGE(2); 167 | 168 | if (ioctl(fd, iocontrol_code, msg) == -1) { 169 | msg_cerr("%s: ioctl: %s\n", __func__, strerror(errno)); 170 | return -1; 171 | } 172 | return 0; 173 | } 174 | 175 | static int linux_spi_read(struct flashctx *flash, uint8_t *buf, 176 | unsigned int start, unsigned int len) 177 | { 178 | return spi_read_chunked(flash, buf, start, len, 179 | (unsigned int)getpagesize()); 180 | } 181 | 182 | static int linux_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) 183 | { 184 | return spi_write_chunked(flash, buf, start, len, 185 | ((unsigned int)getpagesize()) - 4); 186 | } 187 | 188 | #endif // CONFIG_LINUX_SPI == 1 189 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | flashrom README 3 | ------------------------------------------------------------------------------- 4 | 5 | flashrom is a utility for detecting, reading, writing, verifying and erasing 6 | flash chips. It is often used to flash BIOS/EFI/coreboot/firmware images 7 | in-system using a supported mainboard, but it also supports flashing of network 8 | cards (NICs), SATA controller cards, and other external devices which can 9 | program flash chips. 10 | 11 | It supports a wide range of DIP32, PLCC32, DIP8, SO8/SOIC8, TSOP32, and TSOP40 12 | chips, which use various protocols such as LPC, FWH, parallel flash, or SPI. 13 | 14 | Do not use flashrom on laptops! The embedded controller (EC) present in many 15 | laptops interacts badly with any flash attempts and can brick your laptop 16 | permanently. 17 | 18 | Please make a backup of your flash chip before writing to it. 19 | 20 | Please see the flashrom(8) manpage. 21 | 22 | 23 | Packaging 24 | --------- 25 | 26 | To package flashrom and remove dependencies on subversion, either use 27 | make export 28 | or 29 | make tarball 30 | 31 | make export will export all flashrom files from the subversion repository at 32 | revision BASE into a directory named $EXPORTDIR/flashrom-$VERSION-r$SVNREVISION 33 | and will additionally modify the Makefile in that directory to contain the svn 34 | revision of the exported tree. 35 | 36 | make tarball will simply tar up the result of make export and gzip compress it. 37 | 38 | The snapshot tarballs are the result of make tarball and require no further 39 | processing. 40 | 41 | 42 | Build Instructions 43 | ------------------ 44 | 45 | To build flashrom you need to install the following software: 46 | 47 | * pciutils+libpci (if you want support for mainboard or PCI device flashing) 48 | * libusb (if you want FT2232, Dediprog or USB-Blaster support) 49 | * libftdi (if you want FT2232 or USB-Blaster support) 50 | 51 | Linux et al: 52 | 53 | * pciutils / libpci 54 | * pciutils-devel / pciutils-dev / libpci-dev 55 | * zlib-devel / zlib1g-dev (needed if libpci was compiled with libz support) 56 | 57 | On FreeBSD, you need the following ports: 58 | 59 | * devel/gmake 60 | * devel/libpci 61 | 62 | On OpenBSD, you need the following ports: 63 | 64 | * devel/gmake 65 | * sysutils/pciutils 66 | 67 | To compile on Linux, use: 68 | 69 | make 70 | 71 | To compile on FreeBSD, use: 72 | 73 | gmake 74 | 75 | To compile on Nexenta, use: 76 | 77 | make 78 | 79 | To compile on Solaris, use: 80 | 81 | gmake LDFLAGS="-L$pathtolibpci" CC="gcc -I$pathtopciheaders" CFLAGS=-O2 82 | 83 | To compile on NetBSD or DragonFly BSD (with pciutils, libftdi, libusb installed in /usr/pkg/), use: 84 | 85 | gmake 86 | 87 | To compile on OpenBSD, use: 88 | 89 | gmake 90 | 91 | To compile and run on Darwin/Mac OS X: 92 | 93 | Install DirectHW from coresystems GmbH. 94 | DirectHW is available at http://www.coreboot.org/DirectHW . 95 | 96 | To cross-compile on Linux for DOS: 97 | 98 | Get packages of the DJGPP cross compiler and install them: 99 | djgpp-filesystem djgpp-gcc djgpp-cpp djgpp-runtime djgpp-binutils 100 | As an alternative, the DJGPP web site offers packages for download as well: 101 | djcross-binutils-2.19.1-10ap.i386.rpm 102 | djcross-gcc-4.3.2-8ap.i686.rpm 103 | djcrx-2.04pre_20090725-13ap.i386.rpm 104 | The cross toolchain packages for your distribution may have slightly different 105 | names (look for packages named *djgpp*). 106 | 107 | You will need the following library source trees containing their compiled 108 | static libraries either in the parent directory of the flashrom source or 109 | specify the base folder on compile time with the DOSLIBS_BASE parameter. 110 | The default as described above is equal to calling 111 | 'make djgpp-dos DOSLIBS_BASE=..' 112 | 113 | To get and build said libraries... 114 | Download pciutils 3.1.5 and apply http://flashrom.org/File:Pciutils.patch.gz 115 | Compile pciutils, see README.DJGPP for instructions. 116 | Download and compile http://flashrom.org/File:Libgetopt.tar.gz 117 | Enter the flashrom directory. 118 | Run either (change settings where appropriate) 119 | make CC=i586-pc-msdosdjgpp-gcc STRIP=i586-pc-msdosdjgpp-strip 120 | or (above settings hardcoded) 121 | make djgpp-dos 122 | To run flashrom.exe, download http://flashrom.org/File:Csdpmi7b.zip and 123 | unpack CWSDPMI.EXE into the current directory or one in PATH. 124 | 125 | To cross-compile on Linux for Windows: 126 | 127 | Get packages of the MinGW cross compiler and install them: 128 | mingw32-filesystem mingw32-cross-cpp mingw32-cross-binutils mingw32-cross-gcc 129 | mingw32-runtime mingw32-headers 130 | The cross toolchain packages for your distribution may have slightly different 131 | names (look for packages named *mingw*). 132 | PCI-based programmers (internal etc.) are not supported on Windows. 133 | Run (change CC= and STRIP= settings where appropriate) 134 | make CC=i686-w64-mingw32-gcc STRIP=i686-w64-mingw32-strip 135 | 136 | Processor architecture dependent features: 137 | 138 | On non-x86 architectures a few programmers don't work (yet) because they 139 | use port-based I/O which is not directly available on non-x86. Those 140 | programmers will be disabled automatically if you run "make". 141 | 142 | Installation 143 | ------------ 144 | 145 | In order to install flashrom and the manpage into /usr/local, type: 146 | 147 | make install 148 | 149 | For installation in a different directory use DESTDIR, e.g. like this: 150 | 151 | make DESTDIR=/usr install 152 | 153 | If you have insufficient permissions for the destination directory, use sudo 154 | by adding sudo in front of the commands above. 155 | 156 | 157 | Contact 158 | ------- 159 | 160 | The official flashrom website is: 161 | 162 | http://www.flashrom.org/ 163 | 164 | The IRC channel is 165 | 166 | #flashrom at irc.freenode.net 167 | 168 | The mailing list address is 169 | 170 | flashrom@flashrom.org 171 | -------------------------------------------------------------------------------- /udelay.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2000 Silicon Integrated System Corporation 5 | * Copyright (C) 2009,2010 Carl-Daniel Hailfinger 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef __LIBPAYLOAD__ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "flash.h" 29 | 30 | /* loops per microsecond */ 31 | static unsigned long micro = 1; 32 | 33 | __attribute__ ((noinline)) void myusec_delay(unsigned int usecs) 34 | { 35 | unsigned long i; 36 | for (i = 0; i < usecs * micro; i++) { 37 | /* Make sure the compiler doesn't optimize the loop away. */ 38 | __asm__ volatile ("" : : "rm" (i) ); 39 | } 40 | } 41 | 42 | static unsigned long measure_os_delay_resolution(void) 43 | { 44 | unsigned long timeusec; 45 | struct timeval start, end; 46 | unsigned long counter = 0; 47 | 48 | gettimeofday(&start, NULL); 49 | timeusec = 0; 50 | 51 | while (!timeusec && (++counter < 1000000000)) { 52 | gettimeofday(&end, NULL); 53 | timeusec = 1000000 * (end.tv_sec - start.tv_sec) + 54 | (end.tv_usec - start.tv_usec); 55 | /* Protect against time going forward too much. */ 56 | if ((end.tv_sec > start.tv_sec) && 57 | ((end.tv_sec - start.tv_sec) >= LONG_MAX / 1000000 - 1)) 58 | timeusec = 0; 59 | /* Protect against time going backwards during leap seconds. */ 60 | if ((end.tv_sec < start.tv_sec) || (timeusec > LONG_MAX)) 61 | timeusec = 0; 62 | } 63 | return timeusec; 64 | } 65 | 66 | static unsigned long measure_delay(unsigned int usecs) 67 | { 68 | unsigned long timeusec; 69 | struct timeval start, end; 70 | 71 | gettimeofday(&start, NULL); 72 | myusec_delay(usecs); 73 | gettimeofday(&end, NULL); 74 | timeusec = 1000000 * (end.tv_sec - start.tv_sec) + 75 | (end.tv_usec - start.tv_usec); 76 | /* Protect against time going forward too much. */ 77 | if ((end.tv_sec > start.tv_sec) && 78 | ((end.tv_sec - start.tv_sec) >= LONG_MAX / 1000000 - 1)) 79 | timeusec = LONG_MAX; 80 | /* Protect against time going backwards during leap seconds. */ 81 | if ((end.tv_sec < start.tv_sec) || (timeusec > LONG_MAX)) 82 | timeusec = 1; 83 | 84 | return timeusec; 85 | } 86 | 87 | void myusec_calibrate_delay(void) 88 | { 89 | unsigned long count = 1000; 90 | unsigned long timeusec, resolution; 91 | int i, tries = 0; 92 | 93 | msg_pinfo("Calibrating delay loop... "); 94 | resolution = measure_os_delay_resolution(); 95 | if (resolution) { 96 | msg_pdbg("OS timer resolution is %lu usecs, ", resolution); 97 | } else { 98 | msg_pinfo("OS timer resolution is unusable. "); 99 | } 100 | 101 | recalibrate: 102 | count = 1000; 103 | while (1) { 104 | timeusec = measure_delay(count); 105 | if (timeusec > 1000000 / 4) 106 | break; 107 | if (count >= ULONG_MAX / 2) { 108 | msg_pinfo("timer loop overflow, reduced precision. "); 109 | break; 110 | } 111 | count *= 2; 112 | } 113 | tries ++; 114 | 115 | /* Avoid division by zero, but in that case the loop is shot anyway. */ 116 | if (!timeusec) 117 | timeusec = 1; 118 | 119 | /* Compute rounded up number of loops per microsecond. */ 120 | micro = (count * micro) / timeusec + 1; 121 | msg_pdbg("%luM loops per second, ", micro); 122 | 123 | /* Did we try to recalibrate less than 5 times? */ 124 | if (tries < 5) { 125 | /* Recheck our timing to make sure we weren't just hitting 126 | * a scheduler delay or something similar. 127 | */ 128 | for (i = 0; i < 4; i++) { 129 | if (resolution && (resolution < 10)) { 130 | timeusec = measure_delay(100); 131 | } else if (resolution && 132 | (resolution < ULONG_MAX / 200)) { 133 | timeusec = measure_delay(resolution * 10) * 134 | 100 / (resolution * 10); 135 | } else { 136 | /* This workaround should be active for broken 137 | * OS and maybe libpayload. The criterion 138 | * here is horrible or non-measurable OS timer 139 | * resolution which will result in 140 | * measure_delay(100)=0 whereas a longer delay 141 | * (1000 ms) may be sufficient 142 | * to get a nonzero time measurement. 143 | */ 144 | timeusec = measure_delay(1000000) / 10000; 145 | } 146 | if (timeusec < 90) { 147 | msg_pdbg("delay more than 10%% too short (got " 148 | "%lu%% of expected delay), " 149 | "recalculating... ", timeusec); 150 | goto recalibrate; 151 | } 152 | } 153 | } else { 154 | msg_perr("delay loop is unreliable, trying to continue "); 155 | } 156 | 157 | /* We're interested in the actual precision. */ 158 | timeusec = measure_delay(10); 159 | msg_pdbg("10 myus = %ld us, ", timeusec); 160 | timeusec = measure_delay(100); 161 | msg_pdbg("100 myus = %ld us, ", timeusec); 162 | timeusec = measure_delay(1000); 163 | msg_pdbg("1000 myus = %ld us, ", timeusec); 164 | timeusec = measure_delay(10000); 165 | msg_pdbg("10000 myus = %ld us, ", timeusec); 166 | timeusec = measure_delay(resolution * 4); 167 | msg_pdbg("%ld myus = %ld us, ", resolution * 4, timeusec); 168 | 169 | msg_pinfo("OK.\n"); 170 | } 171 | 172 | /* Not very precise sleep. */ 173 | void internal_sleep(unsigned int usecs) 174 | { 175 | #ifdef _WIN32 176 | Sleep((usecs + 999) / 1000); 177 | #else 178 | sleep(usecs / 1000000); 179 | usleep(usecs % 1000000); 180 | #endif 181 | } 182 | 183 | /* Precise delay. */ 184 | void internal_delay(unsigned int usecs) 185 | { 186 | /* If the delay is >1 s, use internal_sleep because timing does not need to be so precise. */ 187 | if (usecs > 1000000) { 188 | internal_sleep(usecs); 189 | } else { 190 | myusec_delay(usecs); 191 | } 192 | } 193 | 194 | #else 195 | #include 196 | 197 | void myusec_calibrate_delay(void) 198 | { 199 | get_cpu_speed(); 200 | } 201 | 202 | void internal_delay(unsigned int usecs) 203 | { 204 | udelay(usecs); 205 | } 206 | #endif 207 | -------------------------------------------------------------------------------- /spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2007, 2008, 2009, 2010, 2011 Carl-Daniel Hailfinger 5 | * Copyright (C) 2008 coresystems GmbH 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; version 2 of the License. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * Contains the generic SPI framework 23 | */ 24 | 25 | #include 26 | #include 27 | #include "flash.h" 28 | #include "flashchips.h" 29 | #include "chipdrivers.h" 30 | #include "programmer.h" 31 | #include "spi.h" 32 | 33 | int spi_send_command(struct flashctx *flash, unsigned int writecnt, 34 | unsigned int readcnt, const unsigned char *writearr, 35 | unsigned char *readarr) 36 | { 37 | return flash->mst->spi.command(flash, writecnt, readcnt, writearr, 38 | readarr); 39 | } 40 | 41 | int spi_send_multicommand(struct flashctx *flash, struct spi_command *cmds) 42 | { 43 | return flash->mst->spi.multicommand(flash, cmds); 44 | } 45 | 46 | int default_spi_send_command(struct flashctx *flash, unsigned int writecnt, 47 | unsigned int readcnt, 48 | const unsigned char *writearr, 49 | unsigned char *readarr) 50 | { 51 | struct spi_command cmd[] = { 52 | { 53 | .writecnt = writecnt, 54 | .readcnt = readcnt, 55 | .writearr = writearr, 56 | .readarr = readarr, 57 | }, { 58 | .writecnt = 0, 59 | .writearr = NULL, 60 | .readcnt = 0, 61 | .readarr = NULL, 62 | }}; 63 | 64 | return spi_send_multicommand(flash, cmd); 65 | } 66 | 67 | int default_spi_send_multicommand(struct flashctx *flash, 68 | struct spi_command *cmds) 69 | { 70 | int result = 0; 71 | for (; (cmds->writecnt || cmds->readcnt) && !result; cmds++) { 72 | result = spi_send_command(flash, cmds->writecnt, cmds->readcnt, 73 | cmds->writearr, cmds->readarr); 74 | } 75 | return result; 76 | } 77 | 78 | int default_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, 79 | unsigned int len) 80 | { 81 | unsigned int max_data = flash->mst->spi.max_data_read; 82 | if (max_data == MAX_DATA_UNSPECIFIED) { 83 | msg_perr("%s called, but SPI read chunk size not defined " 84 | "on this hardware. Please report a bug at " 85 | "flashrom@flashrom.org\n", __func__); 86 | return 1; 87 | } 88 | return spi_read_chunked(flash, buf, start, len, max_data); 89 | } 90 | 91 | int default_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) 92 | { 93 | unsigned int max_data = flash->mst->spi.max_data_write; 94 | if (max_data == MAX_DATA_UNSPECIFIED) { 95 | msg_perr("%s called, but SPI write chunk size not defined " 96 | "on this hardware. Please report a bug at " 97 | "flashrom@flashrom.org\n", __func__); 98 | return 1; 99 | } 100 | return spi_write_chunked(flash, buf, start, len, max_data); 101 | } 102 | 103 | int spi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start, 104 | unsigned int len) 105 | { 106 | unsigned int addrbase = 0; 107 | 108 | /* Check if the chip fits between lowest valid and highest possible 109 | * address. Highest possible address with the current SPI implementation 110 | * means 0xffffff, the highest unsigned 24bit number. 111 | */ 112 | addrbase = spi_get_valid_read_addr(flash); 113 | if (addrbase + flash->chip->total_size * 1024 > (1 << 24)) { 114 | msg_perr("Flash chip size exceeds the allowed access window. "); 115 | msg_perr("Read will probably fail.\n"); 116 | /* Try to get the best alignment subject to constraints. */ 117 | addrbase = (1 << 24) - flash->chip->total_size * 1024; 118 | } 119 | /* Check if alignment is native (at least the largest power of two which 120 | * is a factor of the mapped size of the chip). 121 | */ 122 | if (ffs(flash->chip->total_size * 1024) > (ffs(addrbase) ? : 33)) { 123 | msg_perr("Flash chip is not aligned natively in the allowed " 124 | "access window.\n"); 125 | msg_perr("Read will probably return garbage.\n"); 126 | } 127 | return flash->mst->spi.read(flash, buf, addrbase + start, len); 128 | } 129 | 130 | /* 131 | * Program chip using page (256 bytes) programming. 132 | * Some SPI masters can't do this, they use single byte programming instead. 133 | * The redirect to single byte programming is achieved by setting 134 | * .write_256 = spi_chip_write_1 135 | */ 136 | /* real chunksize is up to 256, logical chunksize is 256 */ 137 | int spi_chip_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) 138 | { 139 | return flash->mst->spi.write_256(flash, buf, start, len); 140 | } 141 | 142 | /* 143 | * Get the lowest allowed address for read accesses. This often happens to 144 | * be the lowest allowed address for all commands which take an address. 145 | * This is a master limitation. 146 | */ 147 | uint32_t spi_get_valid_read_addr(struct flashctx *flash) 148 | { 149 | switch (flash->mst->spi.type) { 150 | #if CONFIG_INTERNAL == 1 151 | #if defined(__i386__) || defined(__x86_64__) 152 | case SPI_CONTROLLER_ICH7: 153 | case SPI_CONTROLLER_ICH9: 154 | /* Return BBAR for ICH chipsets. */ 155 | return ichspi_bbar; 156 | #endif 157 | #endif 158 | default: 159 | return 0; 160 | } 161 | } 162 | 163 | int spi_aai_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) 164 | { 165 | return flash->mst->spi.write_aai(flash, buf, start, len); 166 | } 167 | 168 | int register_spi_master(const struct spi_master *mst) 169 | { 170 | struct registered_master rmst; 171 | 172 | if (!mst->write_aai || !mst->write_256 || !mst->read || !mst->command || 173 | !mst->multicommand || 174 | ((mst->command == default_spi_send_command) && 175 | (mst->multicommand == default_spi_send_multicommand))) { 176 | msg_perr("%s called with incomplete master definition. " 177 | "Please report a bug at flashrom@flashrom.org\n", 178 | __func__); 179 | return ERROR_FLASHROM_BUG; 180 | } 181 | 182 | 183 | rmst.buses_supported = BUS_SPI; 184 | rmst.spi = *mst; 185 | return register_master(&rmst); 186 | } 187 | -------------------------------------------------------------------------------- /atavia.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2010 Uwe Hermann 5 | * Copyright (C) 2011 Jonathan Kollasch 6 | * Copyright (C) 2012-2013 Stefan Tauner 7 | * 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. 12 | * 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. 17 | * 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 21 | */ 22 | 23 | #include 24 | #include 25 | #include "flash.h" 26 | #include "programmer.h" 27 | #include "hwaccess.h" 28 | 29 | #define PCI_VENDOR_ID_VIA 0x1106 30 | 31 | #define VIA_MAX_RETRIES 300 32 | 33 | #define BROM_ADDR 0x60 34 | 35 | #define BROM_DATA 0x64 36 | 37 | #define BROM_ACCESS 0x68 38 | #define BROM_TRIGGER 0x80 39 | #define BROM_WRITE 0x40 40 | #define BROM_SIZE_MASK 0x30 41 | #define BROM_SIZE_64K 0x00 42 | #define BROM_SIZE_32K 0x10 43 | #define BROM_SIZE_16K 0x20 44 | #define BROM_SIZE_0K 0x30 45 | #define BROM_BYTE_ENABLE_MASK 0x0f 46 | 47 | #define BROM_STATUS 0x69 48 | #define BROM_ERROR_STATUS 0x80 49 | 50 | /* Select the byte we want to access. This is done by clearing the bit corresponding to the byte we want to 51 | * access, leaving the others set (yes, really). */ 52 | #define ENABLE_BYTE(address) ((~(1 << ((address) & 3))) & BROM_BYTE_ENABLE_MASK) 53 | #define BYTE_OFFSET(address) (((addr) & 3) * 8) 54 | 55 | const struct dev_entry ata_via[] = { 56 | {PCI_VENDOR_ID_VIA, 0x3249, DEP, "VIA", "VT6421A"}, 57 | 58 | {}, 59 | }; 60 | 61 | static void atavia_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr); 62 | static uint8_t atavia_chip_readb(const struct flashctx *flash, const chipaddr addr); 63 | static const struct par_master lpc_master_atavia = { 64 | .chip_readb = atavia_chip_readb, 65 | .chip_readw = fallback_chip_readw, 66 | .chip_readl = fallback_chip_readl, 67 | .chip_readn = fallback_chip_readn, 68 | .chip_writeb = atavia_chip_writeb, 69 | .chip_writew = fallback_chip_writew, 70 | .chip_writel = fallback_chip_writel, 71 | .chip_writen = fallback_chip_writen, 72 | }; 73 | 74 | static void *atavia_offset = NULL; 75 | static struct pci_dev *dev = NULL; 76 | 77 | static void atavia_prettyprint_access(uint8_t access) 78 | { 79 | uint8_t bmask = access & BROM_BYTE_ENABLE_MASK; 80 | uint8_t size = access & BROM_SIZE_MASK; 81 | 82 | msg_pspew("Accessing byte(s):%s%s%s%s\n", 83 | ((bmask & (1<<3)) == 0) ? " 3" : "", 84 | ((bmask & (1<<2)) == 0) ? " 2" : "", 85 | ((bmask & (1<<1)) == 0) ? " 1" : "", 86 | ((bmask & (1<<0)) == 0) ? " 0" : ""); 87 | if (size == BROM_SIZE_0K) { 88 | msg_pspew("No ROM device found.\n"); 89 | } else 90 | msg_pspew("ROM device with %s kB attached.\n", 91 | (size == BROM_SIZE_64K) ? ">=64" : 92 | (size == BROM_SIZE_32K) ? "32" : "16"); 93 | msg_pspew("Access is a %s.\n", (access & BROM_WRITE) ? "write" : "read"); 94 | msg_pspew("Device is %s.\n", (access & BROM_TRIGGER) ? "busy" : "ready"); 95 | } 96 | 97 | static bool atavia_ready(struct pci_dev *pcidev_dev) 98 | { 99 | int try; 100 | uint8_t access, status; 101 | bool ready = false; 102 | 103 | for (try = 0; try < VIA_MAX_RETRIES; try++) { 104 | access = pci_read_byte(pcidev_dev, BROM_ACCESS); 105 | status = pci_read_byte(pcidev_dev, BROM_STATUS); 106 | if (((access & BROM_TRIGGER) == 0) && (status & BROM_ERROR_STATUS) == 0) { 107 | ready = true; 108 | break; 109 | } else { 110 | programmer_delay(1); 111 | continue; 112 | } 113 | } 114 | 115 | msg_pdbg2("\n%s: %s after %d tries (access=0x%02x, status=0x%02x)\n", 116 | __func__, ready ? "succeeded" : "failed", try, access, status); 117 | atavia_prettyprint_access(access); 118 | return ready; 119 | } 120 | 121 | void *atavia_map(const char *descr, uintptr_t phys_addr, size_t len) 122 | { 123 | return (atavia_offset != 0) ? atavia_offset : (void *)phys_addr; 124 | } 125 | 126 | int atavia_init(void) 127 | { 128 | char *arg = extract_programmer_param("offset"); 129 | if (arg) { 130 | if (strlen(arg) == 0) { 131 | msg_perr("Missing argument for offset.\n"); 132 | free(arg); 133 | return ERROR_FATAL; 134 | } 135 | char *endptr; 136 | atavia_offset = (void *)strtoul(arg, &endptr, 0); 137 | if (*endptr) { 138 | msg_perr("Error: Invalid offset specified: \"%s\".\n", arg); 139 | free(arg); 140 | return ERROR_FATAL; 141 | } 142 | msg_pinfo("Mapping addresses to base %p.\n", atavia_offset); 143 | } 144 | free(arg); 145 | 146 | if (rget_io_perms()) 147 | return 1; 148 | 149 | dev = pcidev_init(ata_via, PCI_ROM_ADDRESS); /* Acutally no BAR setup needed at all. */ 150 | if (!dev) 151 | return 1; 152 | 153 | /* Test if a flash chip is attached. */ 154 | pci_write_long(dev, PCI_ROM_ADDRESS, (uint32_t)PCI_ROM_ADDRESS_MASK); 155 | programmer_delay(90); 156 | uint32_t base = pci_read_long(dev, PCI_ROM_ADDRESS); 157 | msg_pdbg2("BROM base=0x%08x\n", base); 158 | if ((base & PCI_ROM_ADDRESS_MASK) == 0) { 159 | msg_pwarn("Controller thinks there is no ROM attached.\n"); 160 | } 161 | 162 | if (!atavia_ready(dev)) { 163 | msg_perr("Controller not ready.\n"); 164 | return 1; 165 | } 166 | 167 | register_par_master(&lpc_master_atavia, BUS_LPC); 168 | 169 | return 0; 170 | } 171 | 172 | static void atavia_chip_writeb(const struct flashctx *flash, uint8_t val, const chipaddr addr) 173 | { 174 | msg_pspew("%s: 0x%02x to 0x%*" PRIxPTR ".\n", __func__, val, PRIxPTR_WIDTH, addr); 175 | pci_write_long(dev, BROM_ADDR, (addr & ~3)); 176 | pci_write_long(dev, BROM_DATA, val << BYTE_OFFSET(addr)); 177 | pci_write_byte(dev, BROM_ACCESS, BROM_TRIGGER | BROM_WRITE | ENABLE_BYTE(addr)); 178 | 179 | if (!atavia_ready(dev)) { 180 | msg_perr("not ready after write\n"); 181 | } 182 | } 183 | 184 | static uint8_t atavia_chip_readb(const struct flashctx *flash, const chipaddr addr) 185 | { 186 | pci_write_long(dev, BROM_ADDR, (addr & ~3)); 187 | pci_write_byte(dev, BROM_ACCESS, BROM_TRIGGER | ENABLE_BYTE(addr)); 188 | 189 | if (!atavia_ready(dev)) { 190 | msg_perr("not ready after read\n"); 191 | } 192 | 193 | uint8_t val = (pci_read_long(dev, BROM_DATA) >> BYTE_OFFSET(addr)) & 0xff; 194 | msg_pspew("%s: 0x%02x from 0x%*" PRIxPTR ".\n", __func__, val, PRIxPTR_WIDTH, addr); 195 | return val; 196 | } 197 | -------------------------------------------------------------------------------- /Documentation/mysteries_intel.txt: -------------------------------------------------------------------------------- 1 | = BBAR on ICH8 = 2 | There is no sign of BBAR (BIOS Base Address Configuration Register) in the 3 | public datasheet (or specification update) of the ICH8. Also, the offset of 4 | that register has changed between ICH7 (SPIBAR + 50h) and ICH9 (SPIBAR + 5 | A0h), so we have no clue if or where it is on ICH8. Out current policy is to 6 | not touch it at all and assume/hope it is 0. 7 | 8 | = Accesses beyond region bounds in descriptor mode = 9 | Intel's flash image tool will always expand the last region so that it covers 10 | the whole flash chip, but some boards ship with a different configuration. 11 | It seems that in descriptor mode all addresses outside the used regions can not 12 | be accessed whatsoever. This is not specified anywhere publicly as far as we 13 | could tell. flashrom does not handle this explicitly yet. It will just fail 14 | when trying to touch an address outside of any region. 15 | See also http://www.flashrom.org/pipermail/flashrom/2011-August/007606.html 16 | 17 | = (Un)locking the ME region = 18 | If the ME region is locked by the FRAP register in descriptor mode, the host 19 | software is not allowed to read or write any address inside that region. 20 | Although the chipset datasheets specify that "[t]he contents of this register 21 | are that of the Flash Descriptor" [PANTHER], this is not entirely true. 22 | The firmware has to fill at least some of the registers involved. It is not 23 | known when they become read-only or any other details, but there is at least 24 | one HM67-based board, that provides an user-changeable setting in the firmware 25 | user interface to enable ME region updates that lead to a FRAP content that is 26 | not equal to the descriptor region bits [NC9B]. 27 | 28 | There are different ways to unlock access: 29 | 30 | - A pin strap: Flash Descriptor Security Override Strap (as indicated by the 31 | Flash Descriptor Override Pin Strap Status (FDOPSS) in HSFS. That pin is 32 | probably not accessible to end users on consumer boards (every Intel doc i 33 | have seen stresses that this is for debugging in manufacturing only and 34 | should not be available for end users). 35 | The ME indicates this in bits [19:16] (Operation Mode) in the HFS register of 36 | the HECI/MEI PCI device by setting them to 4 (SECOVR_JMPR) [MODE_CTRL]. 37 | 38 | - Intel Management Engine BIOS Extension (MEBx) Disable 39 | This option may be available to end users on some boards usually accessible 40 | by hitting ctrl+p after BIOS POST. Quote: "'Disabling' the Intel ME does not 41 | really disable it: it causes the Intel ME code to be halted at an early stage 42 | of the Intel ME's booting so that the system has no traffic originating from 43 | the Intel ME on any of the buses." [MEBX] The ME indicates this in 44 | bits [19:16] (Operation Mode) in the HFS register of the HECI/MEI PCI device 45 | by setting them to 3 (Soft Temporary Disable) [MODE_CTRL]. 46 | 47 | - Previous to Ibex Peak/5 Series chipsets removing the DIMM from slot (or 48 | channel?) #0 disables the ME completely, which may give the host access to 49 | the ME region. 50 | 51 | - HMRFPO (Host ME Region Flash Protection Override) Enable MEI command 52 | This is the most interesting one because it allows to temporarily disable 53 | the ME region protection by software. The ME indicates this in bits [19:16] 54 | (Operation Mode) in the HFS register of the HECI/MEI PCI device by setting 55 | them to 5 (SECOVER_MEI_MSG) [MODE_CTRL]. 56 | 57 | == MEI/HECI == 58 | Communication between the host software and the different services provided by 59 | the ME is done via a packet-based protocol that uses MMIO transfers to one or 60 | more virtual PCI devices. Upon this layer there exist various services that can 61 | be used to read out hardware management values (e.g. temperatures, fan speeds 62 | etc.). The lower levels of that protocol are well documented: 63 | The locations/offsets of the PCI MMIO registers are noted in the chipset 64 | datasheets. The actually communication is documented in a whitepaper [DCMI] and 65 | an outdated as well as a current Linux kernel implementation (currently in 66 | staging/ exist [KERNEL]. There exists a patch that re-implements this in user 67 | space (as part of flashrom). 68 | 69 | == Problems == 70 | The problem is that only very few higher level protocols are documented publicly, 71 | especially the bunch of messages that contain the HMRFPO commands is probably 72 | well protected and only documented in ME-specific docs and the BIOS writer's 73 | guides. We are aware of a few leaked documents though that give us a few hints 74 | about it, but nothing substantial regarding its implementation. 75 | 76 | The documents are somewhat contradicting each other in various points which 77 | might be due to factual changes in process of time or due to the different 78 | capabilities of the ME firmwares, example: 79 | 80 | Intel's Flash Programming Tool (FPT) "automatically stops ME writing to SPI 81 | ME Region, to prevent both writing at the same time, causing data corruption." [ME8] 82 | 83 | "FPT is not HMRFPO-capable, so needs [the help of the FDOPS pin] HDA_SDO if 84 | used to update the ME Region." [SPS] 85 | 86 | When looking at the various ME firmware editions (and different chipsets), things 87 | get very unclear. Some docs say that HMRFPO needs to be sent before End-of-POST 88 | (EOP), others say that the ME region can be updated in the field or that some 89 | vendor tools use it for updates. This needs to be investigated further before 90 | drawing any conclusion. 91 | 92 | [PANTHER] Intel 7 Series Chipset Family Platform Controller Hub (PCH) Datasheet 93 | Document Number: 326776, April 2012, page 857 94 | [NC9B] Jetway NC9B flashrom v0.9.5.2-r1517 log with ME region unlocked. 95 | NB: "FRAP 0e0f" vs. "FLMSTR1 0a0b". 96 | http://paste.flashrom.org/view.php?id=1215 97 | [MODE_CTRL] Client Platform Enabling Tour: Platform Software 98 | Document Number: 439167, Revision 1.2, page 52 99 | [MEBX] Intel Management Engine BIOS Extension (MEBX) User's Guide 100 | Revision 1.2, Section 3.1 and 3.5 101 | [DCMI] DCMI Host Interface Specification 102 | Revision 1.0 103 | [KERNEL] http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=tree;f=drivers/staging/mei;hb=HEAD 104 | [SPI_PROG] Ibex Peak SPI Programming Guide 105 | Document Number: 403598, Revision 1.3, page 79 106 | [ME8] Manufacturing with Intel Management Engine (ME) Firmware 8.X on Intel 7 Series 107 | Revision 2.0, page 59 108 | [SPS] Manufacturing with Intel Management Engine (ME) on Intel C600 Series Chipset 1 109 | for Romley Server 2 Platforms using Server Platform Services (SPS) Firmware 110 | Revision 2.2, page 51 111 | -------------------------------------------------------------------------------- /nicintel_spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2010 Carl-Daniel Hailfinger 5 | * Copyright (C) 2010 Idwer Vollering 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; version 2 of the License. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * Datasheets: 23 | * PCI/PCI-X Family of Gigabit Ethernet Controllers Software Developer's Manual 24 | * 82540EP/EM, 82541xx, 82544GC/EI, 82545GM/EM, 82546GB/EB, and 82547xx 25 | * http://www.intel.com/content/www/us/en/ethernet-controllers/pci-pci-x-family-gbe-controllers-software-dev-manual.html 26 | * 27 | * PCIe GbE Controllers Open Source Software Developer's Manual 28 | * http://www.intel.com/content/www/us/en/ethernet-controllers/pcie-gbe-controllers-open-source-manual.html 29 | * 30 | * Intel 82574 Gigabit Ethernet Controller Family Datasheet 31 | * http://www.intel.com/content/www/us/en/ethernet-controllers/82574l-gbe-controller-datasheet.html 32 | */ 33 | 34 | #include 35 | #include 36 | #include "flash.h" 37 | #include "programmer.h" 38 | #include "hwaccess.h" 39 | 40 | #define PCI_VENDOR_ID_INTEL 0x8086 41 | #define MEMMAP_SIZE getpagesize() 42 | 43 | /* EEPROM/Flash Control & Data Register */ 44 | #define EECD 0x10 45 | /* Flash Access Register */ 46 | #define FLA 0x1c 47 | 48 | /* 49 | * Register bits of EECD. 50 | * Table 13-6 51 | * 52 | * Bit 04, 05: FWE (Flash Write Enable Control) 53 | * 00b = not allowed 54 | * 01b = flash writes disabled 55 | * 10b = flash writes enabled 56 | * 11b = not allowed 57 | */ 58 | #define FLASH_WRITES_DISABLED 0x10 /* FWE: 10000b */ 59 | #define FLASH_WRITES_ENABLED 0x20 /* FWE: 100000b */ 60 | 61 | /* Flash Access register bits 62 | * Table 13-9 63 | */ 64 | #define FL_SCK 0 65 | #define FL_CS 1 66 | #define FL_SI 2 67 | #define FL_SO 3 68 | #define FL_REQ 4 69 | #define FL_GNT 5 70 | /* Currently unused */ 71 | // #define FL_BUSY 30 72 | // #define FL_ER 31 73 | 74 | uint8_t *nicintel_spibar; 75 | 76 | const struct dev_entry nics_intel_spi[] = { 77 | {PCI_VENDOR_ID_INTEL, 0x105e, OK, "Intel", "82571EB Gigabit Ethernet Controller"}, 78 | {PCI_VENDOR_ID_INTEL, 0x1076, OK, "Intel", "82541GI Gigabit Ethernet Controller"}, 79 | {PCI_VENDOR_ID_INTEL, 0x107c, OK, "Intel", "82541PI Gigabit Ethernet Controller"}, 80 | {PCI_VENDOR_ID_INTEL, 0x10b9, OK, "Intel", "82572EI Gigabit Ethernet Controller"}, 81 | {PCI_VENDOR_ID_INTEL, 0x10d3, OK, "Intel", "82574L Gigabit Ethernet Controller"}, 82 | 83 | {0}, 84 | }; 85 | 86 | static void nicintel_request_spibus(void) 87 | { 88 | uint32_t tmp; 89 | 90 | tmp = pci_mmio_readl(nicintel_spibar + FLA); 91 | tmp |= 1 << FL_REQ; 92 | pci_mmio_writel(tmp, nicintel_spibar + FLA); 93 | 94 | /* Wait until we are allowed to use the SPI bus. */ 95 | while (!(pci_mmio_readl(nicintel_spibar + FLA) & (1 << FL_GNT))) ; 96 | } 97 | 98 | static void nicintel_release_spibus(void) 99 | { 100 | uint32_t tmp; 101 | 102 | tmp = pci_mmio_readl(nicintel_spibar + FLA); 103 | tmp &= ~(1 << FL_REQ); 104 | pci_mmio_writel(tmp, nicintel_spibar + FLA); 105 | } 106 | 107 | static void nicintel_bitbang_set_cs(int val) 108 | { 109 | uint32_t tmp; 110 | 111 | tmp = pci_mmio_readl(nicintel_spibar + FLA); 112 | tmp &= ~(1 << FL_CS); 113 | tmp |= (val << FL_CS); 114 | pci_mmio_writel(tmp, nicintel_spibar + FLA); 115 | } 116 | 117 | static void nicintel_bitbang_set_sck(int val) 118 | { 119 | uint32_t tmp; 120 | 121 | tmp = pci_mmio_readl(nicintel_spibar + FLA); 122 | tmp &= ~(1 << FL_SCK); 123 | tmp |= (val << FL_SCK); 124 | pci_mmio_writel(tmp, nicintel_spibar + FLA); 125 | } 126 | 127 | static void nicintel_bitbang_set_mosi(int val) 128 | { 129 | uint32_t tmp; 130 | 131 | tmp = pci_mmio_readl(nicintel_spibar + FLA); 132 | tmp &= ~(1 << FL_SI); 133 | tmp |= (val << FL_SI); 134 | pci_mmio_writel(tmp, nicintel_spibar + FLA); 135 | } 136 | 137 | static int nicintel_bitbang_get_miso(void) 138 | { 139 | uint32_t tmp; 140 | 141 | tmp = pci_mmio_readl(nicintel_spibar + FLA); 142 | tmp = (tmp >> FL_SO) & 0x1; 143 | return tmp; 144 | } 145 | 146 | static const struct bitbang_spi_master bitbang_spi_master_nicintel = { 147 | .type = BITBANG_SPI_MASTER_NICINTEL, 148 | .set_cs = nicintel_bitbang_set_cs, 149 | .set_sck = nicintel_bitbang_set_sck, 150 | .set_mosi = nicintel_bitbang_set_mosi, 151 | .get_miso = nicintel_bitbang_get_miso, 152 | .request_bus = nicintel_request_spibus, 153 | .release_bus = nicintel_release_spibus, 154 | .half_period = 1, 155 | }; 156 | 157 | static int nicintel_spi_shutdown(void *data) 158 | { 159 | uint32_t tmp; 160 | 161 | /* Disable writes manually. See the comment about EECD in nicintel_spi_init() for details. */ 162 | tmp = pci_mmio_readl(nicintel_spibar + EECD); 163 | tmp &= ~FLASH_WRITES_ENABLED; 164 | tmp |= FLASH_WRITES_DISABLED; 165 | pci_mmio_writel(tmp, nicintel_spibar + EECD); 166 | 167 | return 0; 168 | } 169 | 170 | int nicintel_spi_init(void) 171 | { 172 | struct pci_dev *dev = NULL; 173 | uint32_t tmp; 174 | 175 | if (rget_io_perms()) 176 | return 1; 177 | 178 | dev = pcidev_init(nics_intel_spi, PCI_BASE_ADDRESS_0); 179 | if (!dev) 180 | return 1; 181 | 182 | uint32_t io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); 183 | if (!io_base_addr) 184 | return 1; 185 | 186 | nicintel_spibar = rphysmap("Intel Gigabit NIC w/ SPI flash", io_base_addr, MEMMAP_SIZE); 187 | if (nicintel_spibar == ERROR_PTR) 188 | return 1; 189 | 190 | /* Automatic restore of EECD on shutdown is not possible because EECD 191 | * does not only contain FLASH_WRITES_DISABLED|FLASH_WRITES_ENABLED, 192 | * but other bits with side effects as well. Those other bits must be 193 | * left untouched. 194 | */ 195 | tmp = pci_mmio_readl(nicintel_spibar + EECD); 196 | tmp &= ~FLASH_WRITES_DISABLED; 197 | tmp |= FLASH_WRITES_ENABLED; 198 | pci_mmio_writel(tmp, nicintel_spibar + EECD); 199 | 200 | /* test if FWE is really set to allow writes */ 201 | tmp = pci_mmio_readl(nicintel_spibar + EECD); 202 | if ( (tmp & FLASH_WRITES_DISABLED) || !(tmp & FLASH_WRITES_ENABLED) ) { 203 | msg_perr("Enabling flash write access failed.\n"); 204 | return 1; 205 | } 206 | 207 | if (register_shutdown(nicintel_spi_shutdown, NULL)) 208 | return 1; 209 | 210 | if (register_spi_bitbang_master(&bitbang_spi_master_nicintel)) 211 | return 1; 212 | 213 | return 0; 214 | } 215 | -------------------------------------------------------------------------------- /usbblaster_spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2012 James Laird 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | /* 21 | * Device should be connected as per "active serial" mode: 22 | * 23 | * +---------+------+-----------+ 24 | * | SPI | Pin | Altera | 25 | * +---------+------+-----------+ 26 | * | SCLK | 1 | DCLK | 27 | * | GND | 2,10 | GND | 28 | * | VCC | 4 | VCC(TRGT) | 29 | * | MISO | 7 | DATAOUT | 30 | * | /CS | 8 | nCS | 31 | * | MOSI | 9 | ASDI | 32 | * +---------+------+-----------+ 33 | * 34 | * See also the USB-Blaster Download Cable User Guide: http://www.altera.com/literature/ug/ug_usb_blstr.pdf 35 | */ 36 | 37 | #if CONFIG_USBBLASTER_SPI == 1 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include "flash.h" 45 | #include "programmer.h" 46 | #include "spi.h" 47 | 48 | /* Please keep sorted by vendor ID, then device ID. */ 49 | #define ALTERA_VID 0x09fb 50 | #define ALTERA_USBBLASTER_PID 0x6001 51 | 52 | const struct dev_entry devs_usbblasterspi[] = { 53 | {ALTERA_VID, ALTERA_USBBLASTER_PID, OK, "Altera", "USB-Blaster"}, 54 | 55 | {} 56 | }; 57 | 58 | static const struct spi_master spi_master_usbblaster; 59 | 60 | static struct ftdi_context ftdic; 61 | 62 | // command bytes 63 | #define BIT_BYTE (1<<7) // byte mode (rather than bitbang) 64 | #define BIT_READ (1<<6) // read request 65 | #define BIT_LED (1<<5) 66 | #define BIT_CS (1<<3) 67 | #define BIT_TMS (1<<1) 68 | #define BIT_CLK (1<<0) 69 | 70 | #define BUF_SIZE 64 71 | 72 | /* The programmer shifts bits in the wrong order for SPI, so we use this method to reverse the bits when needed. 73 | * http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits */ 74 | uint8_t reverse(uint8_t b) 75 | { 76 | return ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16; 77 | } 78 | 79 | 80 | /* Returns 0 upon success, a negative number upon errors. */ 81 | int usbblaster_spi_init(void) 82 | { 83 | uint8_t buf[BUF_SIZE + 1]; 84 | 85 | if (ftdi_init(&ftdic) < 0) 86 | return -1; 87 | 88 | if (ftdi_usb_open(&ftdic, ALTERA_VID, ALTERA_USBBLASTER_PID) < 0) { 89 | msg_perr("Failed to open USB-Blaster: %s\n", ftdic.error_str); 90 | return -1; 91 | } 92 | 93 | if (ftdi_usb_reset(&ftdic) < 0) { 94 | msg_perr("USB-Blaster reset failed\n"); 95 | return -1; 96 | } 97 | 98 | if (ftdi_set_latency_timer(&ftdic, 2) < 0) { 99 | msg_perr("USB-Blaster set latency timer failed\n"); 100 | return -1; 101 | } 102 | 103 | if (ftdi_write_data_set_chunksize(&ftdic, 4096) < 0 || 104 | ftdi_read_data_set_chunksize(&ftdic, BUF_SIZE) < 0) { 105 | msg_perr("USB-Blaster set chunk size failed\n"); 106 | return -1; 107 | } 108 | 109 | memset(buf, 0, sizeof(buf)); 110 | buf[sizeof(buf)-1] = BIT_LED | BIT_CS; 111 | if (ftdi_write_data(&ftdic, buf, sizeof(buf)) < 0) { 112 | msg_perr("USB-Blaster reset write failed\n"); 113 | return -1; 114 | } 115 | if (ftdi_read_data(&ftdic, buf, sizeof(buf)) < 0) { 116 | msg_perr("USB-Blaster reset read failed\n"); 117 | return -1; 118 | } 119 | 120 | register_spi_master(&spi_master_usbblaster); 121 | return 0; 122 | } 123 | 124 | static int send_write(unsigned int writecnt, const unsigned char *writearr) 125 | { 126 | int i; 127 | uint8_t buf[BUF_SIZE]; 128 | 129 | memset(buf, 0, sizeof(buf)); 130 | while (writecnt) { 131 | unsigned int n_write = min(writecnt, BUF_SIZE - 1); 132 | msg_pspew("writing %d-byte packet\n", n_write); 133 | 134 | buf[0] = BIT_BYTE | (uint8_t)n_write; 135 | for (i = 0; i < n_write; i++) { 136 | buf[i+1] = reverse(writearr[i]); 137 | } 138 | if (ftdi_write_data(&ftdic, buf, n_write + 1) < 0) { 139 | msg_perr("USB-Blaster write failed\n"); 140 | return -1; 141 | } 142 | 143 | writearr += n_write; 144 | writecnt -= n_write; 145 | } 146 | return 0; 147 | } 148 | 149 | static int send_read(unsigned int readcnt, unsigned char *readarr) 150 | { 151 | int i; 152 | unsigned int n_read; 153 | uint8_t buf[BUF_SIZE]; 154 | memset(buf, 0, sizeof(buf)); 155 | 156 | n_read = readcnt; 157 | while (n_read) { 158 | unsigned int payload_size = min(n_read, BUF_SIZE - 1); 159 | msg_pspew("reading %d-byte packet\n", payload_size); 160 | 161 | buf[0] = BIT_BYTE | BIT_READ | (uint8_t)payload_size; 162 | if (ftdi_write_data(&ftdic, buf, payload_size + 1) < 0) { 163 | msg_perr("USB-Blaster write failed\n"); 164 | return -1; 165 | } 166 | n_read -= payload_size; 167 | }; 168 | 169 | n_read = readcnt; 170 | while (n_read) { 171 | int ret = ftdi_read_data(&ftdic, readarr, n_read); 172 | if (ret < 0) { 173 | msg_perr("USB-Blaster read failed\n"); 174 | return -1; 175 | } 176 | for (i = 0; i < ret; i++) { 177 | readarr[i] = reverse(readarr[i]); 178 | } 179 | n_read -= ret; 180 | readarr += ret; 181 | } 182 | return 0; 183 | } 184 | 185 | /* Returns 0 upon success, a negative number upon errors. */ 186 | static int usbblaster_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, 187 | const unsigned char *writearr, unsigned char *readarr) 188 | { 189 | uint8_t cmd; 190 | int ret = 0; 191 | 192 | cmd = BIT_LED; // asserts /CS 193 | if (ftdi_write_data(&ftdic, &cmd, 1) < 0) { 194 | msg_perr("USB-Blaster enable chip select failed\n"); 195 | ret = -1; 196 | } 197 | 198 | if (!ret && writecnt) 199 | ret = send_write(writecnt, writearr); 200 | 201 | if (!ret && readcnt) 202 | ret = send_read(readcnt, readarr); 203 | 204 | cmd = BIT_CS; 205 | if (ftdi_write_data(&ftdic, &cmd, 1) < 0) { 206 | msg_perr("USB-Blaster disable chip select failed\n"); 207 | ret = -1; 208 | } 209 | 210 | return ret; 211 | } 212 | 213 | 214 | static const struct spi_master spi_master_usbblaster = { 215 | .type = SPI_CONTROLLER_USBBLASTER, 216 | .max_data_read = 256, 217 | .max_data_write = 256, 218 | .command = usbblaster_spi_send_command, 219 | .multicommand = default_spi_send_multicommand, 220 | .read = default_spi_read, 221 | .write_256 = default_spi_write_256, 222 | .write_aai = default_spi_write_aai, 223 | }; 224 | 225 | #endif 226 | -------------------------------------------------------------------------------- /w39.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2008 coresystems GmbH 5 | * Copyright (C) 2010 Carl-Daniel Hailfinger 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include "flash.h" 23 | #include "chipdrivers.h" 24 | 25 | static uint8_t w39_idmode_readb(struct flashctx *flash, unsigned int offset) 26 | { 27 | chipaddr bios = flash->virtual_memory; 28 | uint8_t val; 29 | 30 | /* Product Identification Entry */ 31 | chip_writeb(flash, 0xAA, bios + 0x5555); 32 | chip_writeb(flash, 0x55, bios + 0x2AAA); 33 | chip_writeb(flash, 0x90, bios + 0x5555); 34 | programmer_delay(10); 35 | 36 | /* Read something, maybe hardware lock bits */ 37 | val = chip_readb(flash, bios + offset); 38 | 39 | /* Product Identification Exit */ 40 | chip_writeb(flash, 0xAA, bios + 0x5555); 41 | chip_writeb(flash, 0x55, bios + 0x2AAA); 42 | chip_writeb(flash, 0xF0, bios + 0x5555); 43 | programmer_delay(10); 44 | 45 | return val; 46 | } 47 | 48 | static int printlock_w39_tblwp(uint8_t lock) 49 | { 50 | msg_cdbg("Hardware bootblock locking (#TBL) is %sactive.\n", 51 | (lock & (1 << 2)) ? "" : "not "); 52 | msg_cdbg("Hardware remaining chip locking (#WP) is %sactive..\n", 53 | (lock & (1 << 3)) ? "" : "not "); 54 | if (lock & ((1 << 2) | (1 << 3))) 55 | return -1; 56 | 57 | return 0; 58 | } 59 | 60 | static int printlock_w39_single_bootblock(uint8_t lock, uint16_t kB) 61 | { 62 | msg_cdbg("Software %d kB bootblock locking is %sactive.\n", kB, (lock & 0x03) ? "" : "not "); 63 | if (lock & 0x03) 64 | return -1; 65 | 66 | return 0; 67 | } 68 | 69 | static int printlock_w39_bootblock_64k16k(uint8_t lock) 70 | { 71 | msg_cdbg("Software 64 kB bootblock locking is %sactive.\n", 72 | (lock & (1 << 0)) ? "" : "not "); 73 | msg_cdbg("Software 16 kB bootblock locking is %sactive.\n", 74 | (lock & (1 << 1)) ? "" : "not "); 75 | if (lock & ((1 << 1) | (1 << 0))) 76 | return -1; 77 | 78 | return 0; 79 | } 80 | 81 | static int printlock_w39_common(struct flashctx *flash, unsigned int offset) 82 | { 83 | uint8_t lock; 84 | 85 | lock = w39_idmode_readb(flash, offset); 86 | msg_cdbg("Lockout bits:\n"); 87 | return printlock_w39_tblwp(lock); 88 | } 89 | 90 | int printlock_w39f010(struct flashctx *flash) 91 | { 92 | uint8_t lock; 93 | int ret; 94 | 95 | lock = w39_idmode_readb(flash, 0x00002); 96 | msg_cdbg("Bottom boot block:\n"); 97 | ret = printlock_w39_single_bootblock(lock, 16); 98 | 99 | lock = w39_idmode_readb(flash, 0x1fff2); 100 | msg_cdbg("Top boot block:\n"); 101 | ret |= printlock_w39_single_bootblock(lock, 16); 102 | 103 | return ret; 104 | } 105 | 106 | int printlock_w39l010(struct flashctx *flash) 107 | { 108 | uint8_t lock; 109 | int ret; 110 | 111 | lock = w39_idmode_readb(flash, 0x00002); 112 | msg_cdbg("Bottom boot block:\n"); 113 | ret = printlock_w39_single_bootblock(lock, 8); 114 | 115 | lock = w39_idmode_readb(flash, 0x1fff2); 116 | msg_cdbg("Top boot block:\n"); 117 | ret |= printlock_w39_single_bootblock(lock, 8); 118 | 119 | return ret; 120 | } 121 | 122 | int printlock_w39l020(struct flashctx *flash) 123 | { 124 | uint8_t lock; 125 | int ret; 126 | 127 | lock = w39_idmode_readb(flash, 0x00002); 128 | msg_cdbg("Bottom boot block:\n"); 129 | ret = printlock_w39_bootblock_64k16k(lock); 130 | 131 | lock = w39_idmode_readb(flash, 0x3fff2); 132 | msg_cdbg("Top boot block:\n"); 133 | ret |= printlock_w39_bootblock_64k16k(lock); 134 | 135 | return ret; 136 | } 137 | 138 | int printlock_w39l040(struct flashctx *flash) 139 | { 140 | uint8_t lock; 141 | int ret; 142 | 143 | lock = w39_idmode_readb(flash, 0x00002); 144 | msg_cdbg("Bottom boot block:\n"); 145 | ret = printlock_w39_bootblock_64k16k(lock); 146 | 147 | lock = w39_idmode_readb(flash, 0x7fff2); 148 | msg_cdbg("Top boot block:\n"); 149 | ret |= printlock_w39_bootblock_64k16k(lock); 150 | 151 | return ret; 152 | } 153 | 154 | int printlock_w39v040a(struct flashctx *flash) 155 | { 156 | uint8_t lock; 157 | int ret = 0; 158 | 159 | /* The W39V040A datasheet contradicts itself on the lock register 160 | * location: 0x00002 and 0x7fff2 are both mentioned. Pick the one 161 | * which is similar to the other chips of the same family. 162 | */ 163 | lock = w39_idmode_readb(flash, 0x7fff2); 164 | msg_cdbg("Lockout bits:\n"); 165 | 166 | ret = printlock_w39_tblwp(lock); 167 | ret |= printlock_w39_bootblock_64k16k(lock); 168 | 169 | return ret; 170 | } 171 | 172 | int printlock_w39v040b(struct flashctx *flash) 173 | { 174 | return printlock_w39_common(flash, 0x7fff2); 175 | } 176 | 177 | int printlock_w39v040c(struct flashctx *flash) 178 | { 179 | /* Typo in the datasheet? The other chips use 0x7fff2. */ 180 | return printlock_w39_common(flash, 0xfff2); 181 | } 182 | 183 | int printlock_w39v040fa(struct flashctx *flash) 184 | { 185 | int ret = 0; 186 | 187 | ret = printlock_w39v040a(flash); 188 | ret |= printlock_regspace2_uniform_64k(flash); 189 | 190 | return ret; 191 | } 192 | 193 | int printlock_w39v040fb(struct flashctx *flash) 194 | { 195 | int ret = 0; 196 | 197 | ret = printlock_w39v040b(flash); 198 | ret |= printlock_regspace2_uniform_64k(flash); 199 | 200 | return ret; 201 | } 202 | 203 | int printlock_w39v040fc(struct flashctx *flash) 204 | { 205 | int ret = 0; 206 | 207 | /* W39V040C and W39V040FC use different WP/TBL offsets. */ 208 | ret = printlock_w39_common(flash, 0x7fff2); 209 | ret |= printlock_regspace2_uniform_64k(flash); 210 | 211 | return ret; 212 | } 213 | 214 | int printlock_w39v080a(struct flashctx *flash) 215 | { 216 | return printlock_w39_common(flash, 0xffff2); 217 | } 218 | 219 | int printlock_w39v080fa(struct flashctx *flash) 220 | { 221 | int ret = 0; 222 | 223 | ret = printlock_w39v080a(flash); 224 | ret |= printlock_regspace2_uniform_64k(flash); 225 | 226 | return ret; 227 | } 228 | 229 | int printlock_w39v080fa_dual(struct flashctx *flash) 230 | { 231 | msg_cinfo("Block locking for W39V080FA in dual mode is " 232 | "undocumented.\n"); 233 | /* Better safe than sorry. */ 234 | return -1; 235 | } 236 | 237 | int printlock_at49f(struct flashctx *flash) 238 | { 239 | uint8_t lock = w39_idmode_readb(flash, 0x00002); 240 | msg_cdbg("Hardware bootblock lockout is %sactive.\n", 241 | (lock & 0x01) ? "" : "not "); 242 | return 0; 243 | } 244 | -------------------------------------------------------------------------------- /satamv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2010,2011 Carl-Daniel Hailfinger 5 | * Written by Carl-Daniel Hailfinger for Angelbird Ltd. 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; version 2 of the License. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* Datasheets are not public (yet?) */ 22 | #if defined(__i386__) || defined(__x86_64__) 23 | 24 | #include 25 | #include "flash.h" 26 | #include "programmer.h" 27 | #include "hwaccess.h" 28 | 29 | uint8_t *mv_bar; 30 | uint16_t mv_iobar; 31 | 32 | const struct dev_entry satas_mv[] = { 33 | /* 88SX6041 and 88SX6042 are the same according to the datasheet. */ 34 | {0x11ab, 0x7042, OK, "Marvell", "88SX7042 PCI-e 4-port SATA-II"}, 35 | 36 | {0}, 37 | }; 38 | 39 | #define NVRAM_PARAM 0x1045c 40 | #define FLASH_PARAM 0x1046c 41 | #define EXPANSION_ROM_BAR_CONTROL 0x00d2c 42 | #define PCI_BAR2_CONTROL 0x00c08 43 | #define GPIO_PORT_CONTROL 0x104f0 44 | 45 | static void satamv_chip_writeb(const struct flashctx *flash, uint8_t val, 46 | chipaddr addr); 47 | static uint8_t satamv_chip_readb(const struct flashctx *flash, 48 | const chipaddr addr); 49 | static const struct par_master par_master_satamv = { 50 | .chip_readb = satamv_chip_readb, 51 | .chip_readw = fallback_chip_readw, 52 | .chip_readl = fallback_chip_readl, 53 | .chip_readn = fallback_chip_readn, 54 | .chip_writeb = satamv_chip_writeb, 55 | .chip_writew = fallback_chip_writew, 56 | .chip_writel = fallback_chip_writel, 57 | .chip_writen = fallback_chip_writen, 58 | }; 59 | 60 | /* 61 | * Random notes: 62 | * FCE# Flash Chip Enable 63 | * FWE# Flash Write Enable 64 | * FOE# Flash Output Enable 65 | * FALE[1:0] Flash Address Latch Enable 66 | * FAD[7:0] Flash Multiplexed Address/Data Bus 67 | * FA[2:0] Flash Address Low 68 | * 69 | * GPIO[15,2] GPIO Port Mode 70 | * GPIO[4:3] Flash Size 71 | * 72 | * 0xd2c Expansion ROM BAR Control 73 | * 0xc08 PCI BAR2 (Flash/NVRAM) Control 74 | * 0x1046c Flash Parameters 75 | */ 76 | int satamv_init(void) 77 | { 78 | struct pci_dev *dev = NULL; 79 | uintptr_t addr; 80 | uint32_t tmp; 81 | 82 | if (rget_io_perms()) 83 | return 1; 84 | 85 | /* BAR0 has all internal registers memory mapped. */ 86 | dev = pcidev_init(satas_mv, PCI_BASE_ADDRESS_0); 87 | if (!dev) 88 | return 1; 89 | 90 | addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0); 91 | if (!addr) 92 | return 1; 93 | 94 | mv_bar = rphysmap("Marvell 88SX7042 registers", addr, 0x20000); 95 | if (mv_bar == ERROR_PTR) 96 | return 1; 97 | 98 | tmp = pci_mmio_readl(mv_bar + FLASH_PARAM); 99 | msg_pspew("Flash Parameters:\n"); 100 | msg_pspew("TurnOff=0x%01x\n", (tmp >> 0) & 0x7); 101 | msg_pspew("Acc2First=0x%01x\n", (tmp >> 3) & 0xf); 102 | msg_pspew("Acc2Next=0x%01x\n", (tmp >> 7) & 0xf); 103 | msg_pspew("ALE2Wr=0x%01x\n", (tmp >> 11) & 0x7); 104 | msg_pspew("WrLow=0x%01x\n", (tmp >> 14) & 0x7); 105 | msg_pspew("WrHigh=0x%01x\n", (tmp >> 17) & 0x7); 106 | msg_pspew("Reserved[21:20]=0x%01x\n", (tmp >> 20) & 0x3); 107 | msg_pspew("TurnOffExt=0x%01x\n", (tmp >> 22) & 0x1); 108 | msg_pspew("Acc2FirstExt=0x%01x\n", (tmp >> 23) & 0x1); 109 | msg_pspew("Acc2NextExt=0x%01x\n", (tmp >> 24) & 0x1); 110 | msg_pspew("ALE2WrExt=0x%01x\n", (tmp >> 25) & 0x1); 111 | msg_pspew("WrLowExt=0x%01x\n", (tmp >> 26) & 0x1); 112 | msg_pspew("WrHighExt=0x%01x\n", (tmp >> 27) & 0x1); 113 | msg_pspew("Reserved[31:28]=0x%01x\n", (tmp >> 28) & 0xf); 114 | 115 | tmp = pci_mmio_readl(mv_bar + EXPANSION_ROM_BAR_CONTROL); 116 | msg_pspew("Expansion ROM BAR Control:\n"); 117 | msg_pspew("ExpROMSz=0x%01x\n", (tmp >> 19) & 0x7); 118 | 119 | /* Enable BAR2 mapping to flash */ 120 | tmp = pci_mmio_readl(mv_bar + PCI_BAR2_CONTROL); 121 | msg_pspew("PCI BAR2 (Flash/NVRAM) Control:\n"); 122 | msg_pspew("Bar2En=0x%01x\n", (tmp >> 0) & 0x1); 123 | msg_pspew("BAR2TransAttr=0x%01x\n", (tmp >> 1) & 0x1f); 124 | msg_pspew("BAR2Sz=0x%01x\n", (tmp >> 19) & 0x7); 125 | tmp &= 0xffffffc0; 126 | tmp |= 0x0000001f; 127 | pci_rmmio_writel(tmp, mv_bar + PCI_BAR2_CONTROL); 128 | 129 | /* Enable flash: GPIO Port Control Register 0x104f0 */ 130 | tmp = pci_mmio_readl(mv_bar + GPIO_PORT_CONTROL); 131 | msg_pspew("GPIOPortMode=0x%01x\n", (tmp >> 0) & 0x3); 132 | if (((tmp >> 0) & 0x3) != 0x2) 133 | msg_pinfo("Warning! Either the straps are incorrect or you " 134 | "have no flash or someone overwrote the strap " 135 | "values!\n"); 136 | tmp &= 0xfffffffc; 137 | tmp |= 0x2; 138 | pci_rmmio_writel(tmp, mv_bar + GPIO_PORT_CONTROL); 139 | 140 | /* Get I/O BAR location. */ 141 | addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_2); 142 | if (!addr) 143 | return 1; 144 | 145 | /* Truncate to reachable range. 146 | * FIXME: Check if the I/O BAR is actually reachable. 147 | * This is an arch specific check. 148 | */ 149 | mv_iobar = addr & 0xffff; 150 | msg_pspew("Activating I/O BAR at 0x%04x\n", mv_iobar); 151 | 152 | /* 512 kByte with two 8-bit latches, and 153 | * 4 MByte with additional 3-bit latch. */ 154 | max_rom_decode.parallel = 4 * 1024 * 1024; 155 | register_par_master(&par_master_satamv, BUS_PARALLEL); 156 | 157 | return 0; 158 | } 159 | 160 | /* BAR2 (MEM) can map NVRAM and flash. We set it to flash in the init function. 161 | * If BAR2 is disabled, it still can be accessed indirectly via BAR1 (I/O). 162 | * This code only supports indirect accesses for now. 163 | */ 164 | 165 | /* Indirect access to via the I/O BAR1. */ 166 | static void satamv_indirect_chip_writeb(uint8_t val, chipaddr addr) 167 | { 168 | /* 0x80000000 selects BAR2 for remapping. */ 169 | OUTL(((uint32_t)addr | 0x80000000) & 0xfffffffc, mv_iobar); 170 | OUTB(val, mv_iobar + 0x80 + (addr & 0x3)); 171 | } 172 | 173 | /* Indirect access to via the I/O BAR1. */ 174 | static uint8_t satamv_indirect_chip_readb(const chipaddr addr) 175 | { 176 | /* 0x80000000 selects BAR2 for remapping. */ 177 | OUTL(((uint32_t)addr | 0x80000000) & 0xfffffffc, mv_iobar); 178 | return INB(mv_iobar + 0x80 + (addr & 0x3)); 179 | } 180 | 181 | /* FIXME: Prefer direct access to BAR2 if BAR2 is active. */ 182 | static void satamv_chip_writeb(const struct flashctx *flash, uint8_t val, 183 | chipaddr addr) 184 | { 185 | satamv_indirect_chip_writeb(val, addr); 186 | } 187 | 188 | /* FIXME: Prefer direct access to BAR2 if BAR2 is active. */ 189 | static uint8_t satamv_chip_readb(const struct flashctx *flash, 190 | const chipaddr addr) 191 | { 192 | return satamv_indirect_chip_readb(addr); 193 | } 194 | 195 | #else 196 | #error PCI port I/O access is not supported on this architecture yet. 197 | #endif 198 | -------------------------------------------------------------------------------- /wbsio_spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2008 Peter Stuge 5 | * Copyright (C) 2009,2010 Carl-Daniel Hailfinger 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; version 2 of the License. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #if defined(__i386__) || defined(__x86_64__) 22 | 23 | #include "flash.h" 24 | #include "chipdrivers.h" 25 | #include "programmer.h" 26 | #include "hwaccess.h" 27 | #include "spi.h" 28 | 29 | #define WBSIO_PORT1 0x2e 30 | #define WBSIO_PORT2 0x4e 31 | 32 | static uint16_t wbsio_spibase = 0; 33 | 34 | static uint16_t wbsio_get_spibase(uint16_t port) 35 | { 36 | uint8_t id; 37 | uint16_t flashport = 0; 38 | 39 | w836xx_ext_enter(port); 40 | id = sio_read(port, 0x20); 41 | if (id != 0xa0) { 42 | msg_perr("\nW83627 not found at 0x%x, id=0x%02x want=0xa0.\n", port, id); 43 | goto done; 44 | } 45 | 46 | if (0 == (sio_read(port, 0x24) & 2)) { 47 | msg_perr("\nW83627 found at 0x%x, but SPI pins are not enabled. (CR[0x24] bit 1=0)\n", port); 48 | goto done; 49 | } 50 | 51 | sio_write(port, 0x07, 0x06); 52 | if (0 == (sio_read(port, 0x30) & 1)) { 53 | msg_perr("\nW83627 found at 0x%x, but SPI is not enabled. (LDN6[0x30] bit 0=0)\n", port); 54 | goto done; 55 | } 56 | 57 | flashport = (sio_read(port, 0x62) << 8) | sio_read(port, 0x63); 58 | 59 | done: 60 | w836xx_ext_leave(port); 61 | return flashport; 62 | } 63 | 64 | static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt, 65 | unsigned int readcnt, 66 | const unsigned char *writearr, 67 | unsigned char *readarr); 68 | static int wbsio_spi_read(struct flashctx *flash, uint8_t *buf, 69 | unsigned int start, unsigned int len); 70 | 71 | static const struct spi_master spi_master_wbsio = { 72 | .type = SPI_CONTROLLER_WBSIO, 73 | .max_data_read = MAX_DATA_UNSPECIFIED, 74 | .max_data_write = MAX_DATA_UNSPECIFIED, 75 | .command = wbsio_spi_send_command, 76 | .multicommand = default_spi_send_multicommand, 77 | .read = wbsio_spi_read, 78 | .write_256 = spi_chip_write_1, 79 | .write_aai = default_spi_write_aai, 80 | }; 81 | 82 | int wbsio_check_for_spi(void) 83 | { 84 | if (0 == (wbsio_spibase = wbsio_get_spibase(WBSIO_PORT1))) 85 | if (0 == (wbsio_spibase = wbsio_get_spibase(WBSIO_PORT2))) 86 | return 1; 87 | 88 | msg_pspew("\nwbsio_spibase = 0x%x\n", wbsio_spibase); 89 | 90 | msg_pdbg("%s: Winbond saved on 4 register bits so max chip size is " 91 | "1024 kB!\n", __func__); 92 | max_rom_decode.spi = 1024 * 1024; 93 | register_spi_master(&spi_master_wbsio); 94 | 95 | return 0; 96 | } 97 | 98 | /* W83627DHG has 11 command modes: 99 | * 1=1 command only 100 | * 2=1 command+1 data write 101 | * 3=1 command+2 data read 102 | * 4=1 command+3 address 103 | * 5=1 command+3 address+1 data write 104 | * 6=1 command+3 address+4 data write 105 | * 7=1 command+3 address+1 dummy address inserted by wbsio+4 data read 106 | * 8=1 command+3 address+1 data read 107 | * 9=1 command+3 address+2 data read 108 | * a=1 command+3 address+3 data read 109 | * b=1 command+3 address+4 data read 110 | * 111 | * mode[7:4] holds the command mode 112 | * mode[3:0] holds SPI address bits [19:16] 113 | * 114 | * The Winbond SPI master only supports 20 bit addresses on the SPI bus. :\ 115 | * Would one more byte of RAM in the chip (to get all 24 bits) really make 116 | * such a big difference? 117 | */ 118 | static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt, 119 | unsigned int readcnt, 120 | const unsigned char *writearr, 121 | unsigned char *readarr) 122 | { 123 | int i; 124 | uint8_t mode = 0; 125 | 126 | msg_pspew("%s:", __func__); 127 | 128 | if (1 == writecnt && 0 == readcnt) { 129 | mode = 0x10; 130 | } else if (2 == writecnt && 0 == readcnt) { 131 | OUTB(writearr[1], wbsio_spibase + 4); 132 | msg_pspew(" data=0x%02x", writearr[1]); 133 | mode = 0x20; 134 | } else if (1 == writecnt && 2 == readcnt) { 135 | mode = 0x30; 136 | } else if (4 == writecnt && 0 == readcnt) { 137 | msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f)); 138 | for (i = 2; i < writecnt; i++) { 139 | OUTB(writearr[i], wbsio_spibase + i); 140 | msg_pspew("%02x", writearr[i]); 141 | } 142 | mode = 0x40 | (writearr[1] & 0x0f); 143 | } else if (5 == writecnt && 0 == readcnt) { 144 | msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f)); 145 | for (i = 2; i < 4; i++) { 146 | OUTB(writearr[i], wbsio_spibase + i); 147 | msg_pspew("%02x", writearr[i]); 148 | } 149 | OUTB(writearr[i], wbsio_spibase + i); 150 | msg_pspew(" data=0x%02x", writearr[i]); 151 | mode = 0x50 | (writearr[1] & 0x0f); 152 | } else if (8 == writecnt && 0 == readcnt) { 153 | msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f)); 154 | for (i = 2; i < 4; i++) { 155 | OUTB(writearr[i], wbsio_spibase + i); 156 | msg_pspew("%02x", writearr[i]); 157 | } 158 | msg_pspew(" data=0x"); 159 | for (; i < writecnt; i++) { 160 | OUTB(writearr[i], wbsio_spibase + i); 161 | msg_pspew("%02x", writearr[i]); 162 | } 163 | mode = 0x60 | (writearr[1] & 0x0f); 164 | } else if (5 == writecnt && 4 == readcnt) { 165 | /* XXX: TODO not supported by flashrom infrastructure! 166 | * This mode, 7, discards the fifth byte in writecnt, 167 | * but since we can not express that in flashrom, fail 168 | * the operation for now. 169 | */ 170 | ; 171 | } else if (4 == writecnt && readcnt >= 1 && readcnt <= 4) { 172 | msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f)); 173 | for (i = 2; i < writecnt; i++) { 174 | OUTB(writearr[i], wbsio_spibase + i); 175 | msg_pspew("%02x", writearr[i]); 176 | } 177 | mode = ((7 + readcnt) << 4) | (writearr[1] & 0x0f); 178 | } 179 | msg_pspew(" cmd=%02x mode=%02x\n", writearr[0], mode); 180 | 181 | if (!mode) { 182 | msg_perr("%s: unsupported command type wr=%d rd=%d\n", 183 | __func__, writecnt, readcnt); 184 | /* Command type refers to the number of bytes read/written. */ 185 | return SPI_INVALID_LENGTH; 186 | } 187 | 188 | OUTB(writearr[0], wbsio_spibase); 189 | OUTB(mode, wbsio_spibase + 1); 190 | programmer_delay(10); 191 | 192 | if (!readcnt) 193 | return 0; 194 | 195 | msg_pspew("%s: returning data =", __func__); 196 | for (i = 0; i < readcnt; i++) { 197 | readarr[i] = INB(wbsio_spibase + 4 + i); 198 | msg_pspew(" 0x%02x", readarr[i]); 199 | } 200 | msg_pspew("\n"); 201 | return 0; 202 | } 203 | 204 | static int wbsio_spi_read(struct flashctx *flash, uint8_t *buf, 205 | unsigned int start, unsigned int len) 206 | { 207 | mmio_readn((void *)(flash->virtual_memory + start), buf, len); 208 | return 0; 209 | } 210 | 211 | #endif 212 | -------------------------------------------------------------------------------- /82802ab.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2000 Silicon Integrated System Corporation 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * Datasheet: 23 | * - Name: Intel 82802AB/82802AC Firmware Hub (FWH) 24 | * - URL: http://www.intel.com/design/chipsets/datashts/290658.htm 25 | * - PDF: http://download.intel.com/design/chipsets/datashts/29065804.pdf 26 | * - Order number: 290658-004 27 | */ 28 | 29 | #include "flash.h" 30 | #include "chipdrivers.h" 31 | 32 | void print_status_82802ab(uint8_t status) 33 | { 34 | msg_cdbg("%s", status & 0x80 ? "Ready:" : "Busy:"); 35 | msg_cdbg("%s", status & 0x40 ? "BE SUSPEND:" : "BE RUN/FINISH:"); 36 | msg_cdbg("%s", status & 0x20 ? "BE ERROR:" : "BE OK:"); 37 | msg_cdbg("%s", status & 0x10 ? "PROG ERR:" : "PROG OK:"); 38 | msg_cdbg("%s", status & 0x8 ? "VP ERR:" : "VPP OK:"); 39 | msg_cdbg("%s", status & 0x4 ? "PROG SUSPEND:" : "PROG RUN/FINISH:"); 40 | msg_cdbg("%s", status & 0x2 ? "WP|TBL#|WP#,ABORT:" : "UNLOCK:"); 41 | } 42 | 43 | int probe_82802ab(struct flashctx *flash) 44 | { 45 | chipaddr bios = flash->virtual_memory; 46 | uint8_t id1, id2, flashcontent1, flashcontent2; 47 | int shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED) ? 1 : 0; 48 | 49 | /* Reset to get a clean state */ 50 | chip_writeb(flash, 0xFF, bios); 51 | programmer_delay(10); 52 | 53 | /* Enter ID mode */ 54 | chip_writeb(flash, 0x90, bios); 55 | programmer_delay(10); 56 | 57 | id1 = chip_readb(flash, bios + (0x00 << shifted)); 58 | id2 = chip_readb(flash, bios + (0x01 << shifted)); 59 | 60 | /* Leave ID mode */ 61 | chip_writeb(flash, 0xFF, bios); 62 | 63 | programmer_delay(10); 64 | 65 | msg_cdbg("%s: id1 0x%02x, id2 0x%02x", __func__, id1, id2); 66 | 67 | if (!oddparity(id1)) 68 | msg_cdbg(", id1 parity violation"); 69 | 70 | /* 71 | * Read the product ID location again. We should now see normal 72 | * flash contents. 73 | */ 74 | flashcontent1 = chip_readb(flash, bios + (0x00 << shifted)); 75 | flashcontent2 = chip_readb(flash, bios + (0x01 << shifted)); 76 | 77 | if (id1 == flashcontent1) 78 | msg_cdbg(", id1 is normal flash content"); 79 | if (id2 == flashcontent2) 80 | msg_cdbg(", id2 is normal flash content"); 81 | 82 | msg_cdbg("\n"); 83 | if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id) 84 | return 0; 85 | 86 | return 1; 87 | } 88 | 89 | /* FIXME: needs timeout */ 90 | uint8_t wait_82802ab(struct flashctx *flash) 91 | { 92 | uint8_t status; 93 | chipaddr bios = flash->virtual_memory; 94 | 95 | chip_writeb(flash, 0x70, bios); 96 | if ((chip_readb(flash, bios) & 0x80) == 0) { // it's busy 97 | while ((chip_readb(flash, bios) & 0x80) == 0) ; 98 | } 99 | 100 | status = chip_readb(flash, bios); 101 | 102 | /* Reset to get a clean state */ 103 | chip_writeb(flash, 0xFF, bios); 104 | 105 | return status; 106 | } 107 | 108 | int erase_block_82802ab(struct flashctx *flash, unsigned int page, 109 | unsigned int pagesize) 110 | { 111 | chipaddr bios = flash->virtual_memory; 112 | uint8_t status; 113 | 114 | // clear status register 115 | chip_writeb(flash, 0x50, bios + page); 116 | 117 | // now start it 118 | chip_writeb(flash, 0x20, bios + page); 119 | chip_writeb(flash, 0xd0, bios + page); 120 | programmer_delay(10); 121 | 122 | // now let's see what the register is 123 | status = wait_82802ab(flash); 124 | print_status_82802ab(status); 125 | 126 | /* FIXME: Check the status register for errors. */ 127 | return 0; 128 | } 129 | 130 | /* chunksize is 1 */ 131 | int write_82802ab(struct flashctx *flash, const uint8_t *src, unsigned int start, unsigned int len) 132 | { 133 | int i; 134 | chipaddr dst = flash->virtual_memory + start; 135 | 136 | for (i = 0; i < len; i++) { 137 | /* transfer data from source to destination */ 138 | chip_writeb(flash, 0x40, dst); 139 | chip_writeb(flash, *src++, dst++); 140 | wait_82802ab(flash); 141 | } 142 | 143 | /* FIXME: Ignore errors for now. */ 144 | return 0; 145 | } 146 | 147 | int unlock_28f004s5(struct flashctx *flash) 148 | { 149 | chipaddr bios = flash->virtual_memory; 150 | uint8_t mcfg, bcfg, need_unlock = 0, can_unlock = 0; 151 | int i; 152 | 153 | /* Clear status register */ 154 | chip_writeb(flash, 0x50, bios); 155 | 156 | /* Read identifier codes */ 157 | chip_writeb(flash, 0x90, bios); 158 | 159 | /* Read master lock-bit */ 160 | mcfg = chip_readb(flash, bios + 0x3); 161 | msg_cdbg("master lock is "); 162 | if (mcfg) { 163 | msg_cdbg("locked!\n"); 164 | } else { 165 | msg_cdbg("unlocked!\n"); 166 | can_unlock = 1; 167 | } 168 | 169 | /* Read block lock-bits */ 170 | for (i = 0; i < flash->chip->total_size * 1024; i+= (64 * 1024)) { 171 | bcfg = chip_readb(flash, bios + i + 2); // read block lock config 172 | msg_cdbg("block lock at %06x is %slocked!\n", i, bcfg ? "" : "un"); 173 | if (bcfg) { 174 | need_unlock = 1; 175 | } 176 | } 177 | 178 | /* Reset chip */ 179 | chip_writeb(flash, 0xFF, bios); 180 | 181 | /* Unlock: clear block lock-bits, if needed */ 182 | if (can_unlock && need_unlock) { 183 | msg_cdbg("Unlock: "); 184 | chip_writeb(flash, 0x60, bios); 185 | chip_writeb(flash, 0xD0, bios); 186 | chip_writeb(flash, 0xFF, bios); 187 | msg_cdbg("Done!\n"); 188 | } 189 | 190 | /* Error: master locked or a block is locked */ 191 | if (!can_unlock && need_unlock) { 192 | msg_cerr("At least one block is locked and lockdown is active!\n"); 193 | return -1; 194 | } 195 | 196 | return 0; 197 | } 198 | 199 | int unlock_lh28f008bjt(struct flashctx *flash) 200 | { 201 | chipaddr bios = flash->virtual_memory; 202 | uint8_t mcfg, bcfg; 203 | uint8_t need_unlock = 0, can_unlock = 0; 204 | int i; 205 | 206 | /* Wait if chip is busy */ 207 | wait_82802ab(flash); 208 | 209 | /* Read identifier codes */ 210 | chip_writeb(flash, 0x90, bios); 211 | 212 | /* Read master lock-bit */ 213 | mcfg = chip_readb(flash, bios + 0x3); 214 | msg_cdbg("master lock is "); 215 | if (mcfg) { 216 | msg_cdbg("locked!\n"); 217 | } else { 218 | msg_cdbg("unlocked!\n"); 219 | can_unlock = 1; 220 | } 221 | 222 | /* Read block lock-bits, 8 * 8 KB + 15 * 64 KB */ 223 | for (i = 0; i < flash->chip->total_size * 1024; 224 | i += (i >= (64 * 1024) ? 64 * 1024 : 8 * 1024)) { 225 | bcfg = chip_readb(flash, bios + i + 2); /* read block lock config */ 226 | msg_cdbg("block lock at %06x is %slocked!\n", i, 227 | bcfg ? "" : "un"); 228 | if (bcfg) 229 | need_unlock = 1; 230 | } 231 | 232 | /* Reset chip */ 233 | chip_writeb(flash, 0xFF, bios); 234 | 235 | /* Unlock: clear block lock-bits, if needed */ 236 | if (can_unlock && need_unlock) { 237 | msg_cdbg("Unlock: "); 238 | chip_writeb(flash, 0x60, bios); 239 | chip_writeb(flash, 0xD0, bios); 240 | chip_writeb(flash, 0xFF, bios); 241 | wait_82802ab(flash); 242 | msg_cdbg("Done!\n"); 243 | } 244 | 245 | /* Error: master locked or a block is locked */ 246 | if (!can_unlock && need_unlock) { 247 | msg_cerr("At least one block is locked and lockdown is active!\n"); 248 | return -1; 249 | } 250 | 251 | return 0; 252 | } 253 | -------------------------------------------------------------------------------- /util/ich_descriptors_tool/ich_descriptors_tool.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2010 Matthias Wenzel 5 | * Copyright (C) 2011 Stefan Tauner 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /* 23 | * dump information and binaries from BIOS images that are in descriptor mode 24 | */ 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include "ich_descriptors.h" 35 | /* Some DJGPP builds define __unix__ although they don't support mmap(). 36 | * Cygwin defines __unix__ and supports mmap(), but it does not work well. 37 | */ 38 | #if !defined(__MSDOS__) && !defined(_WIN32) && (defined(unix) || defined(__unix__) || defined(__unix)) || (defined(__MACH__) && defined(__APPLE__)) 39 | #define HAVE_MMAP 1 40 | #include 41 | #endif 42 | 43 | static void dump_file(const char *prefix, const uint32_t *dump, unsigned int len, struct ich_desc_region *reg, unsigned int i) 44 | { 45 | int ret; 46 | char *fn; 47 | const char *reg_name; 48 | uint32_t file_len; 49 | const char *const region_names[5] = { 50 | "Descriptor", "BIOS", "ME", "GbE", "Platform" 51 | }; 52 | uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]); 53 | uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]); 54 | 55 | reg_name = region_names[i]; 56 | if (base > limit) { 57 | printf("The %s region is unused and thus not dumped.\n", reg_name); 58 | return; 59 | } 60 | 61 | limit = limit | 0x0fff; 62 | file_len = limit + 1 - base; 63 | if (base + file_len > len) { 64 | printf("The %s region is spanning 0x%08x-0x%08x, but it is " 65 | "not (fully) included in the image (0-0x%08x), thus not " 66 | "dumped.\n", reg_name, base, limit, len - 1); 67 | return; 68 | } 69 | 70 | fn = malloc(strlen(prefix) + strlen(reg_name) + strlen(".bin") + 2); 71 | if (!fn) { 72 | fprintf(stderr, "Out of memory!\n"); 73 | exit(1); 74 | } 75 | snprintf(fn, strlen(prefix) + strlen(reg_name) + strlen(".bin") + 2, 76 | "%s.%s.bin", prefix, reg_name); 77 | printf("Dumping %u bytes of the %s region from 0x%08x-0x%08x to %s... ", 78 | file_len, region_names[i], base, limit, fn); 79 | int fh = open(fn, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); 80 | if (fh < 0) { 81 | fprintf(stderr, 82 | "ERROR: couldn't open(%s): %s\n", fn, strerror(errno)); 83 | free(fn); 84 | exit(1); 85 | } 86 | free(fn); 87 | 88 | ret = write(fh, &dump[base >> 2], file_len); 89 | if (ret != file_len) { 90 | fprintf(stderr, "FAILED.\n"); 91 | exit(1); 92 | } 93 | 94 | printf("done.\n"); 95 | close(fh); 96 | } 97 | 98 | void dump_files(const char *name, const uint32_t *buf, unsigned int len, struct ich_desc_region *reg) 99 | { 100 | unsigned int i; 101 | printf("=== Dumping region files ===\n"); 102 | for (i = 0; i < 5; i++) 103 | dump_file(name, buf, len, reg, i); 104 | printf("\n"); 105 | } 106 | 107 | static void usage(char *argv[], char *error) 108 | { 109 | if (error != NULL) { 110 | fprintf(stderr, "%s\n", error); 111 | } 112 | printf("usage: '%s -f [-c ] [-d]'\n\n" 113 | "where points to an image of the contents of the SPI flash.\n" 114 | "In case the image is really in descriptor mode %s\n" 115 | "will pretty print some of the contained information.\n" 116 | "To also print the data stored in the descriptor straps you have to indicate\n" 117 | "the chipset series with the '-c' parameter and one of the possible arguments:\n" 118 | "\t- \"ich8\",\n" 119 | "\t- \"ich9\",\n" 120 | "\t- \"ich10\",\n" 121 | "\t- \"silvermont\" for chipsets from Intel's Silvermont architecture (e.g. Bay Trail),\n" 122 | "\t- \"5\" or \"ibex\" for Intel's 5 series chipsets,\n" 123 | "\t- \"6\" or \"cougar\" for Intel's 6 series chipsets,\n" 124 | "\t- \"7\" or \"panther\" for Intel's 7 series chipsets.\n" 125 | "\t- \"8\" or \"lynx\" for Intel's 8 series chipsets.\n" 126 | "\t- \"9\" or \"wildcat\" for Intel's 9 series chipsets.\n" 127 | "If '-d' is specified some regions such as the BIOS image as seen by the CPU or\n" 128 | "the GbE blob that is required to initialize the GbE are also dumped to files.\n", 129 | argv[0], argv[0]); 130 | exit(1); 131 | } 132 | 133 | int main(int argc, char *argv[]) 134 | { 135 | int fd; /* file descriptor to flash file */ 136 | int len; /* file/buffer size in bytes */ 137 | uint32_t *buf; /* mmap'd file */ 138 | uint8_t *pMAC; 139 | int opt, ret; 140 | 141 | int dump = 0; 142 | const char *fn = NULL; 143 | const char *csn = NULL; 144 | enum ich_chipset cs = CHIPSET_ICH_UNKNOWN; 145 | struct ich_descriptors desc = {{ 0 }}; 146 | 147 | while ((opt = getopt(argc, argv, "df:c:")) != -1) { 148 | switch (opt) { 149 | case 'd': 150 | dump = 1; 151 | break; 152 | case 'f': 153 | fn = optarg; 154 | break; 155 | case 'c': 156 | csn = optarg; 157 | break; 158 | default: /* '?' */ 159 | usage(argv, NULL); 160 | } 161 | } 162 | if (fn == NULL) 163 | usage(argv, "Need the file name of a descriptor image to read from."); 164 | 165 | fd = open(fn, O_RDONLY); 166 | if (fd < 0) 167 | usage(argv, "No such file"); 168 | len = lseek(fd, 0, SEEK_END); 169 | if (len < 0) 170 | usage(argv, "Seeking to the end of the file failed"); 171 | 172 | #ifdef HAVE_MMAP 173 | buf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); 174 | if (buf == (void *) -1) 175 | #endif 176 | { 177 | /* fallback for stupid OSes like cygwin */ 178 | buf = malloc(len); 179 | if (!buf) 180 | usage(argv, "Could not allocate memory"); 181 | lseek(fd, 0, SEEK_SET); 182 | if (len != read(fd, buf, len)) 183 | usage(argv, "Seeking to the end of the file failed"); 184 | } 185 | printf("The flash image has a size of %d [0x%x] bytes.\n", len, len); 186 | close(fd); 187 | 188 | if (csn != NULL) { 189 | if (strcmp(csn, "ich8") == 0) 190 | cs = CHIPSET_ICH8; 191 | else if (strcmp(csn, "ich9") == 0) 192 | cs = CHIPSET_ICH9; 193 | else if (strcmp(csn, "ich10") == 0) 194 | cs = CHIPSET_ICH10; 195 | else if ((strcmp(csn, "5") == 0) || 196 | (strcmp(csn, "ibex") == 0)) 197 | cs = CHIPSET_5_SERIES_IBEX_PEAK; 198 | else if ((strcmp(csn, "6") == 0) || 199 | (strcmp(csn, "cougar") == 0)) 200 | cs = CHIPSET_6_SERIES_COUGAR_POINT; 201 | else if ((strcmp(csn, "7") == 0) || 202 | (strcmp(csn, "panther") == 0)) 203 | cs = CHIPSET_7_SERIES_PANTHER_POINT; 204 | else if ((strcmp(csn, "8") == 0) || 205 | (strcmp(csn, "lynx") == 0)) 206 | cs = CHIPSET_8_SERIES_LYNX_POINT; 207 | else if ((strcmp(csn, "silvermont") == 0)) 208 | cs = CHIPSET_BAYTRAIL; 209 | else if ((strcmp(csn, "9") == 0) || 210 | (strcmp(csn, "wildcat") == 0)) 211 | cs = CHIPSET_9_SERIES_WILDCAT_POINT; 212 | } 213 | 214 | ret = read_ich_descriptors_from_dump(buf, len, &desc); 215 | switch (ret) { 216 | case ICH_RET_OK: 217 | break; 218 | case ICH_RET_ERR: 219 | printf("Image not in descriptor mode.\n"); 220 | exit(1); 221 | case ICH_RET_OOB: 222 | printf("Tried to access a location out of bounds of the image. - Corrupt image?\n"); 223 | exit(1); 224 | default: 225 | printf("Unhandled return value at %s:%u, please report this.\n", 226 | __FILE__, __LINE__); 227 | exit(1); 228 | } 229 | 230 | prettyprint_ich_descriptors(cs, &desc); 231 | 232 | pMAC = (uint8_t *) &buf[ICH_FREG_BASE(desc.region.reg3_base) >> 2]; 233 | if (len >= ICH_FREG_BASE(desc.region.reg3_base) + 5 && pMAC[0] != 0xff) 234 | printf("The MAC address might be at offset 0x%x: " 235 | "%02x:%02x:%02x:%02x:%02x:%02x\n", 236 | ICH_FREG_BASE(desc.region.reg3_base), 237 | pMAC[0], pMAC[1], pMAC[2], pMAC[3], pMAC[4], pMAC[5]); 238 | 239 | if (dump == 1) 240 | dump_files(fn, buf, len, &desc.region); 241 | 242 | return 0; 243 | } 244 | -------------------------------------------------------------------------------- /rayer_spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the flashrom project. 3 | * 4 | * Copyright (C) 2009,2010 Carl-Daniel Hailfinger 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; version 2 of the License. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | /* Driver for various LPT adapters. 21 | * 22 | * This driver uses non-portable direct I/O port accesses which won't work on 23 | * any non-x86 platform, and even on x86 there is a high chance there will be 24 | * collisions with any loaded parallel port drivers. 25 | * The big advantage of direct port I/O is OS independence and speed because 26 | * most OS parport drivers will perform many unnecessary accesses although 27 | * this driver just treats the parallel port as a GPIO set. 28 | */ 29 | #if defined(__i386__) || defined(__x86_64__) 30 | 31 | #include 32 | #include 33 | #include 34 | #include "flash.h" 35 | #include "programmer.h" 36 | #include "hwaccess.h" 37 | 38 | /* We have two sets of pins, out and in. The numbers for both sets are 39 | * independent and are bitshift values, not real pin numbers. 40 | * Default settings are for the RayeR hardware. 41 | */ 42 | 43 | struct rayer_programmer { 44 | const char *type; 45 | const enum test_state status; 46 | const char *description; 47 | const void *dev_data; 48 | }; 49 | 50 | struct rayer_pinout { 51 | uint8_t cs_bit; 52 | uint8_t sck_bit; 53 | uint8_t mosi_bit; 54 | uint8_t miso_bit; 55 | void (*preinit)(const void *); 56 | int (*shutdown)(void *); 57 | }; 58 | 59 | static const struct rayer_pinout rayer_spipgm = { 60 | .cs_bit = 5, 61 | .sck_bit = 6, 62 | .mosi_bit = 7, 63 | .miso_bit = 6, 64 | }; 65 | 66 | static void dlc5_preinit(const void *); 67 | static int dlc5_shutdown(void *); 68 | 69 | static const struct rayer_pinout xilinx_dlc5 = { 70 | .cs_bit = 2, 71 | .sck_bit = 1, 72 | .mosi_bit = 0, 73 | .miso_bit = 4, 74 | .preinit = dlc5_preinit, 75 | .shutdown = dlc5_shutdown, 76 | }; 77 | 78 | static void byteblaster_preinit(const void *); 79 | static int byteblaster_shutdown(void *); 80 | 81 | static const struct rayer_pinout altera_byteblastermv = { 82 | .cs_bit = 1, 83 | .sck_bit = 0, 84 | .mosi_bit = 6, 85 | .miso_bit = 7, 86 | .preinit = byteblaster_preinit, 87 | .shutdown = byteblaster_shutdown, 88 | }; 89 | 90 | static void stk200_preinit(const void *); 91 | static int stk200_shutdown(void *); 92 | 93 | static const struct rayer_pinout atmel_stk200 = { 94 | .cs_bit = 7, 95 | .sck_bit = 4, 96 | .mosi_bit = 5, 97 | .miso_bit = 6, 98 | .preinit = stk200_preinit, 99 | .shutdown = stk200_shutdown, 100 | }; 101 | 102 | static const struct rayer_pinout wiggler_lpt = { 103 | .cs_bit = 1, 104 | .sck_bit = 2, 105 | .mosi_bit = 3, 106 | .miso_bit = 7, 107 | }; 108 | 109 | static const struct rayer_programmer rayer_spi_types[] = { 110 | {"rayer", NT, "RayeR SPIPGM", &rayer_spipgm}, 111 | {"xilinx", NT, "Xilinx Parallel Cable III (DLC 5)", &xilinx_dlc5}, 112 | {"byteblastermv", OK, "Altera ByteBlasterMV", &altera_byteblastermv}, 113 | {"stk200", NT, "Atmel STK200/300 adapter", &atmel_stk200}, 114 | {"wiggler", OK, "Wiggler LPT", &wiggler_lpt}, 115 | {0}, 116 | }; 117 | 118 | static const struct rayer_pinout *pinout = NULL; 119 | 120 | static uint16_t lpt_iobase; 121 | 122 | /* Cached value of last byte sent. */ 123 | static uint8_t lpt_outbyte; 124 | 125 | static void rayer_bitbang_set_cs(int val) 126 | { 127 | lpt_outbyte &= ~(1 << pinout->cs_bit); 128 | lpt_outbyte |= (val << pinout->cs_bit); 129 | OUTB(lpt_outbyte, lpt_iobase); 130 | } 131 | 132 | static void rayer_bitbang_set_sck(int val) 133 | { 134 | lpt_outbyte &= ~(1 << pinout->sck_bit); 135 | lpt_outbyte |= (val << pinout->sck_bit); 136 | OUTB(lpt_outbyte, lpt_iobase); 137 | } 138 | 139 | static void rayer_bitbang_set_mosi(int val) 140 | { 141 | lpt_outbyte &= ~(1 << pinout->mosi_bit); 142 | lpt_outbyte |= (val << pinout->mosi_bit); 143 | OUTB(lpt_outbyte, lpt_iobase); 144 | } 145 | 146 | static int rayer_bitbang_get_miso(void) 147 | { 148 | uint8_t tmp; 149 | 150 | tmp = INB(lpt_iobase + 1) ^ 0x80; // bit.7 inverted 151 | tmp = (tmp >> pinout->miso_bit) & 0x1; 152 | return tmp; 153 | } 154 | 155 | static const struct bitbang_spi_master bitbang_spi_master_rayer = { 156 | .type = BITBANG_SPI_MASTER_RAYER, 157 | .set_cs = rayer_bitbang_set_cs, 158 | .set_sck = rayer_bitbang_set_sck, 159 | .set_mosi = rayer_bitbang_set_mosi, 160 | .get_miso = rayer_bitbang_get_miso, 161 | .half_period = 0, 162 | }; 163 | 164 | int rayer_spi_init(void) 165 | { 166 | const struct rayer_programmer *prog = rayer_spi_types; 167 | char *arg = NULL; 168 | 169 | /* Non-default port requested? */ 170 | arg = extract_programmer_param("iobase"); 171 | if (arg) { 172 | char *endptr = NULL; 173 | unsigned long tmp; 174 | tmp = strtoul(arg, &endptr, 0); 175 | /* Port 0, port >0x10000, unaligned ports and garbage strings 176 | * are rejected. 177 | */ 178 | if (!tmp || (tmp >= 0x10000) || (tmp & 0x3) || 179 | (*endptr != '\0')) { 180 | /* Using ports below 0x100 is a really bad idea, and 181 | * should only be done if no port between 0x100 and 182 | * 0xfffc works due to routing issues. 183 | */ 184 | msg_perr("Error: iobase= specified, but the I/O base " 185 | "given was invalid.\nIt must be a multiple of " 186 | "0x4 and lie between 0x100 and 0xfffc.\n"); 187 | free(arg); 188 | return 1; 189 | } else { 190 | lpt_iobase = (uint16_t)tmp; 191 | msg_pinfo("Non-default I/O base requested. This will " 192 | "not change the hardware settings.\n"); 193 | } 194 | } else { 195 | /* Pick a default value for the I/O base. */ 196 | lpt_iobase = 0x378; 197 | } 198 | free(arg); 199 | 200 | msg_pdbg("Using address 0x%x as I/O base for parallel port access.\n", 201 | lpt_iobase); 202 | 203 | arg = extract_programmer_param("type"); 204 | if (arg) { 205 | for (; prog->type != NULL; prog++) { 206 | if (strcasecmp(arg, prog->type) == 0) { 207 | break; 208 | } 209 | } 210 | if (prog->type == NULL) { 211 | msg_perr("Error: Invalid device type specified.\n"); 212 | free(arg); 213 | return 1; 214 | } 215 | free(arg); 216 | } 217 | msg_pinfo("Using %s pinout.\n", prog->description); 218 | pinout = (struct rayer_pinout *)prog->dev_data; 219 | 220 | if (rget_io_perms()) 221 | return 1; 222 | 223 | /* Get the initial value before writing to any line. */ 224 | lpt_outbyte = INB(lpt_iobase); 225 | 226 | if (pinout->shutdown) 227 | register_shutdown(pinout->shutdown, (void*)pinout); 228 | if (pinout->preinit) 229 | pinout->preinit(pinout); 230 | 231 | if (register_spi_bitbang_master(&bitbang_spi_master_rayer)) 232 | return 1; 233 | 234 | return 0; 235 | } 236 | 237 | static void byteblaster_preinit(const void *data){ 238 | msg_pdbg("byteblaster_preinit\n"); 239 | /* Assert #EN signal. */ 240 | OUTB(2, lpt_iobase + 2 ); 241 | } 242 | 243 | static int byteblaster_shutdown(void *data){ 244 | msg_pdbg("byteblaster_shutdown\n"); 245 | /* De-Assert #EN signal. */ 246 | OUTB(0, lpt_iobase + 2 ); 247 | return 0; 248 | } 249 | 250 | static void stk200_preinit(const void *data) { 251 | msg_pdbg("stk200_init\n"); 252 | /* Assert #EN signals, set LED signal. */ 253 | lpt_outbyte = (1 << 6) ; 254 | OUTB(lpt_outbyte, lpt_iobase); 255 | } 256 | 257 | static int stk200_shutdown(void *data) { 258 | msg_pdbg("stk200_shutdown\n"); 259 | /* Assert #EN signals, clear LED signal. */ 260 | lpt_outbyte = (1 << 2) | (1 << 3); 261 | OUTB(lpt_outbyte, lpt_iobase); 262 | return 0; 263 | } 264 | 265 | static void dlc5_preinit(const void *data) { 266 | msg_pdbg("dlc5_preinit\n"); 267 | /* Assert pin 6 to receive MISO. */ 268 | lpt_outbyte |= (1<<4); 269 | OUTB(lpt_outbyte, lpt_iobase); 270 | } 271 | 272 | static int dlc5_shutdown(void *data) { 273 | msg_pdbg("dlc5_shutdown\n"); 274 | /* De-assert pin 6 to force MISO low. */ 275 | lpt_outbyte &= ~(1<<4); 276 | OUTB(lpt_outbyte, lpt_iobase); 277 | return 0; 278 | } 279 | 280 | #else 281 | #error PCI port I/O access is not supported on this architecture yet. 282 | #endif 283 | --------------------------------------------------------------------------------