diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b678326e8..80ca6d64f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install build dependencies run: | @@ -23,16 +23,22 @@ jobs: sudo apt-get install -y git build-essential debhelper pkg-config libpci-dev libusb-1.0-0-dev libftdi1-dev meson - name: Build Flashrom - run: make + run: | + meson setup builddir + meson compile -C builddir + + - name: Test Flashrom + run: | + meson test -C builddir - name: Save Flashrom binary as artifact run: | mkdir artifacts - mv flashrom artifacts/ + mv builddir/flashrom artifacts/ continue-on-error: true # Allow workflow to continue even if 'flashrom' doesn't exist - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: flashrom-artifact path: artifacts/ diff --git a/.gitignore b/.gitignore index 8a32a701d..d1cf656d6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ *.d -!Makefile.d/ *.o +/.doctrees /.features /.dependencies /.libdeps @@ -9,8 +9,10 @@ /flashrom-* /flashrom.exe /flashrom.8 +/flashrom.bash /libflashrom.a /libflashrom-doc/ +/man8 /util/ich_descriptors_tool/ich_descriptors_tool /util/ich_descriptors_tool/ich_descriptors_tool.exe diff --git a/82802ab.c b/82802ab.c index 0b4de4976..a440bd45b 100644 --- a/82802ab.c +++ b/82802ab.c @@ -45,11 +45,11 @@ int probe_82802ab(struct flashctx *flash) /* Reset to get a clean state */ chip_writeb(flash, 0xFF, bios); - programmer_delay(10); + programmer_delay(flash, 10); /* Enter ID mode */ chip_writeb(flash, 0x90, bios); - programmer_delay(10); + programmer_delay(flash, 10); id1 = chip_readb(flash, bios + (0x00 << shifted)); id2 = chip_readb(flash, bios + (0x01 << shifted)); @@ -57,7 +57,7 @@ int probe_82802ab(struct flashctx *flash) /* Leave ID mode */ chip_writeb(flash, 0xFF, bios); - programmer_delay(10); + programmer_delay(flash, 10); msg_cdbg("%s: id1 0x%02x, id2 0x%02x", __func__, id1, id2); @@ -114,7 +114,7 @@ int erase_block_82802ab(struct flashctx *flash, unsigned int page, // now start it chip_writeb(flash, 0x20, bios + page); chip_writeb(flash, 0xd0, bios + page); - programmer_delay(10); + programmer_delay(flash, 10); // now let's see what the register is status = wait_82802ab(flash); @@ -142,7 +142,7 @@ int write_82802ab(struct flashctx *flash, const uint8_t *src, unsigned int start return 0; } -int unlock_28f004s5(struct flashctx *flash) +static int unlock_28f004s5(struct flashctx *flash) { chipaddr bios = flash->virtual_memory; uint8_t mcfg, bcfg; @@ -195,7 +195,7 @@ int unlock_28f004s5(struct flashctx *flash) return 0; } -int unlock_lh28f008bjt(struct flashctx *flash) +static int unlock_lh28f008bjt(struct flashctx *flash) { chipaddr bios = flash->virtual_memory; uint8_t mcfg, bcfg; @@ -249,3 +249,12 @@ int unlock_lh28f008bjt(struct flashctx *flash) return 0; } + +blockprotect_func_t *lookup_82802ab_blockprotect_func_ptr(const struct flashchip *const chip) +{ + switch (chip->unlock) { + case UNLOCK_28F004S5: return unlock_28f004s5; + case UNLOCK_LH28F008BJT: return unlock_lh28f008bjt; + default: return NULL; /* fallthough */ + }; +} diff --git a/Documentation/building.md b/Documentation/building.md deleted file mode 100644 index aabb45b18..000000000 --- a/Documentation/building.md +++ /dev/null @@ -1,127 +0,0 @@ -# Compiling from Source with meson (recommended) - -## Dependencies: - - * C compiler (GCC | Clang) * - * meson >=0.53.0 * - * ninja * - * pkg-config * - * cmocka ** - * system-headers *** - * libpci *** - * libusb1 >=1.0.9 *** - * libftdi1 *** - * libjaylink *** - -\* Compile time dependency -\** For unit-testing only -\*** Runtime / Programmer specific - -## Build Options: - * classic_cli=auto/enabled/disabled - * classic_cli_default_programmer=: - * classic_cli_print_wiki=auto/enabled/disabled - * tests=auto/enabled/disabled - * ich_descriptors_tool=auto/enabled/disabled - * use_internal_dmi=true/false - * programmer=... - -## Configure -``` -meson builddir -D -``` -- __builddir__ is the directory in which flashrom will be build -- for all available options see `meson_options.txt` - -## Compile -``` -ninja -C builddir -``` - -## Install -``` -ninja -C builddir install -``` - -## Run unit tests -``` -ninja -C builddir test -``` - -## System specific information -### Ubuntu / Debian (Linux) - * __linux-headers__ are version specific -``` -apt-get install -y gcc meson ninja-build pkg-config libcmocka-dev \ - linux-headers-generic libpci-dev libusb-1.0-0-dev libftdi1-dev \ - libjaylink-dev -``` - -### ArchLinux / Manjaro - * __libjaylink__ is not available through the package manager -``` -pacman -S --noconfirm gcc meson ninja pkg-config cmocka \ - pciutils libusb libftdi -``` - -### NixOS / Nixpkgs -``` -nix-shell /util/shell.nix -``` -or -``` -nix-shell -p meson ninja pkg-config cmocka pciutils libusb1 libftdi1 libjaylink -``` - -### OpenSUSE -``` -zypper install -y gcc meson ninja pkg-config libcmocka-devel \ - pciutils-devel libusb-1_0-devel libftdi1-devel \ - libjaylink-devel -``` - -### Alpine -``` -apk add build-base meson ninja pkgconf cmocka-dev pciutils-dev libusb-dev libftdi1-dev libjaylink-dev linux-headers -``` - - -### Freebsd / DragonFly BSD - * Tests are not working yet and must be disabled with `-Dtests=disabled` - * __libjaylink__ is not available through the package manager - * __libusb1__ is part of the base system -``` -pkg install pkgconf meson ninja cmocka libpci libftdi1 -``` - -### OpenBSD - * Tests are not working yet and must be disabled with `-Dtests=disabled` - * __libjaylink__ is not available through the package manager -``` -pkg_add install meson ninja pkg-config cmocka pciutils libusb1 libftdi1 -``` - -### NetBSD - * Tests are not working yet and must be disabled with `-Dtests=disabled` - * __libjaylink__ is not available through the package manager - * note: https://www.cambus.net/installing-ca-certificates-on-netbsd/ -``` -pkgin install meson ninja pkg-config cmocka pciutils libusb1 libftdi1 -``` - -### OpenIndiana (Illumos, Solaris, SunOS) - * Tests are not working yet and must be disabled with `-Dtests=disabled` - * __libpci__ missing, pciutils is build without it - * __libftdi1__, __libjaylink__ is not available through the package manager - * TODO: replace __build-essential__ with the default compiler -``` -pkg install build-essential meson ninja cmocka libusb-1 -``` - -### MacOS (Homebrew) - * Tests are not working yet and must be disabled with `-Dtests=disabled` - * Internal, PCI programmer not supported - * __libjaylink__ is not available through the package manager -``` -brew install meson ninja pkg-config cmocka libusb libftdi -``` diff --git a/Documentation/mysteries_intel.txt b/Documentation/mysteries_intel.txt deleted file mode 100644 index 088abb877..000000000 --- a/Documentation/mysteries_intel.txt +++ /dev/null @@ -1,173 +0,0 @@ -= BBAR on ICH8 = - There is no sign of BBAR (BIOS Base Address Configuration Register) in the - public datasheet (or specification update) of the ICH8. Also, the offset of - that register has changed between ICH7 (SPIBAR + 50h) and ICH9 (SPIBAR + - A0h), so we have no clue if or where it is on ICH8. Out current policy is to - not touch it at all and assume/hope it is 0. - -= Software Sequencing vs. Hardware Sequencing and the "Opaque flash chip" = -Software sequencing and hardware sequencing are two methods used to interface -with the SPI controller on Intel platforms. They can be selected using either -ich_spi_mode=swseq or ich_spi_mode=hwseq programmer parameters. Flashrom will -attempt to automatically detect which mode to use. - -Software sequencing is the traditional method whereby software running on the -CPU handles most of the logic needed to interact with the flash chip. This -offers good flexibility since the user can utilize any opcode available in the -OPMENU registers, and OPMENU can be left unlocked or on coreboot-supported -platforms the owner of the system may program it for their needs before locking -it. Advanced or non-standard features of a chip such as write protection and -OTP may therefore be directly utilized by software. - -Hardware sequencing is a newer method (since around 2011) whereby most of the -logic for interacting with the SPI flash chip is contained within the SPI -controller itself and software such as flashrom may only select a few operations -chosen by Intel via the Flash Cycle (FCYCLE) field. The chip must conform to -specifications from Intel for each chipset/PCH. The specs are given in the -"SPI Programming Guide" application note. See [SPI_PROG] cited at the bottom of -this document for an example. - -Hardware sequencing simplifies things from a software perspective since the -software is guaranteed some minimal level of support and doesn't even need to -know the chip's ID or opcodes; it just needs to tell the SPI controller to -perform a type of transaction such as "read", "4k block erase", etc. Hence when -using hardware sequencing one will see "Opaque flash chip" as the chip's -description since software might not be able to identify the chip. The SPI -controller can combine multiple physical flash chips to logically appear as a -single large flash device, and in such cases it would not make sense for -flashrom to try to identify the chip. - -In many non-Intel systems the software has full control of a generic SPI -controller where the software controls the SPI signals and also constructs the -data payload including pre-op (e.g. write enable latch), opcode, address, and -data. Intel SPI flash controllers are purpose-built for flash chip access and -the software does not control the hardware directly. This makes Intel SPI -controllers less flexible from a software standpoint, however there are some -benefits such as guaranteed atomicity and multi-master arbitration needed for -modern Intel platforms where the CPU and various microprocessors can share the -same flash chip. - -= SMM BIOS Write Protection = -Sometimes a hardware vendor will enable "SMM BIOS Write Protect" (SMM_BWP) -in the firmware during boot time. The bits that control SMM_BWP are in the -BIOS_CNTL register in the LPC interface. - -When enabled, the SPI flash can only be written when the system is operating in -in System Management Mode (SMM). In other words, only certain code that was -installed by the BIOS can write to the flash chip. Programs that run in OS -context such as flashrom can still read the flash chip, but cannot write to the -flash chip. - -Flashrom will attempt to detect this and print a warning such as the following: -"Warning: BIOS region SMM protection is enabled!" - -Many vendor-supplied firmware update utilities do not actually write to the ROM; -instead they transfer data to/from memory which is read/written by a routine -running in SMM and is responsible for writing to the firmware ROM. This causes -severe system performance degradataion since all processors must be in SMM -context (ring -2) instead of OS context (ring 0) while the firmware ROM is being -written. - -= Accesses beyond region bounds in descriptor mode = - Intel's flash image tool will always expand the last region so that it covers - the whole flash chip, but some boards ship with a different configuration. - It seems that in descriptor mode all addresses outside the used regions can not - be accessed whatsoever. This is not specified anywhere publicly as far as we - could tell. flashrom does not handle this explicitly yet. It will just fail - when trying to touch an address outside of any region. - See also http://www.flashrom.org/pipermail/flashrom/2011-August/007606.html - -= (Un)locking the ME region = - If the ME region is locked by the FRAP register in descriptor mode, the host - software is not allowed to read or write any address inside that region. - Although the chipset datasheets specify that "[t]he contents of this register - are that of the Flash Descriptor" [PANTHER], this is not entirely true. - The firmware has to fill at least some of the registers involved. It is not - known when they become read-only or any other details, but there is at least - one HM67-based board, that provides an user-changeable setting in the firmware - user interface to enable ME region updates that lead to a FRAP content that is - not equal to the descriptor region bits [NC9B]. - - There are different ways to unlock access: - - - A pin strap: Flash Descriptor Security Override Strap (as indicated by the - Flash Descriptor Override Pin Strap Status (FDOPSS) in HSFS. That pin is - probably not accessible to end users on consumer boards (every Intel doc i - have seen stresses that this is for debugging in manufacturing only and - should not be available for end users). - The ME indicates this in bits [19:16] (Operation Mode) in the HFS register of - the HECI/MEI PCI device by setting them to 4 (SECOVR_JMPR) [MODE_CTRL]. - - - Intel Management Engine BIOS Extension (MEBx) Disable - This option may be available to end users on some boards usually accessible - by hitting ctrl+p after BIOS POST. Quote: "'Disabling' the Intel ME does not - really disable it: it causes the Intel ME code to be halted at an early stage - of the Intel ME's booting so that the system has no traffic originating from - the Intel ME on any of the buses." [MEBX] The ME indicates this in - bits [19:16] (Operation Mode) in the HFS register of the HECI/MEI PCI device - by setting them to 3 (Soft Temporary Disable) [MODE_CTRL]. - - - Previous to Ibex Peak/5 Series chipsets removing the DIMM from slot (or - channel?) #0 disables the ME completely, which may give the host access to - the ME region. - - - HMRFPO (Host ME Region Flash Protection Override) Enable MEI command - This is the most interesting one because it allows to temporarily disable - the ME region protection by software. The ME indicates this in bits [19:16] - (Operation Mode) in the HFS register of the HECI/MEI PCI device by setting - them to 5 (SECOVER_MEI_MSG) [MODE_CTRL]. - -== MEI/HECI == - Communication between the host software and the different services provided by - the ME is done via a packet-based protocol that uses MMIO transfers to one or - more virtual PCI devices. Upon this layer there exist various services that can - be used to read out hardware management values (e.g. temperatures, fan speeds - etc.). The lower levels of that protocol are well documented: - The locations/offsets of the PCI MMIO registers are noted in the chipset - datasheets. The actually communication is documented in a whitepaper [DCMI] and - an outdated as well as a current Linux kernel implementation (currently in - staging/ exist [KERNEL]. There exists a patch that re-implements this in user - space (as part of flashrom). - -== Problems == - The problem is that only very few higher level protocols are documented publicly, - especially the bunch of messages that contain the HMRFPO commands is probably - well protected and only documented in ME-specific docs and the BIOS writer's - guides. We are aware of a few leaked documents though that give us a few hints - about it, but nothing substantial regarding its implementation. - - The documents are somewhat contradicting each other in various points which - might be due to factual changes in process of time or due to the different - capabilities of the ME firmwares, example: - - Intel's Flash Programming Tool (FPT) "automatically stops ME writing to SPI - ME Region, to prevent both writing at the same time, causing data corruption." [ME8] - - "FPT is not HMRFPO-capable, so needs [the help of the FDOPS pin] HDA_SDO if - used to update the ME Region." [SPS] - - When looking at the various ME firmware editions (and different chipsets), things - get very unclear. Some docs say that HMRFPO needs to be sent before End-of-POST - (EOP), others say that the ME region can be updated in the field or that some - vendor tools use it for updates. This needs to be investigated further before - drawing any conclusion. - -[PANTHER] Intel 7 Series Chipset Family Platform Controller Hub (PCH) Datasheet - Document Number: 326776, April 2012, page 857 -[NC9B] Jetway NC9B flashrom v0.9.5.2-r1517 log with ME region unlocked. - NB: "FRAP 0e0f" vs. "FLMSTR1 0a0b". - http://paste.flashrom.org/view.php?id=1215 -[MODE_CTRL] Client Platform Enabling Tour: Platform Software - Document Number: 439167, Revision 1.2, page 52 -[MEBX] Intel Management Engine BIOS Extension (MEBX) User's Guide - Revision 1.2, Section 3.1 and 3.5 -[DCMI] DCMI Host Interface Specification - Revision 1.0 -[KERNEL] http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=tree;f=drivers/staging/mei;hb=HEAD -[SPI_PROG] Ibex Peak SPI Programming Guide - Document Number: 403598, Revision 1.3, page 79 -[ME8] Manufacturing with Intel Management Engine (ME) Firmware 8.X on Intel 7 Series - Revision 2.0, page 59 -[SPS] Manufacturing with Intel Management Engine (ME) on Intel C600 Series Chipset 1 - for Romley Server 2 Platforms using Server Platform Services (SPS) Firmware - Revision 2.2, page 51 diff --git a/MAINTAINERS b/MAINTAINERS index d72c17002..c54eceb77 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1,5 +1,4 @@ - List of upstream flashrom maintainers This represents the list of maintainers that work on the upstream flashrom @@ -9,11 +8,8 @@ don't have a maintainer. If you are looking for reviewers for such a subtree, it's often a good choice to look at the git history to see who worked on it last. -Please try to follow our [development guidelines]. This will make things -easier on the maintainers. Not all of these guidelines matter for every -trivial patch. So apply some common sense. - -[development guidelines]: https://www.flashrom.org/Development_Guidelines +Please follow our development guide: +https://www.flashrom.org/dev_guide/development_guide.html Happy hacking! @@ -81,15 +77,25 @@ Maintainers List (try to look for most precise areas first) ################################################################################ BUILD SYSTEM -M: Thomas Heijligen +M: Peter Marheine S: Maintained -F: Makefile* F: meson* -F: Makefile*/ F: */meson* -F: */Makefile* F: util/ich_descriptors_tool/meson* -F: util/ich_descriptors_tool/Makefile* + +ERASE/WRITE ALGORITHM +M: Aarya Chaumal +S: Maintained +F: erasure_layout* +F: include/erasure_layout* + +FLASHCHIPS +M: Anastasia Klimchuk +M: Nikolai Artemiev +M: Stefan Reinauer +S: Maintained +F: flashchips* +F: include/flashchips* I2C HELPERS M: Peter Marheine @@ -98,6 +104,7 @@ F: i2c_helper_linux.c WRITEPROTECT M: Nikolai Artemiev +M: Sergii Dmytruk S: Supported F: writeprotect* F: include/writeprotect* @@ -107,15 +114,40 @@ F: include/writeprotect* ################################################################################ MAINTAINERS -M: Felix Singer M: Anastasia Klimchuk S: Maintained F: MAINTAINERS +SPHINX DOCS +M: Anastasia Klimchuk +S: Maintained +F: doc/ +F: README.rst + ################################################################################ # PROGRAMMERS ################################################################################ +AMD SB600SPI +M: Martin Roth +S: Maintained +F: sb600spi.c + +BUS PIRATE +M: David Reguera +S: Maintained +F: buspirate_spi.c + +CH347 +M: Nicholas Chin +S: Maintained +F: ch347_spi.c + +DirtyJTAG +M: Jean THOMAS +S: Maintained +F: dirtyjtag_spi.c + I2C PROGRAMMERS M: Peter Marheine S: Supported @@ -128,13 +160,28 @@ M: Nikolai Artemiev S: Supported F: linux_mtd.c +National Instruments USB-845x +M: Miklos Marton +S: Maintained +F: ni845x_spi.c + +RAIDEN DEBUG SPI +M: Nikolai Artemiev +S: Maintained +F: raiden_debug_spi.c + +STLINK-V3 +M: Miklos Marton +S: Maintained +F: stlinkv3_spi.c + ################################################################################ # TESTS ################################################################################ UNIT TESTS M: Anastasia Klimchuk -S: Supported +S: Maintained F: tests/ F: subprojects/cmocka.wrap @@ -142,12 +189,23 @@ F: subprojects/cmocka.wrap # UTILS ################################################################################ +BASH COMPLETION +M: Alexander Goncharov +S: Maintained +F: util/flashrom.bash-completion.tmpl + +CONTINUOUS INTEGRATION SCRIPT +M: Anastasia Klimchuk +S: Maintained +F: test_build.sh + FLASHROM TESTER -M: Evan Benn +M: Hsuan Ting Chen +R: Evan Benn S: Supported F: util/flashrom_tester/ -NIX SHELL -M: Felix Singer +FLASHROM DOCKER +M: Stefan Reinauer S: Maintained -F: util/shell.nix +F: util/docker/ diff --git a/Makefile b/Makefile deleted file mode 100644 index 0e3ee99bb..000000000 --- a/Makefile +++ /dev/null @@ -1,1108 +0,0 @@ -# -# This file is part of the flashrom project. -# -# Copyright (C) 2005 coresystems GmbH -# Copyright (C) 2009,2010,2012 Carl-Daniel Hailfinger -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# - -PROGRAM = flashrom - -############################################################################### -# Defaults for the toolchain. - -# If you want to cross-compile, just run e.g. -# make CC=i586-pc-msdosdjgpp-gcc -# You may have to specify STRIP/AR/RANLIB as well. -# -# Note for anyone editing this Makefile: gnumake will happily ignore any -# changes in this Makefile to variables set on the command line. -STRIP ?= strip -STRIP_ARGS = -s -INSTALL = install -PREFIX ?= /usr/local -MANDIR ?= $(PREFIX)/share/man -CFLAGS ?= -Os -Wall -Wextra -Wno-unused-parameter -Wshadow -Wmissing-prototypes -Wwrite-strings -EXPORTDIR ?= . -RANLIB ?= ranlib -PKG_CONFIG ?= pkg-config -BUILD_DETAILS_FILE ?= build_details.txt - -# The following parameter changes the default programmer that will be used if there is no -p/--programmer -# argument given when running flashrom. The predefined setting does not enable any default so that every -# user has to declare the programmer he wants to use on every run. The rationale for this to be not set -# (to e.g. the internal programmer) is that forgetting to specify this when working with another programmer -# easily puts the system attached to the default programmer at risk (e.g. you want to flash coreboot to another -# system attached to an external programmer while the default programmer is set to the internal programmer, and -# you forget to use the -p parameter. This would (try to) overwrite the existing firmware of the computer -# running flashrom). Please do not enable this without thinking about the possible consequences. Possible -# values can be found when running 'flashrom --list-supported' under the 'Supported programmers' section. -CONFIG_DEFAULT_PROGRAMMER_NAME ?= -# The following adds a default parameter for the default programmer set above (only). -CONFIG_DEFAULT_PROGRAMMER_ARGS ?= -# Example: compiling with -# make CONFIG_DEFAULT_PROGRAMMER_NAME=serprog CONFIG_DEFAULT_PROGRAMMER_ARGS="dev=/dev/ttyUSB0:1500000" -# would make executing './flashrom' (almost) equivialent to './flashrom -p serprog:dev=/dev/ttyUSB0:1500000'. - -# The user can provide CPP, C and LDFLAGS and the Makefile will extend these -override CPPFLAGS := $(CPPFLAGS) -override CFLAGS := $(CFLAGS) -override LDFLAGS := $(LDFLAGS) - -# If your compiler spits out excessive warnings, run make WARNERROR=no -# You shouldn't have to change this flag. -WARNERROR ?= yes - -ifeq ($(WARNERROR), yes) -override CFLAGS += -Werror -endif - -ifdef LIBS_BASE -PKG_CONFIG_LIBDIR ?= $(LIBS_BASE)/lib/pkgconfig -override CPPFLAGS += -I$(LIBS_BASE)/include -override LDFLAGS += -L$(LIBS_BASE)/lib -Wl,-rpath -Wl,$(LIBS_BASE)/lib -endif - -ifeq ($(CONFIG_STATIC),yes) -override LDFLAGS += -static -endif - -# Set LC_ALL=C to minimize influences of the locale. -# However, this won't work for the majority of relevant commands because they use the $(shell) function and -# GNU make does not relay variables exported within the makefile to their environment. -LC_ALL=C -export LC_ALL - -dummy_for_make_3_80:=$(shell printf "Build started on %s\n\n" "$$(date)" >$(BUILD_DETAILS_FILE)) - -# Provide an easy way to execute a command, print its output to stdout and capture any error message on stderr -# in the build details file together with the original stdout output. -debug_shell = $(shell export LC_ALL=C ; { echo 'exec: export LC_ALL=C ; { $(subst ','\'',$(1)) ; }' >&2; \ - { $(1) ; } | tee -a $(BUILD_DETAILS_FILE) ; echo >&2 ; } 2>>$(BUILD_DETAILS_FILE)) - -include Makefile.include - -############################################################################### -# Dependency handling. - -DEPENDS_ON_SERIAL := \ - CONFIG_BUSPIRATE_SPI \ - CONFIG_PONY_SPI \ - CONFIG_SERPROG \ - -DEPENDS_ON_SOCKETS := \ - CONFIG_SERPROG \ - -DEPENDS_ON_BITBANG_SPI := \ - CONFIG_DEVELOPERBOX_SPI \ - CONFIG_INTERNAL_X86 \ - CONFIG_NICINTEL_SPI \ - CONFIG_OGP_SPI \ - CONFIG_PONY_SPI \ - CONFIG_RAYER_SPI \ - -DEPENDS_ON_RAW_MEM_ACCESS := \ - CONFIG_AST1100 \ - CONFIG_AST2400 \ - CONFIG_ATAPROMISE \ - CONFIG_DRKAISER \ - CONFIG_GFXNVIDIA \ - CONFIG_INTERNAL_X86 \ - CONFIG_IT8212 \ - CONFIG_NICINTEL \ - CONFIG_NICINTEL_EEPROM \ - CONFIG_NICINTEL_SPI \ - CONFIG_OGP_SPI \ - CONFIG_SATAMV \ - CONFIG_SATASII \ - -DEPENDS_ON_X86_MSR := \ - CONFIG_INTERNAL_X86 \ - -DEPENDS_ON_X86_PORT_IO := \ - CONFIG_AST1100 \ - CONFIG_AST2400 \ - CONFIG_ATAHPT \ - CONFIG_ATAPROMISE \ - CONFIG_INTERNAL_X86 \ - CONFIG_NIC3COM \ - CONFIG_NICNATSEMI \ - CONFIG_NICREALTEK \ - CONFIG_RAYER_SPI \ - CONFIG_SATAMV \ - -DEPENDS_ON_LIBPCI := \ - CONFIG_AST1100 \ - CONFIG_AST2400 \ - CONFIG_ATAHPT \ - CONFIG_ATAPROMISE \ - CONFIG_ATAVIA \ - CONFIG_DRKAISER \ - CONFIG_GFXNVIDIA \ - CONFIG_INTERNAL \ - CONFIG_IT8212 \ - CONFIG_NIC3COM \ - CONFIG_NICINTEL \ - CONFIG_NICINTEL_EEPROM \ - CONFIG_NICINTEL_SPI \ - CONFIG_NICNATSEMI \ - CONFIG_NICREALTEK \ - CONFIG_OGP_SPI \ - CONFIG_SATAMV \ - CONFIG_SATASII \ - -DEPENDS_ON_LIBUSB1 := \ - CONFIG_CH341A_SPI \ - CONFIG_DEDIPROG \ - CONFIG_DEVELOPERBOX_SPI \ - CONFIG_DIGILENT_SPI \ - CONFIG_PICKIT2_SPI \ - CONFIG_RAIDEN_DEBUG_SPI \ - CONFIG_STLINKV3_SPI \ - -DEPENDS_ON_LIBFTDI1 := \ - CONFIG_FT2232_SPI \ - CONFIG_USBBLASTER_SPI \ - -DEPENDS_ON_LIBJAYLINK := \ - CONFIG_JLINK_SPI \ - -DEPENDS_ON_LIB_NI845X := \ - CONFIG_NI845X_SPI \ - -DEPENDS_ON_LINUX_I2C := \ - CONFIG_MSTARDDC_SPI \ - CONFIG_PARADE_LSPCON \ - CONFIG_REALTEK_MST_I2C_SPI \ - CONFIG_MEDIATEK_I2C_SPI \ - -ifeq ($(CONFIG_ENABLE_LIBUSB1_PROGRAMMERS), no) -$(call disable_all,$(DEPENDS_ON_LIBUSB1)) -endif - -ifeq ($(CONFIG_ENABLE_LIBPCI_PROGRAMMERS), no) -$(call disable_all,$(DEPENDS_ON_LIBPCI)) -endif - -############################################################################### -# General OS-specific settings. -# 1. Prepare for later by gathering information about host and target OS -# 2. Set compiler flags and parameters according to OSes -# 3. Likewise verify user-supplied CONFIG_* variables. - -# HOST_OS is only used to work around local toolchain issues. -HOST_OS ?= $(shell uname) -ifeq ($(findstring MINGW, $(HOST_OS)), MINGW) -# Explicitly set CC = gcc on MinGW, otherwise: "cc: command not found". -CC = gcc -endif - -CC_WORKING := $(call c_compile_test, Makefile.d/cc_test.c) - -# Configs for dependencies. Can be overwritten by commandline -CONFIG_LIBFTDI1_VERSION := $(call dependency_version, libftdi1) -CONFIG_LIBFTDI1_CFLAGS := $(call dependency_cflags, libftdi1) -CONFIG_LIBFTDI1_LDFLAGS := $(call dependency_ldflags, libftdi1) - -# Hack to keep legacy auto detection of Program Files (x86), Only active if none of the CONFIG_ variables for ni845x are set. -ifeq ($(CONFIG_NI845X_LIBRARY_PATH)$(CONFIG_LIB_NI845X_CFLAGS)$(CONFIG_LIB_NI845X_LDFLAGS),) -PROGRAMFILES_X86 = $(shell env | sed -n "s/^PROGRAMFILES(X86)=//p") -ifneq ($(PROGRAMFILES_X86DIR),) -ifneq ($(PROGRAMFILES_X86DIR), ${PROGRAMFILES}) -NI854_X86_LIBRARY_PATH := '${PROGRAMFILES_X86}\National Instruments\NI-845x\MS Visual C' -endif -endif -endif - -CONFIG_NI845X_LIBRARY_PATH := '${PROGRAMFILES}\National Instruments\NI-845x\MS Visual C' -CONFIG_LIB_NI845X_CFLAGS := -I$(CONFIG_NI845X_LIBRARY_PATH) $(if NI854_X86_LIBRARY_PATH, -I${NI854_X86_LIBRARY_PATH}) -CONFIG_LIB_NI845X_LDFLAGS := -L$(CONFIG_NI845X_LIBRARY_PATH) $(if NI854_X86_LIBRARY_PATH, -L${NI854_X86_LIBRARY_PATH}) -lni845x - -CONFIG_LIBJAYLINK_VERSION := $(call dependency_version, libjaylink) -CONFIG_LIBJAYLINK_CFLAGS := $(call dependency_cflags, libjaylink) -CONFIG_LIBJAYLINK_LDFLAGS := $(call dependency_ldflags, libjaylink) - -CONFIG_LIBUSB1_VERSION := $(call dependency_version, libusb-1.0) -CONFIG_LIBUSB1_CFLAGS := $(call dependency_cflags, libusb-1.0) -CONFIG_LIBUSB1_LDFLAGS := $(call dependency_ldflags, libusb-1.0) - -CONFIG_LIBPCI_VERSION := $(call dependency_version, libpci) -CONFIG_LIBPCI_CFLAGS := $(call dependency_cflags, libpci) -CONFIG_LIBPCI_LDFLAGS := $(call dependency_ldflags, libpci) - -# Determine the destination OS, architecture and endian -# IMPORTANT: The following lines must be placed before TARGET_OS, ARCH or ENDIAN -# is ever used (of course), but should come after any lines setting CC because -# the lines below use CC itself. -override TARGET_OS := $(call c_macro_test, Makefile.d/os_test.h) -override ARCH := $(call c_macro_test, Makefile.d/arch_test.h) -override ENDIAN := $(call c_macro_test, Makefile.d/endian_test.h) - - -HAS_LIBFTDI1 := $(call find_dependency, libftdi1) -HAS_LIB_NI845X := no -HAS_LIBJAYLINK := $(call find_dependency, libjaylink) -HAS_LIBUSB1 := $(call find_dependency, libusb-1.0) -HAS_LIBPCI := $(call find_dependency, libpci) - -HAS_PCI_OLD_GET_DEV := $(call c_compile_test, Makefile.d/pci_old_get_dev_test.c, $(CONFIG_LIBPCI_CFLAGS)) -HAS_FT232H := $(call c_compile_test, Makefile.d/ft232h_test.c, $(CONFIG_LIBFTDI1_CFLAGS)) -HAS_UTSNAME := $(call c_compile_test, Makefile.d/utsname_test.c) -HAS_CLOCK_GETTIME := $(call c_compile_test, Makefile.d/clock_gettime_test.c) -HAS_EXTERN_LIBRT := $(call c_link_test, Makefile.d/clock_gettime_test.c, , -lrt) -HAS_LINUX_MTD := $(call c_compile_test, Makefile.d/linux_mtd_test.c) -HAS_LINUX_SPI := $(call c_compile_test, Makefile.d/linux_spi_test.c) -HAS_LINUX_I2C := $(call c_compile_test, Makefile.d/linux_i2c_test.c) -HAS_SERIAL := $(strip $(if $(filter $(TARGET_OS), DOS libpayload), no, yes)) -EXEC_SUFFIX := $(strip $(if $(filter $(TARGET_OS), DOS MinGW), .exe)) - -override CFLAGS += -Iinclude - -ifeq ($(TARGET_OS), DOS) -# DJGPP has odd uint*_t definitions which cause lots of format string warnings. -override CFLAGS += -Wno-format -override LDFLAGS += -lgetopt -endif - -ifeq ($(TARGET_OS), $(filter $(TARGET_OS), MinGW Cygwin)) -$(call mark_unsupported,$(DEPENDS_ON_RAW_MEM_ACCESS)) -$(call mark_unsupported,$(DEPENDS_ON_X86_PORT_IO)) -$(call mark_unsupported,$(DEPENDS_ON_X86_MSR)) -FEATURE_FLAGS += -D'IS_WINDOWS=1' -else -FEATURE_FLAGS += -D'IS_WINDOWS=0' -endif - -# FIXME: Should we check for Cygwin/MSVC as well? -ifeq ($(TARGET_OS), MinGW) -# MinGW doesn't have the ffs() function, but we can use gcc's __builtin_ffs(). -FLASHROM_CFLAGS += -Dffs=__builtin_ffs -# Some functions provided by Microsoft do not work as described in C99 specifications. This macro fixes that -# for MinGW. See http://sourceforge.net/p/mingw-w64/wiki2/printf%20and%20scanf%20family/ */ -FLASHROM_CFLAGS += -D__USE_MINGW_ANSI_STDIO=1 - -# For now we disable all PCI-based programmers on Windows/MinGW (no libpci). -$(call mark_unsupported,$(DEPENDS_ON_LIBPCI)) -# And programmers that need raw access. -$(call mark_unsupported,$(DEPENDS_ON_RAW_MEM_ACCESS)) - -else # No MinGW - -# NI USB-845x only supported on Windows at the moment -$(call mark_unsupported,CONFIG_NI845X_SPI) - -endif - -ifeq ($(TARGET_OS), libpayload) -ifeq ($(MAKECMDGOALS),) -.DEFAULT_GOAL := libflashrom.a -$(info Setting default goal to libflashrom.a) -endif -$(call mark_unsupported,CONFIG_DUMMY) -# libpayload does not provide the romsize field in struct pci_dev that the atapromise code requires. -$(call mark_unsupported,CONFIG_ATAPROMISE) -# Dediprog, Developerbox, USB-Blaster, PICkit2, CH341A and FT2232 are not supported with libpayload (missing libusb support). -$(call mark_unsupported,$(DEPENDS_ON_LIBUSB1) $(DEPENDS_ON_LIBFTDI) $(DEPENDS_ON_LIBJAYLINK)) -endif - -ifeq ($(HAS_LINUX_MTD), no) -$(call mark_unsupported,CONFIG_LINUX_MTD) -endif - -ifeq ($(HAS_LINUX_SPI), no) -$(call mark_unsupported,CONFIG_LINUX_SPI) -endif - -ifeq ($(HAS_LINUX_I2C), no) -$(call mark_unsupported,DEPENDS_ON_LINUX_I2C) -endif - -ifeq ($(TARGET_OS), Android) -# Android on x86 (currently) does not provide raw PCI port I/O operations. -$(call mark_unsupported,$(DEPENDS_ON_X86_PORT_IO)) -endif - -# Disable the internal programmer on unsupported architectures or systems -ifeq ($(or $(filter $(ARCH), x86), $(filter $(TARGET_OS), Linux)), ) -$(call mark_unsupported,CONFIG_INTERNAL) -endif - -ifeq ($(HAS_LIBPCI), no) -$(call mark_unsupported,$(DEPENDS_ON_LIBPCI)) -endif - -ifeq ($(HAS_LIBFTDI1), no) -$(call mark_unsupported,$(DEPENDS_ON_LIBFTDI1)) -endif - -ifeq ($(HAS_LIB_NI845X), no) -$(call mark_unsupported,$(DEPENDS_ON_LIB_NI845X)) -endif - -ifeq ($(HAS_LIBJAYLINK), no) -$(call mark_unsupported,$(DEPENDS_ON_LIBJAYLINK)) -endif - -ifeq ($(HAS_LIBUSB1), no) -$(call mark_unsupported,$(DEPENDS_ON_LIBUSB1)) -endif - -ifeq ($(HAS_SERIAL), no) -$(call mark_unsupported, $(DEPENDS_ON_SERIAL)) -endif - -ifeq ($(ENDIAN), little) -FEATURE_FLAGS += -D'__FLASHROM_LITTLE_ENDIAN__=1' -endif -ifeq ($(ENDIAN), big) -FEATURE_FLAGS += -D'__FLASHROM_BIG_ENDIAN__=1' -endif - -# PCI port I/O support is unimplemented on PPC/MIPS/SPARC and unavailable on ARM. -# Right now this means the drivers below only work on x86. -ifneq ($(ARCH), x86) -$(call mark_unsupported,$(DEPENDS_ON_X86_MSR)) -$(call mark_unsupported,$(DEPENDS_ON_X86_PORT_IO)) -endif - -# Additionally disable all drivers needing raw access (memory, PCI, port I/O) -# on architectures with unknown raw access properties. -# Right now those architectures are alpha hppa m68k sh s390 -ifneq ($(ARCH), $(filter $(ARCH), x86 mips ppc arm sparc arc e2k)) -$(call mark_unsupported,$(DEPENDS_ON_RAW_MEM_ACCESS)) -endif - -############################################################################### -# Flash chip drivers and bus support infrastructure. - -CHIP_OBJS = jedec.o stm50.o w39.o w29ee011.o \ - sst28sf040.o 82802ab.o \ - sst49lfxxxc.o sst_fwhub.o edi.o flashchips.o spi.o spi25.o spi25_statusreg.o \ - spi95.o opaque.o sfdp.o en29lv640b.o at45db.o s25f.o \ - writeprotect.o writeprotect_ranges.o - -############################################################################### -# Library code. - -LIB_OBJS = libflashrom.o layout.o flashrom.o udelay.o parallel.o programmer.o programmer_table.o \ - helpers.o helpers_fileio.o ich_descriptors.o fmap.o platform/endian_$(ENDIAN).o platform/memaccess.o - - -############################################################################### -# Frontend related stuff. - -CLI_OBJS = cli_classic.o cli_output.o cli_common.o print.o - -# versioninfo.inc stores metadata required to build a packaged flashrom. It is generated by the export rule and -# imported below. If versioninfo.inc is not found and the variables are not defined by the user, the info will -# be obtained using util/getrevision.sh, which is the common case during development. --include versioninfo.inc -VERSION ?= $(shell ./util/getrevision.sh --revision) -MAN_DATE ?= $(shell ./util/getrevision.sh --date $(PROGRAM).8.tmpl 2>/dev/null) - -SCMDEF := -D'FLASHROM_VERSION="$(VERSION)"' - -# No spaces in release names unless set explicitly -RELEASENAME ?= $(shell echo "$(VERSION)" | sed -e 's/ /_/') - -# If a VCS is found then try to install hooks. -$(shell ./util/getrevision.sh -c 2>/dev/null && ./util/git-hooks/install.sh) - -############################################################################### -# Default settings of CONFIG_* variables. - -# Always enable internal/onboard support for now. -CONFIG_INTERNAL ?= yes -CONFIG_INTERNAL_X86 ?= yes - -# Always enable serprog for now. -CONFIG_SERPROG ?= yes - -# RayeR SPIPGM hardware support -CONFIG_RAYER_SPI ?= yes - -# ChromiumOS servo DUT debug board hardware support -CONFIG_RAIDEN_DEBUG_SPI ?= yes - -# PonyProg2000 SPI hardware support -CONFIG_PONY_SPI ?= yes - -# Always enable 3Com NICs for now. -CONFIG_NIC3COM ?= yes - -# Enable NVIDIA graphics cards. Note: write and erase do not work properly. -CONFIG_GFXNVIDIA ?= yes - -# Enable AST1100 BMC SoCs. -CONFIG_AST1100 ?= yes - -# Enable AST2400 BMC SoCs. -CONFIG_AST2400 ?= yes - -# Always enable SiI SATA controllers for now. -CONFIG_SATASII ?= yes - -# Highpoint (HPT) ATA/RAID controller support. -# IMPORTANT: This code is not yet working! -CONFIG_ATAHPT ?= no - -# VIA VT6421A LPC memory support -CONFIG_ATAVIA ?= yes - -# Promise ATA controller support. -CONFIG_ATAPROMISE ?= no - -# Always enable FT2232 SPI dongles for now. -CONFIG_FT2232_SPI ?= yes - -# ITE Embedded Controllers. -CONFIG_ITE_EC ?= yes - -# Always enable Altera USB-Blaster dongles for now. -CONFIG_USBBLASTER_SPI ?= yes - -# MSTAR DDC support needs more tests/reviews/cleanups. -CONFIG_MSTARDDC_SPI ?= no - -# Always enable PICkit2 SPI dongles for now. -CONFIG_PICKIT2_SPI ?= yes - -# Always enable STLink V3 -CONFIG_STLINKV3_SPI ?= yes - -# Disables Parade LSPCON support until the i2c helper supports multiple systems. -CONFIG_PARADE_LSPCON ?= no - -# Disables MediaTek support until the i2c helper supports multiple systems. -CONFIG_MEDIATEK_I2C_SPI ?= no - -# Disables REALTEK_MST support until the i2c helper supports multiple systems. -CONFIG_REALTEK_MST_I2C_SPI ?= no - -# Always enable dummy tracing for now. -CONFIG_DUMMY ?= yes - -# Always enable Dr. Kaiser for now. -CONFIG_DRKAISER ?= yes - -# Always enable Realtek NICs for now. -CONFIG_NICREALTEK ?= yes - -# Disable National Semiconductor NICs until support is complete and tested. -CONFIG_NICNATSEMI ?= no - -# Always enable Intel NICs for now. -CONFIG_NICINTEL ?= yes - -# Always enable SPI on Intel NICs for now. -CONFIG_NICINTEL_SPI ?= yes - -# Always enable EEPROM on Intel NICs for now. -CONFIG_NICINTEL_EEPROM ?= yes - -# Always enable SPI on OGP cards for now. -CONFIG_OGP_SPI ?= yes - -# Always enable Bus Pirate SPI for now. -CONFIG_BUSPIRATE_SPI ?= yes - -# Always enable Dediprog SF100 for now. -CONFIG_DEDIPROG ?= yes - -# Always enable Developerbox emergency recovery for now. -CONFIG_DEVELOPERBOX_SPI ?= yes - -# Always enable Marvell SATA controllers for now. -CONFIG_SATAMV ?= yes - -# Enable Linux spidev and MTD interfaces by default. We disable them on non-Linux targets. -CONFIG_LINUX_MTD ?= yes -CONFIG_LINUX_SPI ?= yes - -# Always enable ITE IT8212F PATA controllers for now. -CONFIG_IT8212 ?= yes - -# Winchiphead CH341A -CONFIG_CH341A_SPI ?= yes - -# Digilent Development board JTAG -CONFIG_DIGILENT_SPI ?= yes - -# Disable J-Link for now. -CONFIG_JLINK_SPI ?= no - -# National Instruments USB-845x is Windows only and needs a proprietary library. -CONFIG_NI845X_SPI ?= no - -# Disable wiki printing by default. It is only useful if you have wiki access. -CONFIG_PRINT_WIKI ?= no - -# Disable all features if CONFIG_NOTHING=yes is given unless CONFIG_EVERYTHING was also set -ifeq ($(CONFIG_NOTHING), yes) - ifeq ($(CONFIG_EVERYTHING), yes) - $(error Setting CONFIG_NOTHING=yes and CONFIG_EVERYTHING=yes does not make sense) - endif - $(foreach var, $(filter CONFIG_%, $(.VARIABLES)),\ - $(if $(filter yes, $($(var))),\ - $(eval $(var)=no))) -endif - -# Enable all features if CONFIG_EVERYTHING=yes is given -ifeq ($(CONFIG_EVERYTHING), yes) -$(foreach var, $(filter CONFIG_%, $(.VARIABLES)),\ - $(if $(filter no, $($(var))),\ - $(eval $(var)=yes))) -endif - -############################################################################### -# Handle CONFIG_* variables that depend on others set (and verified) above. - -# The external DMI decoder (dmidecode) does not work in libpayload. Bail out if the internal one got disabled. -ifeq ($(TARGET_OS), libpayload) -ifeq ($(CONFIG_INTERNAL), yes) -ifeq ($(CONFIG_INTERNAL_DMI), no) -UNSUPPORTED_FEATURES += CONFIG_INTERNAL_DMI=no -else -override CONFIG_INTERNAL_DMI = yes -endif -endif -endif - -# Use internal DMI/SMBIOS decoder by default instead of relying on dmidecode. -CONFIG_INTERNAL_DMI ?= yes - -############################################################################### -# Programmer drivers and programmer support infrastructure. -# Depending on the CONFIG_* variables set and verified above we set compiler flags and parameters below. - -ifdef CONFIG_DEFAULT_PROGRAMMER_NAME -FEATURE_FLAGS += -D'CONFIG_DEFAULT_PROGRAMMER_NAME=&programmer_$(CONFIG_DEFAULT_PROGRAMMER_NAME)' -else -FEATURE_FLAGS += -D'CONFIG_DEFAULT_PROGRAMMER_NAME=NULL' -endif - -FEATURE_FLAGS += -D'CONFIG_DEFAULT_PROGRAMMER_ARGS="$(CONFIG_DEFAULT_PROGRAMMER_ARGS)"' - -################################################################################ - -ifeq ($(ARCH), x86) -ifeq ($(CONFIG_INTERNAL) $(CONFIG_INTERNAL_X86), yes yes) -FEATURE_FLAGS += -D'CONFIG_INTERNAL=1' -PROGRAMMER_OBJS += processor_enable.o chipset_enable.o board_enable.o cbtable.o \ - internal.o it87spi.o sb600spi.o amd_imc.o wbsio_spi.o mcp6x_spi.o \ - ichspi.o dmi.o known_boards.o sio.o -endif -else -ifeq ($(CONFIG_INTERNAL), yes) -FEATURE_FLAGS += -D'CONFIG_INTERNAL=1' -PROGRAMMER_OBJS += processor_enable.o chipset_enable.o board_enable.o cbtable.o internal.o known_boards.o -endif -NEED_LIBPCI += CONFIG_INTERNAL -endif - -ifeq ($(CONFIG_ITE_EC), yes) -FEATURE_FLAGS += -D'CONFIG_ITE_EC=1' -PROGRAMMER_OBJS += ite_ec.o -ifeq ($(findstring it87spi.o,$(PROGRAMMER_OBJS)),) -# Do not include it87spi.c twice -PROGRAMMER_OBJS += it87spi.o -endif -NEED_RAW_ACCESS += CONFIG_ITE_EC -NEED_LIBPCI += CONFIG_ITE_EC -endif - -ifeq ($(CONFIG_INTERNAL_DMI), yes) -FEATURE_FLAGS += -D'CONFIG_INTERNAL_DMI=1' -endif - -ifeq ($(CONFIG_SERPROG), yes) -FEATURE_FLAGS += -D'CONFIG_SERPROG=1' -PROGRAMMER_OBJS += serprog.o -endif - -ifeq ($(CONFIG_RAYER_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_RAYER_SPI=1' -PROGRAMMER_OBJS += rayer_spi.o -endif - -ifeq ($(CONFIG_RAIDEN_DEBUG_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_RAIDEN_DEBUG_SPI=1' -PROGRAMMER_OBJS += raiden_debug_spi.o -endif - -ifeq ($(CONFIG_PONY_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_PONY_SPI=1' -PROGRAMMER_OBJS += pony_spi.o -endif - -ifeq ($(CONFIG_NIC3COM), yes) -FEATURE_FLAGS += -D'CONFIG_NIC3COM=1' -PROGRAMMER_OBJS += nic3com.o -endif - -ifeq ($(CONFIG_GFXNVIDIA), yes) -FEATURE_FLAGS += -D'CONFIG_GFXNVIDIA=1' -PROGRAMMER_OBJS += gfxnvidia.o -endif - -ifeq ($(CONFIG_AST1100), yes) -FEATURE_FLAGS += -D'CONFIG_AST1100=1' -PROGRAMMER_OBJS += ast1100.o -NEED_LIBPCI += CONFIG_AST1100 -endif - -ifeq ($(CONFIG_AST2400), yes) -FEATURE_FLAGS += -D'CONFIG_AST2400=1' -PROGRAMMER_OBJS += ast2400.o -NEED_LIBPCI += CONFIG_AST2400 -endif - -ifeq ($(CONFIG_SATASII), yes) -FEATURE_FLAGS += -D'CONFIG_SATASII=1' -PROGRAMMER_OBJS += satasii.o -endif - -ifeq ($(CONFIG_ATAHPT), yes) -FEATURE_FLAGS += -D'CONFIG_ATAHPT=1' -PROGRAMMER_OBJS += atahpt.o -endif - -ifeq ($(CONFIG_ATAVIA), yes) -FEATURE_FLAGS += -D'CONFIG_ATAVIA=1' -PROGRAMMER_OBJS += atavia.o -endif - -ifeq ($(CONFIG_ATAPROMISE), yes) -FEATURE_FLAGS += -D'CONFIG_ATAPROMISE=1' -PROGRAMMER_OBJS += atapromise.o -endif - -ifeq ($(CONFIG_IT8212), yes) -FEATURE_FLAGS += -D'CONFIG_IT8212=1' -PROGRAMMER_OBJS += it8212.o -endif - -ifeq ($(CONFIG_FT2232_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_FT2232_SPI=1' -PROGRAMMER_OBJS += ft2232_spi.o -endif - -ifeq ($(CONFIG_USBBLASTER_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_USBBLASTER_SPI=1' -PROGRAMMER_OBJS += usbblaster_spi.o -endif - -ifeq ($(CONFIG_PICKIT2_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_PICKIT2_SPI=1' -PROGRAMMER_OBJS += pickit2_spi.o -endif - -ifeq ($(CONFIG_STLINKV3_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_STLINKV3_SPI=1' -PROGRAMMER_OBJS += stlinkv3_spi.o -endif - -ifeq ($(CONFIG_PARADE_LSPCON), yes) -FEATURE_FLAGS += -D'CONFIG_PARADE_LSPCON=1' -PROGRAMMER_OBJS += parade_lspcon.o -endif - -ifeq ($(CONFIG_MEDIATEK_I2C_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_MEDIATEK_I2C_SPI=1' -PROGRAMMER_OBJS += mediatek_i2c_spi.o -endif - -ifeq ($(CONFIG_REALTEK_MST_I2C_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_REALTEK_MST_I2C_SPI=1' -PROGRAMMER_OBJS += realtek_mst_i2c_spi.o -endif - -ifeq ($(CONFIG_DUMMY), yes) -FEATURE_FLAGS += -D'CONFIG_DUMMY=1' -PROGRAMMER_OBJS += dummyflasher.o -endif - -ifeq ($(CONFIG_DRKAISER), yes) -FEATURE_FLAGS += -D'CONFIG_DRKAISER=1' -PROGRAMMER_OBJS += drkaiser.o -endif - -ifeq ($(CONFIG_NICREALTEK), yes) -FEATURE_FLAGS += -D'CONFIG_NICREALTEK=1' -PROGRAMMER_OBJS += nicrealtek.o -endif - -ifeq ($(CONFIG_NICNATSEMI), yes) -FEATURE_FLAGS += -D'CONFIG_NICNATSEMI=1' -PROGRAMMER_OBJS += nicnatsemi.o -endif - -ifeq ($(CONFIG_NICINTEL), yes) -FEATURE_FLAGS += -D'CONFIG_NICINTEL=1' -PROGRAMMER_OBJS += nicintel.o -endif - -ifeq ($(CONFIG_NICINTEL_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_NICINTEL_SPI=1' -PROGRAMMER_OBJS += nicintel_spi.o -endif - -ifeq ($(CONFIG_NICINTEL_EEPROM), yes) -FEATURE_FLAGS += -D'CONFIG_NICINTEL_EEPROM=1' -PROGRAMMER_OBJS += nicintel_eeprom.o -endif - -ifeq ($(CONFIG_OGP_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_OGP_SPI=1' -PROGRAMMER_OBJS += ogp_spi.o -endif - -ifeq ($(CONFIG_BUSPIRATE_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_BUSPIRATE_SPI=1' -PROGRAMMER_OBJS += buspirate_spi.o -endif - -ifeq ($(CONFIG_DEDIPROG), yes) -FEATURE_FLAGS += -D'CONFIG_DEDIPROG=1' -PROGRAMMER_OBJS += dediprog.o -endif - -ifeq ($(CONFIG_DEVELOPERBOX_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_DEVELOPERBOX_SPI=1' -PROGRAMMER_OBJS += developerbox_spi.o -endif - -ifeq ($(CONFIG_SATAMV), yes) -FEATURE_FLAGS += -D'CONFIG_SATAMV=1' -PROGRAMMER_OBJS += satamv.o -endif - -ifeq ($(CONFIG_LINUX_MTD), yes) -FEATURE_FLAGS += -D'CONFIG_LINUX_MTD=1' -PROGRAMMER_OBJS += linux_mtd.o -endif - -ifeq ($(CONFIG_LINUX_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_LINUX_SPI=1' -PROGRAMMER_OBJS += linux_spi.o -endif - -ifeq ($(CONFIG_MSTARDDC_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_MSTARDDC_SPI=1' -PROGRAMMER_OBJS += mstarddc_spi.o -endif - -ifeq ($(CONFIG_CH341A_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_CH341A_SPI=1' -PROGRAMMER_OBJS += ch341a_spi.o -endif - -ifeq ($(CONFIG_DIGILENT_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_DIGILENT_SPI=1' -PROGRAMMER_OBJS += digilent_spi.o -endif - -ifeq ($(CONFIG_JLINK_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_JLINK_SPI=1' -PROGRAMMER_OBJS += jlink_spi.o -endif - -ifeq ($(CONFIG_NI845X_SPI), yes) -FEATURE_FLAGS += -D'CONFIG_NI845X_SPI=1' -PROGRAMMER_OBJS += ni845x_spi.o -endif - -USE_BITBANG_SPI := $(if $(call filter_deps,$(DEPENDS_ON_BITBANG_SPI)),yes,no) -ifeq ($(USE_BITBANG_SPI), yes) -LIB_OBJS += bitbang_spi.o -endif - -USE_LINUX_I2C := $(if $(call filter_deps,$(DEPENDS_ON_LINUX_I2C)),yes,no) -ifeq ($(USE_LINUX_I2C), yes) -LIB_OBJS += i2c_helper_linux.o -endif - -USE_SERIAL := $(if $(call filter_deps,$(DEPENDS_ON_SERIAL)),yes,no) -ifeq ($(USE_SERIAL), yes) -LIB_OBJS += serial.o -ifeq ($(TARGET_OS), Linux) -LIB_OBJS += custom_baud_linux.o -else -LIB_OBJS += custom_baud.o -endif -endif - -USE_SOCKETS := $(if $(call filter_deps,$(DEPENDS_ON_SOCKETS)),yes,no) -ifeq ($(USE_SOCKETS), yes) -ifeq ($(TARGET_OS), SunOS) -override LDFLAGS += -lsocket -lnsl -endif -endif - -USE_X86_MSR := $(if $(call filter_deps,$(DEPENDS_ON_X86_MSR)),yes,no) -ifeq ($(USE_X86_MSR), yes) -PROGRAMMER_OBJS += hwaccess_x86_msr.o -endif - -USE_X86_PORT_IO := $(if $(call filter_deps,$(DEPENDS_ON_X86_PORT_IO)),yes,no) -ifeq ($(USE_X86_PORT_IO), yes) -FEATURE_FLAGS += -D'__FLASHROM_HAVE_OUTB__=1' -PROGRAMMER_OBJS += hwaccess_x86_io.o -endif - -USE_RAW_MEM_ACCESS := $(if $(call filter_deps,$(DEPENDS_ON_RAW_MEM_ACCESS)),yes,no) -ifeq ($(USE_RAW_MEM_ACCESS), yes) -PROGRAMMER_OBJS += hwaccess_physmap.o -endif - -ifeq (Darwin yes, $(TARGET_OS) $(filter $(USE_X86_MSR) $(USE_X86_PORT_IO) $(USE_RAW_MEM_ACCESS), yes)) -override LDFLAGS += -framework IOKit -framework DirectHW -endif - -ifeq (NetBSD yes, $(TARGET_OS) $(filter $(USE_X86_MSR) $(USE_X86_PORT_IO), yes)) -override LDFLAGS += -l$(shell uname -p) -endif - -ifeq (OpenBSD yes, $(TARGET_OS) $(filter $(USE_X86_MSR) $(USE_X86_PORT_IO), yes)) -override LDFLAGS += -l$(shell uname -m) -endif - -USE_LIBPCI := $(if $(call filter_deps,$(DEPENDS_ON_LIBPCI)),yes,no) -ifeq ($(USE_LIBPCI), yes) -PROGRAMMER_OBJS += pcidev.o -override CFLAGS += $(CONFIG_LIBPCI_CFLAGS) -override LDFLAGS += $(CONFIG_LIBPCI_LDFLAGS) -ifeq ($(TARGET_OS), NetBSD) -# The libpci we want is called libpciutils on NetBSD and needs NetBSD libpci. -PCILIBS += -lpciutils -lpci -else -PCILIBS += -lpci -endif -endif - -ifneq ($(NEED_RAW_ACCESS), ) -# Raw memory, MSR or PCI port I/O access. -FEATURE_CFLAGS += -D'NEED_RAW_ACCESS=1' -PROGRAMMER_OBJS += hwaccess_physmap.o -# Generic Super I/O and EC helpers for raw access -PROGRAMMER_OBJS += sio.o acpi_ec.o -ifeq ($(ARCH), x86) -FEATURE_CFLAGS += -D'__FLASHROM_HAVE_OUTB__=1' -PROGRAMMER_OBJS += hwaccess_x86_io.o hwaccess_x86_msr.o - -ifeq ($(TARGET_OS), NetBSD) -PCILIBS += -l$(shell uname -p) -endif -ifeq ($(TARGET_OS), OpenBSD) -PCILIBS += -l$(shell uname -m) -endif -endif - -ifeq ($(TARGET_OS), Darwin) -# DirectHW framework can be found in the DirectHW library. -PCILIBS += -framework IOKit -framework DirectHW -endif -endif - -USE_LIBUSB1 := $(if $(call filter_deps,$(DEPENDS_ON_LIBUSB1)),yes,no) -ifeq ($(USE_LIBUSB1), yes) -override CFLAGS += $(CONFIG_LIBUSB1_CFLAGS) -override LDFLAGS += $(CONFIG_LIBUSB1_LDFLAGS) -PROGRAMMER_OBJS +=usbdev.o usb_device.o -endif - -USE_LIBFTDI1 := $(if $(call filter_deps,$(DEPENDS_ON_LIBFTDI1)),yes,no) -ifeq ($(USE_LIBFTDI1), yes) -override CFLAGS += $(CONFIG_LIBFTDI1_CFLAGS) -override LDFLAGS += $(CONFIG_LIBFTDI1_LDFLAGS) -ifeq ($(HAS_FT232H), yes) -FEATURE_FLAGS += -D'HAVE_FT232H=1' -endif -endif - -USE_LIB_NI845X := $(if $(call filter_deps,$(DEPENDS_ON_LIB_NI845X)),yes,no) -ifeq ($(USE_LIB_NI845X), yes) -override CFLAGS += $(CONFIG_LIB_NI845X_CFLAGS) -override LDFLAGS += $(CONFIG_LIB_NI845X_LDFLAGS) -endif - -USE_LIBJAYLINK := $(if $(call filter_deps,$(DEPENDS_ON_LIBJAYLINK)),yes,no) -ifeq ($(USE_LIBJAYLINK), yes) -override CFLAGS += $(CONFIG_LIBJAYLINK_CFLAGS) -override LDFLAGS += $(CONFIG_LIBJAYLINK_LDFLAGS) -endif - -ifeq ($(CONFIG_PRINT_WIKI), yes) -FEATURE_FLAGS += -D'CONFIG_PRINT_WIKI=1' -CLI_OBJS += print_wiki.o -endif - -ifeq ($(HAS_UTSNAME), yes) -FEATURE_FLAGS += -D'HAVE_UTSNAME=1' -endif - -ifeq ($(HAS_CLOCK_GETTIME), yes) -FEATURE_FLAGS += -D'HAVE_CLOCK_GETTIME=1' -ifeq ($(HAS_EXTERN_LIBRT), yes) -override LDFLAGS += -lrt -endif -endif - -OBJS = $(CHIP_OBJS) $(PROGRAMMER_OBJS) $(LIB_OBJS) - - -all: $(PROGRAM)$(EXEC_SUFFIX) $(PROGRAM).8 -ifeq ($(ARCH), x86) - @+$(MAKE) -C util/ich_descriptors_tool/ HOST_OS=$(HOST_OS) TARGET_OS=$(TARGET_OS) -endif - -config: - @echo Building flashrom version $(VERSION) - @echo -n "C compiler found: " - @if [ $(CC_WORKING) = yes ]; \ - then $(CC) --version 2>/dev/null | head -1; \ - else echo no; echo Aborting.; exit 1; fi - @echo "Target arch: $(ARCH)" - @if [ $(ARCH) = unknown ]; then echo Aborting.; exit 1; fi - @echo "Target OS: $(TARGET_OS)" - @if [ $(TARGET_OS) = unknown ]; then echo Aborting.; exit 1; fi - @if [ $(TARGET_OS) = libpayload ] && ! $(CC) --version 2>&1 | grep -q coreboot; then \ - echo " Warning: It seems you are not using coreboot's reference compiler."; \ - echo " This might work but usually does not, please beware."; fi - @echo "Target endian: $(ENDIAN)" - @if [ $(ENDIAN) = unknown ]; then echo Aborting.; exit 1; fi - @echo Dependency libpci found: $(HAS_LIBPCI) $(CONFIG_LIBPCI_VERSION) - @if [ $(HAS_LIBPCI) = yes ]; then \ - echo " Checking for old \"pci_get_dev()\": $(HAS_PCI_OLD_GET_DEV)";\ - echo " CFLAGS: $(CONFIG_LIBPCI_CFLAGS)"; \ - echo " LDFLAGS: $(CONFIG_LIBPCI_LDFLAGS)"; \ - fi - @echo Dependency libusb1 found: $(HAS_LIBUSB1) $(CONFIG_LIBUSB1_VERSION) - @if [ $(HAS_LIBUSB1) = yes ]; then \ - echo " CFLAGS: $(CONFIG_LIBUSB1_CFLAGS)"; \ - echo " LDFLAGS: $(CONFIG_LIBUSB1_LDFLAGS)"; \ - fi - @echo Dependency libjaylink found: $(HAS_LIBJAYLINK) $(CONFIG_LIBJAYLINK_VERSION) - @if [ $(HAS_LIBJAYLINK) = yes ]; then \ - echo " CFLAGS: $(CONFIG_LIBJAYLINK_CFLAGS)"; \ - echo " LDFLAGS: $(CONFIG_LIBJAYLINK_LDFLAGS)"; \ - fi - @echo Dependency NI-845x found: $(HAS_LIB_NI845X) - @if [ $(HAS_LIB_NI845X) = yes ]; then \ - echo " CFLAGS: $(CONFIG_LIB_NI845X_CFLAGS)"; \ - echo " LDFLAGS: $(CONFIG_LIB_NI845X_LDFLAGS)"; \ - fi - @echo Dependency libftdi1 found: $(HAS_LIBFTDI1) $(CONFIG_LIBFTDI1_VERSION) - @if [ $(HAS_LIBFTDI1) = yes ]; then \ - echo " Checking for \"TYPE_232H\" in \"enum ftdi_chip_type\": $(HAS_FT232H)"; \ - echo " CFLAGS: $(CONFIG_LIBFTDI1_CFLAGS)"; \ - echo " LDFLAGS: $(CONFIG_LIBFTDI1_LDFLAGS)"; \ - fi - @echo "Checking for header \"mtd/mtd-user.h\": $(HAS_LINUX_MTD)" - @echo "Checking for header \"linux/spi/spidev.h\": $(HAS_LINUX_SPI)" - @echo "Checking for header \"linux/i2c-dev.h\": $(HAS_LINUX_I2C)" - @echo "Checking for header \"linux/i2c.h\": $(HAS_LINUX_I2C)" - @echo "Checking for header \"sys/utsname.h\": $(HAS_UTSNAME)" - @echo "Checking for function \"clock_gettime\": $(HAS_CLOCK_GETTIME)" - @echo "Checking for external \"librt\": $(HAS_EXTERN_LIBRT)" - @if ! [ "$(PROGRAMMER_OBJS)" ]; then \ - echo "You have to enable at least one programmer driver!"; \ - exit 1; \ - fi - @if [ "$(UNSUPPORTED_FEATURES)" ]; then \ - echo "The following features are unavailable on your machine: $(UNSUPPORTED_FEATURES)" \ - exit 1; \ - fi - -%.o: %.c | config - $(CC) -MMD $(CFLAGS) $(CPPFLAGS) $(FLASHROM_CFLAGS) $(FEATURE_FLAGS) $(SCMDEF) -o $@ -c $< - -$(PROGRAM)$(EXEC_SUFFIX): $(CLI_OBJS) libflashrom.a - $(CC) -o $@ $^ $(LDFLAGS) - -libflashrom.a: $(OBJS) - $(AR) rcs $@ $^ - $(RANLIB) $@ - -$(PROGRAM).8.html: $(PROGRAM).8 - @groff -mandoc -Thtml $< >$@ - -$(PROGRAM).8: $(PROGRAM).8.tmpl - @# Add the man page change date and version to the man page - @sed -e 's#.TH FLASHROM 8 .*#.TH FLASHROM 8 "$(MAN_DATE)" "$(VERSION)" "$(MAN_DATE)"#' <$< >$@ - -strip: $(PROGRAM)$(EXEC_SUFFIX) - $(STRIP) $(STRIP_ARGS) $(PROGRAM)$(EXEC_SUFFIX) - -# Make sure to add all names of generated binaries here. -# This includes all frontends and libflashrom. -# We don't use EXEC_SUFFIX here because we want to clean everything. -clean: - rm -f $(PROGRAM) $(PROGRAM).exe libflashrom.a $(filter-out Makefile.d, $(wildcard *.d *.o platform/*.d platform/*.o)) \ - $(PROGRAM).8 $(PROGRAM).8.html $(BUILD_DETAILS_FILE) - @+$(MAKE) -C util/ich_descriptors_tool/ clean - -install: $(PROGRAM)$(EXEC_SUFFIX) $(PROGRAM).8 - mkdir -p $(DESTDIR)$(PREFIX)/sbin - mkdir -p $(DESTDIR)$(MANDIR)/man8 - $(INSTALL) -m 0755 $(PROGRAM)$(EXEC_SUFFIX) $(DESTDIR)$(PREFIX)/sbin - $(INSTALL) -m 0644 $(PROGRAM).8 $(DESTDIR)$(MANDIR)/man8 - -libinstall: libflashrom.a include/libflashrom.h - mkdir -p $(DESTDIR)$(PREFIX)/lib - $(INSTALL) -m 0644 libflashrom.a $(DESTDIR)$(PREFIX)/lib - mkdir -p $(DESTDIR)$(PREFIX)/include - $(INSTALL) -m 0644 include/libflashrom.h $(DESTDIR)$(PREFIX)/include - -_export: $(PROGRAM).8 - @rm -rf "$(EXPORTDIR)/flashrom-$(RELEASENAME)" - @mkdir -p "$(EXPORTDIR)/flashrom-$(RELEASENAME)" - @git archive HEAD | tar -x -C "$(EXPORTDIR)/flashrom-$(RELEASENAME)" -# Generate versioninfo.inc containing metadata that would not be available in exported sources otherwise. - @echo "VERSION = $(VERSION)" > "$(EXPORTDIR)/flashrom-$(RELEASENAME)/versioninfo.inc" - @echo "MAN_DATE = $(MAN_DATE)" >> "$(EXPORTDIR)/flashrom-$(RELEASENAME)/versioninfo.inc" -# Restore modification date of all tracked files not marked 'export-ignore' in .gitattributes. -# sed is required to filter out file names having the attribute set. -# The sed program saves the file name in the hold buffer and then checks if the respective value is 'set'. -# If so it ignores the rest of the program, which otherwise restores the file name and prints it. - @git ls-tree -r -z -t --full-name --name-only HEAD | \ - git check-attr -z --stdin export-ignore | \ - sed -zne 'x;n;n;{/^set$$/b;};x;p;' | \ - xargs -0 sh -c 'for f; do \ - touch -d $$(git log --pretty=format:%cI -1 HEAD -- "$$f") \ - "$(EXPORTDIR)/flashrom-$(RELEASENAME)/$$f"; \ - done' dummy_arg0 - -export: _export - @echo "Exported $(EXPORTDIR)/flashrom-$(RELEASENAME)/" - - -# TAROPTIONS reduces information leakage from the packager's system. -# If other tar programs support command line arguments for setting uid/gid of -# stored files, they can be handled here as well. -TAROPTIONS = $(shell LC_ALL=C tar --version|grep -q GNU && echo "--owner=root --group=root") - -tarball: _export - @tar -cj --format=ustar -f "$(EXPORTDIR)/flashrom-$(RELEASENAME).tar.bz2" -C $(EXPORTDIR)/ \ - $(TAROPTIONS) "flashrom-$(RELEASENAME)/" -# Delete the exported directory again because it is most likely what's expected by the user. - @rm -rf "$(EXPORTDIR)/flashrom-$(RELEASENAME)" - @echo Created "$(EXPORTDIR)/flashrom-$(RELEASENAME).tar.bz2" - -libpayload: clean - make CC="CC=i386-elf-gcc lpgcc" AR=i386-elf-ar RANLIB=i386-elf-ranlib - -.PHONY: all install clean distclean config _export export tarball libpayload - -# Disable implicit suffixes and built-in rules (for performance and profit) -.SUFFIXES: - --include $(OBJS:.o=.d) diff --git a/Makefile.d/arch_test.h b/Makefile.d/arch_test.h deleted file mode 100644 index 654f8e562..000000000 --- a/Makefile.d/arch_test.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is part of the flashrom project. - * - * Copyright (C) 2011 Carl-Daniel Hailfinger - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/* - * This file determinate the target architecture. It should only be used - * by the Makefile - */ - -#if defined (__i386__) || defined (__x86_64__) || defined(__amd64__) - #define __FLASHROM_ARCH__ "x86" -#elif defined (__mips) || defined (__mips__) || defined (__MIPS__) || defined (mips) - #define __FLASHROM_ARCH__ "mips" -#elif defined(__powerpc) || defined(__powerpc__) || defined(__powerpc64__) || defined(__POWERPC__) || \ - defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || \ - defined(_ARCH_PPC64) || defined(__ppc) - #define __FLASHROM_ARCH__ "ppc" -#elif defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_ARM) || defined(_M_ARM) || defined(__arm) || \ - defined(__aarch64__) - #define __FLASHROM_ARCH__ "arm" -#elif defined (__sparc__) || defined (__sparc) - #define __FLASHROM_ARCH__ "sparc" -#elif defined (__alpha__) - #define __FLASHROM_ARCH__ "alpha" -#elif defined (__hppa__) || defined (__hppa) - #define __FLASHROM_ARCH__ "hppa" -#elif defined (__m68k__) - #define __FLASHROM_ARCH__ "m68k" -#elif defined (__riscv) - #define __FLASHROM_ARCH__ "riscv" -#elif defined (__sh__) - #define __FLASHROM_ARCH__ "sh" -#elif defined(__s390__) || defined(__s390x__) || defined(__zarch__) - #define __FLASHROM_ARCH__ "s390" -#elif defined(__arc__) - #define __FLASHROM_ARCH__ "arc" -#elif defined(__ARC64__) - #define __FLASHROM_ARCH__ "arc64" -#elif defined(__e2k__) - #define __FLASHROM_ARCH__ "e2k" -#else - #define __FLASHROM_ARCH__ "unknown" -#endif -__FLASHROM_ARCH__ diff --git a/Makefile.d/cc_test.c b/Makefile.d/cc_test.c deleted file mode 100644 index 0610964d8..000000000 --- a/Makefile.d/cc_test.c +++ /dev/null @@ -1,6 +0,0 @@ -int main(int argc, char **argv) -{ - (void)argc; - (void)argv; - return 0; -} diff --git a/Makefile.d/clock_gettime_test.c b/Makefile.d/clock_gettime_test.c deleted file mode 100644 index 000aa425f..000000000 --- a/Makefile.d/clock_gettime_test.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -int main(int argc, char **argv) -{ - (void)argc; - (void)argv; - struct timespec res; - clock_gettime(CLOCK_REALTIME, &res); - return 0; -} diff --git a/Makefile.d/endian_test.h b/Makefile.d/endian_test.h deleted file mode 100644 index 36658b318..000000000 --- a/Makefile.d/endian_test.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file is part of the flashrom project. - * - * Copyright (C) 2011 Carl-Daniel Hailfinger - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/* - * This file determinate the target endian. It should only be used my the Makefile - */ - -#if defined (__i386__) || defined (__x86_64__) || defined(__amd64__) -/* All x86 is little-endian. */ -#define __FLASHROM_LITTLE_ENDIAN__ 1 -#elif defined (__mips) || defined (__mips__) || defined (__MIPS__) || defined (mips) -/* MIPS can be either endian. */ -#if defined (__MIPSEL) || defined (__MIPSEL__) || defined (_MIPSEL) || defined (MIPSEL) -#define __FLASHROM_LITTLE_ENDIAN__ 1 -#elif defined (__MIPSEB) || defined (__MIPSEB__) || defined (_MIPSEB) || defined (MIPSEB) -#define __FLASHROM_BIG_ENDIAN__ 1 -#endif -#elif defined(__powerpc) || defined(__powerpc__) || defined(__powerpc64__) || defined(__POWERPC__) || \ - defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || \ - defined(_ARCH_PPC64) || defined(__ppc) -/* PowerPC can be either endian. */ -#if defined (_BIG_ENDIAN) || defined (__BIG_ENDIAN__) -#define __FLASHROM_BIG_ENDIAN__ 1 -#elif defined (_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) -#define __FLASHROM_LITTLE_ENDIAN__ 1 -#endif -#elif defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_ARM) || defined(_M_ARM) || defined(__arm) || \ - defined(__aarch64__) -/* ARM can be either endian. */ -#if defined (__ARMEB__) || defined (__BIG_ENDIAN__) -#define __FLASHROM_BIG_ENDIAN__ 1 -#elif defined (__ARMEL__) || defined (__LITTLE_ENDIAN__) -#define __FLASHROM_LITTLE_ENDIAN__ 1 -#endif -#elif defined (__sparc__) || defined (__sparc) -/* SPARC is big endian in general (but allows to access data in little endian too). */ -#define __FLASHROM_BIG_ENDIAN__ 1 -#elif defined(__arc__) -#if defined(__BIG_ENDIAN__) -#define __FLASHROM_BIG_ENDIAN__ 1 -#else -#define __FLASHROM_LITTLE_ENDIAN__ 1 -#endif -#endif - -#if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__) -/* If architecture-specific approaches fail try generic variants. First: BSD (works about everywhere). */ -#if !(defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(__WINDOWS__)) -#include -#if defined (__BYTE_ORDER) -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define __FLASHROM_LITTLE_ENDIAN__ -#elif __BYTE_ORDER == __BIG_ENDIAN -#define __FLASHROM_BIG_ENDIAN__ -#else -#error Unknown byte order! -#endif -#endif /* defined __BYTE_ORDER */ -#endif /* !IS_WINDOWS */ -#if !defined (__FLASHROM_BIG_ENDIAN__) && !defined (__FLASHROM_LITTLE_ENDIAN__) -/* Nonstandard libc-specific macros for determining endianness. */ -/* musl provides an endian.h as well... but it can not be detected from within C. */ -#if defined(__GLIBC__) -#include -#if BYTE_ORDER == LITTLE_ENDIAN -#define __FLASHROM_LITTLE_ENDIAN__ 1 -#elif BYTE_ORDER == BIG_ENDIAN -#define __FLASHROM_BIG_ENDIAN__ 1 -#endif -#endif -#endif -#endif -#if defined(__FLASHROM_LITTLE_ENDIAN__) -"little" -#else -"big" -#endif diff --git a/Makefile.d/ft232h_test.c b/Makefile.d/ft232h_test.c deleted file mode 100644 index 21bc99589..000000000 --- a/Makefile.d/ft232h_test.c +++ /dev/null @@ -1,3 +0,0 @@ -#include - -enum ftdi_chip_type type = TYPE_232H; \ No newline at end of file diff --git a/Makefile.d/linux_i2c_test.c b/Makefile.d/linux_i2c_test.c deleted file mode 100644 index 768226bab..000000000 --- a/Makefile.d/linux_i2c_test.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include - -int main(int argc, char **argv) -{ - (void)argc; - (void)argv; - return 0; -} diff --git a/Makefile.d/linux_mtd_test.c b/Makefile.d/linux_mtd_test.c deleted file mode 100644 index d254e242c..000000000 --- a/Makefile.d/linux_mtd_test.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -int main(int argc, char **argv) -{ - (void)argc; - (void)argv; - return 0; -} diff --git a/Makefile.d/linux_spi_test.c b/Makefile.d/linux_spi_test.c deleted file mode 100644 index a4d265786..000000000 --- a/Makefile.d/linux_spi_test.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include - -int main(int argc, char **argv) -{ - (void)argc; - (void)argv; - return 0; -} diff --git a/Makefile.d/os_test.h b/Makefile.d/os_test.h deleted file mode 100644 index 17045b254..000000000 --- a/Makefile.d/os_test.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is part of the flashrom project. - * - * Copyright (C) 2011 Carl-Daniel Hailfinger - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/* - * This file determinate the target os. It should only be used my the Makefile - */ - -// Solaris -#if defined (__sun) && (defined(__i386) || defined(__amd64)) -#define __FLASHROM_OS__ "SunOS" -// OS X -#elif defined(__MACH__) && defined(__APPLE__) -#define __FLASHROM_OS__ "Darwin" -// FreeBSD -#elif defined(__FreeBSD__) -#define __FLASHROM_OS__ "FreeBSD" -// FreeBSD with glibc-based userspace (e.g. Debian/kFreeBSD) -#elif defined(__FreeBSD_kernel__) && defined(__GLIBC__) -#define __FLASHROM_OS__ "FreeBSD-glibc" -// DragonFlyBSD -#elif defined(__DragonFly__) -#define __FLASHROM_OS__ "DragonFlyBSD" -// NetBSD -#elif defined(__NetBSD__) -#define __FLASHROM_OS__ "NetBSD" -// OpenBSD -#elif defined(__OpenBSD__) -#define __FLASHROM_OS__ "OpenBSD" -// DJGPP -#elif defined(__DJGPP__) -#define __FLASHROM_OS__ "DOS" -// MinGW (always has _WIN32 available) -#elif defined(__MINGW32__) -#define __FLASHROM_OS__ "MinGW" -// Cygwin (usually without _WIN32) -#elif defined( __CYGWIN__) -#define __FLASHROM_OS__ "Cygwin" -// libpayload -#elif defined(__LIBPAYLOAD__) -#define __FLASHROM_OS__ "libpayload" -// GNU Hurd -#elif defined(__gnu_hurd__) -#define __FLASHROM_OS__ "Hurd" -// Linux -#elif defined(__linux__) - // There are various flags in use on Android apparently. __ANDROID__ seems to be the most trustworthy. - #if defined(__ANDROID__) - #define __FLASHROM_OS__ "Android" - #else - #define __FLASHROM_OS__ "Linux" - #endif -#else -#define __FLASHROM_OS__ "unknown" -#endif -__FLASHROM_OS__ diff --git a/Makefile.d/pci_old_get_dev_test.c b/Makefile.d/pci_old_get_dev_test.c deleted file mode 100644 index 322365159..000000000 --- a/Makefile.d/pci_old_get_dev_test.c +++ /dev/null @@ -1,17 +0,0 @@ -/* Avoid a failing test due to libpci header symbol shadowing breakage */ -#define index shadow_workaround_index -#if !defined __NetBSD__ -#include -#else -#include -#endif -struct pci_access *pacc; -struct pci_dev *dev = {0}; -int main(int argc, char **argv) -{ - (void) argc; - (void) argv; - pacc = pci_alloc(); - dev = pci_get_dev(pacc, dev->bus, dev->dev, 1); - return 0; -} diff --git a/Makefile.d/utsname_test.c b/Makefile.d/utsname_test.c deleted file mode 100644 index 7bc666527..000000000 --- a/Makefile.d/utsname_test.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -struct utsname osinfo; -int main(int argc, char **argv) -{ - (void)argc; - (void)argv; - uname(&osinfo); - return 0; -} diff --git a/Makefile.include b/Makefile.include deleted file mode 100644 index a55f6f552..000000000 --- a/Makefile.include +++ /dev/null @@ -1,61 +0,0 @@ -# -# This file is part of the flashrom project. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# - -# Here are functions and macros defined for the Makefile - -define mark_unsupported -$(foreach p,$1, \ - $(if $(filter $($(p)),yes), \ - $(eval UNSUPPORTED_FEATURES += $(p)=yes), \ - $(eval override $(p) := no))) -endef - -define filter_deps -$(strip $(foreach p,$1, \ - $(if $(filter $($(p)),yes), \ - $(p)))) -endef - -define disable_all -$(foreach p,$1, \ - $(eval override $(p) := no)) -endef - -# Run the C Preprocessor with file $1 and return the last line, removing quotes. -define c_macro_test -$(strip $(call debug_shell, $(CC) -E $1 | tail -1 | tr -d '"')) -endef - -define c_compile_test # $1: files to compile, $2: cflags -$(call debug_shell, $(CC) -c -Wall -Werror $2 $1 -o /dev/null && echo yes || echo no) -endef - -define c_link_test # $1: file to compile and link, $2: cflags, $3: ldflags -$(call debug_shell, $(CC) -Wall -Werror $2 $1 $3 -o /dev/null && echo yes || echo no) -endef - -define find_dependency -$(call debug_shell, $(if $(PKG_CONFIG_LIBDIR),PKG_CONFIG_LIBDIR=$(PKG_CONFIG_LIBDIR),) $(PKG_CONFIG) --exists $1 && echo yes || echo no) -endef - -define dependency_version -$(call debug_shell, $(if $(PKG_CONFIG_LIBDIR),PKG_CONFIG_LIBDIR=$(PKG_CONFIG_LIBDIR),) $(PKG_CONFIG) --modversion $1 2>/dev/null) -endef - -define dependency_cflags -$(call debug_shell, $(if $(PKG_CONFIG_LIBDIR),PKG_CONFIG_LIBDIR=$(PKG_CONFIG_LIBDIR),) $(PKG_CONFIG) --cflags $1 2>/dev/null) -endef - -define dependency_ldflags -$(call debug_shell, $(if $(PKG_CONFIG_LIBDIR),PKG_CONFIG_LIBDIR=$(PKG_CONFIG_LIBDIR),) $(PKG_CONFIG) --libs --static $1 2>/dev/null) -endef diff --git a/README b/README deleted file mode 100644 index 49af09e92..000000000 --- a/README +++ /dev/null @@ -1,198 +0,0 @@ -------------------------------------------------------------------------------- -flashrom README -------------------------------------------------------------------------------- - -flashrom is a utility for detecting, reading, writing, verifying and erasing -flash chips. It is often used to flash BIOS/EFI/coreboot/firmware images -in-system using a supported mainboard, but it also supports flashing of network -cards (NICs), SATA controller cards, and other external devices which can -program flash chips. - -It supports a wide range of flash chips (most commonly found in SOIC8, DIP8, -SOIC16, WSON8, PLCC32, DIP32, TSOP32, and TSOP40 packages), which use various -protocols such as LPC, FWH, parallel flash, or SPI. - -Do not use flashrom on laptops (yet)! The embedded controller (EC) present in -many laptops might interact badly with any attempts to communicate with the -flash chip and may brick your laptop. - -Please make a backup of your flash chip before writing to it. - -Please see the flashrom(8) manpage. - - -Packaging ---------- - -To package flashrom and remove dependencies on Git, either use -make export -or -make tarball - -'make export' will export all flashrom files from the Git repository at -revision HEAD into a directory named "$EXPORTDIR/flashrom-$RELEASENAME" -and will additionally add a "versioninfo.inc" file in that directory to -contain the Git revision of the exported tree and a date for the manual -page. - -'make tarball' will simply tar up the result of make export and compress -it with bzip2. - -The snapshot tarballs are the result of 'make tarball' and require no -further processing. Some git files (for example the rust bindings) are omitted -from the tarball, as controlled by the .gitattributes files. - - -Build Instructions ------------------- - -To build flashrom you need to install the following software: - - * C compiler (GCC / clang) - * pkg-config - - * pciutils+libpci (if you want support for mainboard or PCI device flashing) - * libusb (if you want FT2232, Dediprog or USB-Blaster support) - * libftdi (if you want FT2232 or USB-Blaster support) - * libjaylink (if you want support for SEGGER J-Link and compatible devices) - -Linux et al: - - * pciutils / libpci - * pciutils-devel / pciutils-dev / libpci-dev - * zlib-devel / zlib1g-dev (needed if libpci was compiled with libz support) - -On FreeBSD, you need the following ports: - - * devel/gmake - * devel/libpci - -On OpenBSD, you need the following ports: - - * devel/gmake - * sysutils/pciutils - -To compile on Linux, use: - - make - -To compile on FreeBSD, OpenBSD or DragonFly BSD, use: - - gmake - -To compile on Nexenta, use: - - make - -To compile on Solaris, use: - - gmake LDFLAGS="-L$pathtolibpci" CC="gcc -I$pathtopciheaders" CFLAGS=-O2 - -To compile on NetBSD (with pciutils, libftdi, libusb installed in /usr/pkg/), use: - - gmake - -To compile and run on Darwin/Mac OS X: - - Install DirectHW from coresystems GmbH. - DirectHW is available at http://www.coreboot.org/DirectHW . - -To cross-compile on Linux for DOS: - - Get packages of the DJGPP cross compiler and install them: - djgpp-filesystem djgpp-gcc djgpp-cpp djgpp-runtime djgpp-binutils - As an alternative, the DJGPP web site offers packages for download as well: - djcross-binutils-2.29.1-1ap.x86_64.rpm - djcross-gcc-7.2.0-1ap.x86_64.rpm - djcrx-2.05-5.x86_64.rpm - The cross toolchain packages for your distribution may have slightly different - names (look for packages named *djgpp*). - - Alternatively, you could use a script to build it from scratch: - https://github.com/andrewwutw/build-djgpp - - You will need the libpci and libgetopt library source trees and - their compiled static libraries and header files installed in some - directory say libpci-libgetopt/, which will be later specified with - LIBS_BASE parameter during flashrom compilation. Easiest way to - handle it is to put pciutils, libgetopt and flashrom directories - in one subdirectory. There will be an extra subdirectory libpci-libgetopt - created, which will contain compiled libpci and libgetopt. - - Download pciutils 3.5.6 and apply http://flashrom.org/File:Pciutils-3.5.6.patch.gz - Compile pciutils, using following command line: - - make ZLIB=no DNS=no HOST=i386-djgpp-djgpp CROSS_COMPILE=i586-pc-msdosdjgpp- \ - PREFIX=/ DESTDIR=$PWD/../libpci-libgetopt \ - STRIP="--strip-program=i586-pc-msdosdjgpp-strip -s" install install-lib - - Download and compile with 'make' http://flashrom.org/File:Libgetopt.tar.gz - - Copy the libgetopt.a to ../libpci-libgetopt/lib and - getopt.h to ../libpci-libgetopt/include - - Enter the flashrom directory. - - make CC=i586-pc-msdosdjgpp-gcc STRIP=i586-pc-msdosdjgpp-strip LIBS_BASE=../libpci-libgetopt/ strip - - If you like, you can compress the resulting executable with UPX: - - upx -9 flashrom.exe - - To run flashrom.exe, download http://flashrom.org/File:Csdpmi7b.zip and - unpack CWSDPMI.EXE into the current directory or one in PATH. - -To cross-compile on Linux for Windows: - - Get packages of the MinGW cross compiler and install them: - mingw32-filesystem mingw32-cross-cpp mingw32-cross-binutils mingw32-cross-gcc - mingw32-runtime mingw32-headers - The cross toolchain packages for your distribution may have slightly different - names (look for packages named *mingw*). - PCI-based programmers (internal etc.) are not supported on Windows. - Run (change CC= and STRIP= settings where appropriate) - make CC=i686-w64-mingw32-gcc STRIP=i686-w64-mingw32-strip - -Processor architecture dependent features: - - On non-x86 architectures a few programmers don't work (yet) because they - use port-based I/O which is not directly available on non-x86. Those - programmers will be disabled automatically if you run "make". - -Compiler quirks: - -If you are using clang and if you want to enable only one driver, you may hit an -overzealous compiler warning from clang. Compile with "make WARNERROR=no" to -force it to continue and enjoy. - -Bindings: - - Foreign function interface bindings for the rust language are included in the - bindings folder. These are not compiled as part of the normal build process. - See the readme under bindings/rust for more information. - -Installation ------------- - -In order to install flashrom and the manpage into /usr/local, type: - - make install - -For installation in a different directory use DESTDIR, e.g. like this: - - make DESTDIR=/usr install - -If you have insufficient permissions for the destination directory, use sudo -by adding sudo in front of the commands above. - - -Contact -------- - -The official flashrom website is: - - http://www.flashrom.org/ - -Available contact methods are - - https://www.flashrom.org/Contact diff --git a/README.rst b/README.rst new file mode 100644 index 000000000..29005172e --- /dev/null +++ b/README.rst @@ -0,0 +1,45 @@ +flashrom README +=============== + +flashrom is a utility for detecting, reading, writing, verifying and erasing +flash chips. It is often used to flash BIOS/EFI/coreboot/firmware images +in-system using a supported mainboard, but it also supports flashing of network +cards (NICs), SATA controller cards, and other external devices which can +program flash chips. + +It supports a wide range of flash chips (most commonly found in SOIC8, DIP8, +SOIC16, WSON8, PLCC32, DIP32, TSOP32, and TSOP40 packages), which use various +protocols such as LPC, FWH, parallel flash, or SPI. + +Do not use flashrom on laptops (yet)! The embedded controller (EC) present in +many laptops might interact badly with any attempts to communicate with the +flash chip and may brick your laptop. + +Please make a backup of your flash chip before writing to it. + +Please see the flashrom(8) manpage :doc:`classic_cli_manpage`. + + +Building / installing / packaging +--------------------------------- + +flashrom is built with **meson**. TLDR: + +:: + + meson setup builddir + meson compile -C builddir + meson test -C builddir + meson install -C builddir + +For full detailed instructions, follow the information in +:doc:`dev_guide/building_from_source` + +Contact +------- + +The official flashrom website is: + + https://www.flashrom.org/ + +For available contact methods see :doc:`contact` diff --git a/VERSION b/VERSION new file mode 100644 index 000000000..4a062329a --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1.5.0-devel diff --git a/amd_imc.c b/amd_imc.c index 4d3715e85..d57728e56 100644 --- a/amd_imc.c +++ b/amd_imc.c @@ -60,7 +60,7 @@ static int mbox_wait_ack(uint16_t mbox_port) msg_pwarn("IMC MBOX: Timeout!\n"); return 1; } - programmer_delay(1000); + default_delay(1000); } return 0; } @@ -122,7 +122,7 @@ static int imc_resume(void *data) int ret = imc_send_cmd(dev, 0xb5); if (ret != 0) - msg_pinfo("Resuming IMC failed)\n"); + msg_pinfo("Resuming IMC failed.\n"); else msg_pdbg2("IMC resumed.\n"); return ret; diff --git a/asm106x.c b/asm106x.c new file mode 100644 index 000000000..0c9cf111d --- /dev/null +++ b/asm106x.c @@ -0,0 +1,154 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2023 Alex Badea + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include "programmer.h" +#include "platform/pci.h" + +#define PCI_VENDOR_ID_ASMEDIA 0x1b21 + +#define ASM106X_REG_DATA 0xf0 +#define ASM106X_REG_CTRL 0xf4 +#define ASM106X_CTRL_RUN 0x20 /* SPI master is running */ +#define ASM106X_CTRL_CSN 0x10 /* CS_n pin output */ +#define ASM106X_CTRL_WRITE 0x08 /* 0=read, 1=write */ +#define ASM106X_CTRL_MASK 0xc0 /* unknown, untouched */ + +struct asm106x_data { + struct pci_dev *pci; +}; + +static const struct dev_entry asm106x_devs[] = { + {PCI_VENDOR_ID_ASMEDIA, 0x0612, OK, "ASMedia", "ASM106x"}, + + {0}, +}; + +static int asm106x_wait_ready(struct pci_dev *pci, uint8_t *pval) +{ + unsigned int timeout = 100; + uint8_t val; + + while (timeout) { + val = pci_read_byte(pci, ASM106X_REG_CTRL); + msg_pdbg2("asm106x status %#02"PRIx8" tries %d\n", val, timeout); + if (!(val & ASM106X_CTRL_RUN)) { + if (pval) + *pval = val; + return 0; + } + default_delay(10); + timeout--; + } + + msg_pdbg("asm106x timed out, ctrl %#02"PRIx8"\n", val); + return 1; +} + + +static int asm106x_command(const struct flashctx *flash, + unsigned int writecnt, unsigned int readcnt, + const unsigned char *writearr, unsigned char *readarr) +{ + struct asm106x_data *data = flash->mst->spi.data; + uint8_t ctrl; + int rv = 1; + + msg_pdbg2("asm106x command: wr %d rd %d\n", writecnt, readcnt); + if (asm106x_wait_ready(data->pci, &ctrl)) + return 1; + ctrl &= ASM106X_CTRL_MASK; + + while (writecnt) { + const unsigned int chunk = min(writecnt, 4); + uint32_t val = 0; + + for (int k = chunk-1; k >= 0; k--) + val = (val << 8) | writearr[k]; + msg_pdbg2("asm106x write %#08"PRIx32" chunk %u\n", val, chunk); + pci_write_long(data->pci, ASM106X_REG_DATA, val); + pci_write_byte(data->pci, ASM106X_REG_CTRL, + ctrl | ASM106X_CTRL_RUN | ASM106X_CTRL_WRITE | chunk); + if (asm106x_wait_ready(data->pci, NULL)) + goto out; + writecnt -= chunk; + writearr += chunk; + } + while (readcnt) { + const unsigned int chunk = min(readcnt, 4); + + pci_write_byte(data->pci, ASM106X_REG_CTRL, + ctrl | ASM106X_CTRL_RUN | chunk); + if (asm106x_wait_ready(data->pci, NULL)) + goto out; + + uint32_t val = pci_read_long(data->pci, ASM106X_REG_DATA); + msg_pdbg2("asm106x read %#08"PRIx32" chunk %u\n", val, chunk); + for (unsigned int k = 0; k < chunk; k++) { + readarr[k] = val & 0xff; + val >>= 8; + } + readcnt -= chunk; + readarr += chunk; + } + + rv = 0; +out: + pci_write_byte(data->pci, ASM106X_REG_CTRL, ctrl | ASM106X_CTRL_CSN); + return rv; +} + +static int asm106x_shutdown(void *data) +{ + free(data); + return 0; +} + +static const struct spi_master asm106x_spi_master = { + .features = SPI_MASTER_4BA, + .max_data_read = MAX_DATA_READ_UNLIMITED, + .max_data_write = MAX_DATA_WRITE_UNLIMITED, + .command = asm106x_command, + .shutdown = asm106x_shutdown, + .read = default_spi_read, + .write_256 = default_spi_write_256, +}; + +static int asm106x_init(const struct programmer_cfg *cfg) +{ + struct pci_dev *pci; + struct asm106x_data *data; + + /* TODO: no BAR required (just config space) */ + pci = pcidev_init(cfg, asm106x_devs, PCI_ROM_ADDRESS); + if (!pci) + return 1; + + data = calloc(1, sizeof(*data)); + if (!data) { + msg_perr("cannot allocate memory for asm106x_data\n"); + return 1; + } + data->pci = pci; + return register_spi_master(&asm106x_spi_master, data); +} + +const struct programmer_entry programmer_asm106x = { + .name = "asm106x", + .type = PCI, + .devs.dev = asm106x_devs, + .init = asm106x_init, +}; diff --git a/at45db.c b/at45db.c index 3f586a21f..6d66a6e99 100644 --- a/at45db.c +++ b/at45db.c @@ -80,9 +80,10 @@ static unsigned int at45db_get_sector_count(struct flashctx *flash) unsigned int i, j; unsigned int cnt = 0; for (i = 0; i < NUM_ERASEFUNCTIONS; i++) { - if (flash->chip->block_erasers[i].block_erase == &spi_erase_at45db_sector) { + const struct block_eraser *const eraser = &flash->chip->block_erasers[i]; + if (eraser->block_erase == SPI_ERASE_AT45DB_SECTOR) { for (j = 0; j < NUM_ERASEREGIONS; j++) { - cnt += flash->chip->block_erasers[i].eraseblocks[j].count; + cnt += eraser->eraseblocks[j].count; } } } @@ -199,12 +200,12 @@ int probe_spi_at45db(struct flashctx *flash) } switch (chip->page_size) { - case 256: chip->gran = write_gran_256bytes; break; - case 264: chip->gran = write_gran_264bytes; break; - case 512: chip->gran = write_gran_512bytes; break; - case 528: chip->gran = write_gran_528bytes; break; - case 1024: chip->gran = write_gran_1024bytes; break; - case 1056: chip->gran = write_gran_1056bytes; break; + case 256: chip->gran = WRITE_GRAN_256BYTES; break; + case 264: chip->gran = WRITE_GRAN_264BYTES; break; + case 512: chip->gran = WRITE_GRAN_512BYTES; break; + case 528: chip->gran = WRITE_GRAN_528BYTES; break; + case 1024: chip->gran = WRITE_GRAN_1024BYTES; break; + case 1056: chip->gran = WRITE_GRAN_1056BYTES; break; default: msg_cerr("%s: unknown page size %d.\n", __func__, chip->page_size); return 0; @@ -309,7 +310,7 @@ static int at45db_wait_ready (struct flashctx *flash, unsigned int us, unsigned return 0; if (ret != 0 || retries-- == 0) return 1; - programmer_delay(us); + programmer_delay(flash, us); } } diff --git a/atahpt.c b/atahpt.c index 89b44c2f8..71fd4d5b5 100644 --- a/atahpt.c +++ b/atahpt.c @@ -74,13 +74,7 @@ static int atahpt_shutdown(void *par_data) static const struct par_master par_master_atahpt = { .chip_readb = atahpt_chip_readb, - .chip_readw = fallback_chip_readw, - .chip_readl = fallback_chip_readl, - .chip_readn = fallback_chip_readn, .chip_writeb = atahpt_chip_writeb, - .chip_writew = fallback_chip_writew, - .chip_writel = fallback_chip_writel, - .chip_writen = fallback_chip_writen, .shutdown = atahpt_shutdown, }; diff --git a/atapromise.c b/atapromise.c index 625eb83b0..9beebf142 100644 --- a/atapromise.c +++ b/atapromise.c @@ -71,7 +71,7 @@ static void atapromise_limit_chip(struct flashchip *chip, size_t rom_size) for (i = 0; i < NUM_ERASEFUNCTIONS; ++i) { if (chip->block_erasers[i].eraseblocks[0].size != size) { chip->block_erasers[i].eraseblocks[0].count = 0; - chip->block_erasers[i].block_erase = NULL; + chip->block_erasers[i].block_erase = NO_BLOCK_ERASE_FUNC; } else { chip->block_erasers[i].eraseblocks[0].size = rom_size; usable_erasers++; @@ -113,13 +113,7 @@ static int atapromise_shutdown(void *par_data) static const struct par_master par_master_atapromise = { .chip_readb = atapromise_chip_readb, - .chip_readw = fallback_chip_readw, - .chip_readl = fallback_chip_readl, - .chip_readn = fallback_chip_readn, .chip_writeb = atapromise_chip_writeb, - .chip_writew = fallback_chip_writew, - .chip_writel = fallback_chip_writel, - .chip_writen = fallback_chip_writen, .shutdown = atapromise_shutdown, }; diff --git a/atavia.c b/atavia.c index 5cbe058f4..da2ab2fc3 100644 --- a/atavia.c +++ b/atavia.c @@ -90,7 +90,7 @@ static bool atavia_ready(struct pci_dev *pcidev_dev) ready = true; break; } else { - programmer_delay(1); + default_delay(1); continue; } } @@ -135,13 +135,7 @@ static uint8_t atavia_chip_readb(const struct flashctx *flash, const chipaddr ad static const struct par_master lpc_master_atavia = { .map_flash_region = atavia_map, .chip_readb = atavia_chip_readb, - .chip_readw = fallback_chip_readw, - .chip_readl = fallback_chip_readl, - .chip_readn = fallback_chip_readn, .chip_writeb = atavia_chip_writeb, - .chip_writew = fallback_chip_writew, - .chip_writel = fallback_chip_writel, - .chip_writen = fallback_chip_writen, }; static int atavia_init(const struct programmer_cfg *cfg) @@ -151,14 +145,14 @@ static int atavia_init(const struct programmer_cfg *cfg) if (strlen(arg) == 0) { msg_perr("Missing argument for offset.\n"); free(arg); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } char *endptr; atavia_offset = (void *)strtoul(arg, &endptr, 0); if (*endptr) { msg_perr("Error: Invalid offset specified: \"%s\".\n", arg); free(arg); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } msg_pinfo("Mapping addresses to base %p.\n", atavia_offset); } @@ -170,9 +164,9 @@ static int atavia_init(const struct programmer_cfg *cfg) /* Test if a flash chip is attached. */ pci_write_long(dev, PCI_ROM_ADDRESS, (uint32_t)PCI_ROM_ADDRESS_MASK); - programmer_delay(90); + default_delay(90); uint32_t base = pci_read_long(dev, PCI_ROM_ADDRESS); - msg_pdbg2("BROM base=0x%08x\n", base); + msg_pdbg2("BROM base=0x%08"PRIx32"\n", base); if ((base & PCI_ROM_ADDRESS_MASK) == 0) { msg_pwarn("Controller thinks there is no ROM attached.\n"); } diff --git a/bindings/rust/libflashrom-sys/Cargo.toml b/bindings/rust/libflashrom-sys/Cargo.toml index 54e016d38..af84b8af8 100644 --- a/bindings/rust/libflashrom-sys/Cargo.toml +++ b/bindings/rust/libflashrom-sys/Cargo.toml @@ -1,6 +1,12 @@ [package] name = "libflashrom-sys" version = "0.1.0" +description = "Native bindings to the libflashrom library." +readme = "../README" +homepage = "https://www.flashrom.org/" +repository = "https://review.coreboot.org/plugins/gitiles/flashrom/" +license = "GPL-2.0-only" +categories = ["external-ffi-bindings", "hardware-support"] links = "flashrom" build = "build.rs" edition = "2021" diff --git a/bindings/rust/libflashrom/Cargo.toml b/bindings/rust/libflashrom/Cargo.toml index 68636dffb..1d8fb5298 100644 --- a/bindings/rust/libflashrom/Cargo.toml +++ b/bindings/rust/libflashrom/Cargo.toml @@ -1,10 +1,14 @@ [package] name = "libflashrom" version = "0.1.0" +description = "Bindings to the libflashrom library." +readme = "../README" +homepage = "https://www.flashrom.org/" +repository = "https://review.coreboot.org/plugins/gitiles/flashrom/" +license = "GPL-2.0-only" +categories = ["api-bindings", "hardware-support"] edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] libflashrom-sys = { path = "../libflashrom-sys" } libc = "0.2.124" diff --git a/bindings/rust/libflashrom/src/lib.rs b/bindings/rust/libflashrom/src/lib.rs index 39e76acbe..c3d4ebdcc 100644 --- a/bindings/rust/libflashrom/src/lib.rs +++ b/bindings/rust/libflashrom/src/lib.rs @@ -312,6 +312,7 @@ pub enum WPError { WpErrRangeUnsupported, WpErrModeUnsupported, WpErrRangeListUnavailable, + WpErrUnsupportedState, WpErrUnknown(libflashrom_sys::flashrom_wp_result), } @@ -341,6 +342,9 @@ impl From for WPError { libflashrom_sys::flashrom_wp_result::FLASHROM_WP_ERR_RANGE_LIST_UNAVAILABLE => { WPError::WpErrRangeListUnavailable } + libflashrom_sys::flashrom_wp_result::FLASHROM_WP_ERR_UNSUPPORTED_STATE => { + WPError::WpErrUnsupportedState + } _ => WPError::WpErrUnknown(e), // this could also be a panic } } @@ -469,6 +473,87 @@ impl Drop for Programmer { } } +/// A translation of the flashrom_flag type +/// +/// Keep this list in sync with libflashrom.h +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub enum FlashromFlag { + FlashromFlagForce, + FlashromFlagForceBoardmismatch, + FlashromFlagVerifyAfterWrite, + FlashromFlagVerifyWholeChip, + FlashromFlagSkipUnreadableRegions, + FlashromFlagSkipUnwritableRegions, +} + +impl From for libflashrom_sys::flashrom_flag { + fn from(e: FlashromFlag) -> Self { + match e { + FlashromFlag::FlashromFlagForce => libflashrom_sys::flashrom_flag::FLASHROM_FLAG_FORCE, + FlashromFlag::FlashromFlagForceBoardmismatch => { + libflashrom_sys::flashrom_flag::FLASHROM_FLAG_FORCE_BOARDMISMATCH + } + FlashromFlag::FlashromFlagVerifyAfterWrite => { + libflashrom_sys::flashrom_flag::FLASHROM_FLAG_VERIFY_AFTER_WRITE + } + FlashromFlag::FlashromFlagVerifyWholeChip => { + libflashrom_sys::flashrom_flag::FLASHROM_FLAG_VERIFY_WHOLE_CHIP + } + FlashromFlag::FlashromFlagSkipUnreadableRegions => { + libflashrom_sys::flashrom_flag::FLASHROM_FLAG_SKIP_UNREADABLE_REGIONS + } + FlashromFlag::FlashromFlagSkipUnwritableRegions => { + libflashrom_sys::flashrom_flag::FLASHROM_FLAG_SKIP_UNWRITABLE_REGIONS + } + e => panic!("Unexpected FlashromFlag: {:?}", e), + } + } +} + +/// Various flags of the flashrom context +/// +/// Keep the struct in sync with the flags in flash.h +#[derive(Debug)] +pub struct FlashromFlags { + pub force: bool, + pub force_boardmismatch: bool, + pub verify_after_write: bool, + pub verify_whole_chip: bool, + pub skip_unreadable_regions: bool, + pub skip_unwritable_regions: bool, +} + +/// Keep the default values in sync with cli_classic.c +impl Default for FlashromFlags { + fn default() -> Self { + Self { + force: false, + force_boardmismatch: false, + verify_after_write: true, + verify_whole_chip: true, + // These flags are introduced to address issues related to CSME locking parts. Setting + // them to false as default values + skip_unreadable_regions: false, + skip_unwritable_regions: false, + } + } +} + +impl fmt::Display for FlashromFlags { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "FlashromFlags {{ force: {}, force_boardmismatch: {}, verify_after_write: {}, verify_whole_chip: {}, skip_unreadable_regions: {}, skip_unwritable_regions: {} }}", + self.force, + self.force_boardmismatch, + self.verify_after_write, + self.verify_whole_chip, + self.skip_unreadable_regions, + self.skip_unwritable_regions, + ) + } +} + impl Chip { /// Probe for a chip /// @@ -701,6 +786,11 @@ impl Chip { }) } } + + /// Set a flag in the given flash context + pub fn flag_set(&mut self, flag: FlashromFlag, value: bool) -> () { + unsafe { libflashrom_sys::flashrom_flag_set(self.ctx.as_mut(), flag.into(), value) } + } } impl Drop for Chip { @@ -875,6 +965,32 @@ impl Layout { } } + /// Exclude a region + /// + /// # Errors + /// + /// This function will return an error if the region is not a valid CString, + /// or if libflashrom returns an error. + pub fn exclude_region(&mut self, region: &str) -> std::result::Result<(), RegionError> { + let err = { + let region = CString::new(region)?; + unsafe { + libflashrom_sys::flashrom_layout_exclude_region( + self.layout.as_mut(), + region.as_ptr(), + ) + } + }; + if err != 0 { + Err(RegionError::ErrorCode(ErrorCode { + function: "flashrom_layout_exclude_region", + code: err, + })) + } else { + Ok(()) + } + } + /// Get the [`Range`] for the given region /// /// # Errors diff --git a/bitbang_spi.c b/bitbang_spi.c index a926b103b..dde5dbc42 100644 --- a/bitbang_spi.c +++ b/bitbang_spi.c @@ -76,10 +76,10 @@ static uint8_t bitbang_spi_read_byte(const struct bitbang_spi_master *master, vo bitbang_spi_set_sck_set_mosi(master, 0, 0, spi_data); else bitbang_spi_set_sck(master, 0, spi_data); - programmer_delay(master->half_period); + default_delay(master->half_period); ret <<= 1; ret |= bitbang_spi_set_sck_get_miso(master, 1, spi_data); - programmer_delay(master->half_period); + default_delay(master->half_period); } return ret; } @@ -90,9 +90,9 @@ static void bitbang_spi_write_byte(const struct bitbang_spi_master *master, uint for (i = 7; i >= 0; i--) { bitbang_spi_set_sck_set_mosi(master, 0, (val >> i) & 1, spi_data); - programmer_delay(master->half_period); + default_delay(master->half_period); bitbang_spi_set_sck(master, 1, spi_data); - programmer_delay(master->half_period); + default_delay(master->half_period); } } @@ -122,9 +122,9 @@ static int bitbang_spi_send_command(const struct flashctx *flash, readarr[i] = bitbang_spi_read_byte(master, data->spi_data); bitbang_spi_set_sck(master, 0, data->spi_data); - programmer_delay(master->half_period); + default_delay(master->half_period); bitbang_spi_set_cs(master, 1, data->spi_data); - programmer_delay(master->half_period); + default_delay(master->half_period); /* FIXME: Run bitbang_spi_release_bus here or in programmer init? */ bitbang_spi_release_bus(master, data->spi_data); @@ -143,12 +143,9 @@ static const struct spi_master spi_master_bitbang = { .max_data_read = MAX_DATA_READ_UNLIMITED, .max_data_write = MAX_DATA_WRITE_UNLIMITED, .command = bitbang_spi_send_command, - .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = bitbang_spi_shutdown, - .probe_opcode = default_spi_probe_opcode, }; int register_spi_bitbang_master(const struct bitbang_spi_master *master, void *spi_data) @@ -165,6 +162,9 @@ int register_spi_bitbang_master(const struct bitbang_spi_master *master, void *s } struct bitbang_spi_master_data *data = calloc(1, sizeof(*data)); + if (!data) + return ERROR_FLASHROM_FATAL; + data->master = master; if (spi_data) data->spi_data = spi_data; diff --git a/board_enable.c b/board_enable.c index 91e92edf4..05bd4056a 100644 --- a/board_enable.c +++ b/board_enable.c @@ -124,7 +124,7 @@ static int fdc37b787_gpio50_raise(uint16_t port) * Suited for: * - Nokia IP530: Intel 440BX + PIIX4 + FDC37B787 */ -static int fdc37b787_gpio50_raise_3f0(void) +static int fdc37b787_gpio50_raise_3f0(struct board_cfg *cfg) { return fdc37b787_gpio50_raise(0x3f0); } @@ -435,7 +435,7 @@ static int winbond_gpio_set(uint16_t base, enum winbond_id chipid, * - Agami Aruma * - IWILL DK8-HTX */ -static int w83627hf_gpio24_raise_2e(void) +static int w83627hf_gpio24_raise_2e(struct board_cfg *cfg) { return winbond_gpio_set(0x2e, WINBOND_W83627HF_ID, 24, 1); } @@ -446,7 +446,7 @@ static int w83627hf_gpio24_raise_2e(void) * Suited for: * - MSI MS-6577 */ -static int w83627hf_gpio25_raise_2e(void) +static int w83627hf_gpio25_raise_2e(struct board_cfg *cfg) { return winbond_gpio_set(0x2e, WINBOND_W83627HF_ID, 25, 1); } @@ -457,7 +457,7 @@ static int w83627hf_gpio25_raise_2e(void) * Suited for: * - ASUS A8N-VM CSM: AMD Socket 939 + GeForce 6150 (C51) + MCP51 */ -static int w83627ehf_gpio22_raise_2e(void) +static int w83627ehf_gpio22_raise_2e(struct board_cfg *cfg) { return winbond_gpio_set(0x2e, WINBOND_W83627EHF_ID, 22, 1); } @@ -468,7 +468,7 @@ static int w83627ehf_gpio22_raise_2e(void) * Suited for: * - MSI K8T Neo2-F V2.0 */ -static int w83627thf_gpio44_raise_2e(void) +static int w83627thf_gpio44_raise_2e(struct board_cfg *cfg) { return winbond_gpio_set(0x2e, WINBOND_W83627THF_ID, 44, 1); } @@ -479,7 +479,7 @@ static int w83627thf_gpio44_raise_2e(void) * Suited for: * - MSI K8N Neo3 */ -static int w83627thf_gpio44_raise_4e(void) +static int w83627thf_gpio44_raise_4e(struct board_cfg *cfg) { return winbond_gpio_set(0x4e, WINBOND_W83627THF_ID, 44, 1); } @@ -535,7 +535,7 @@ static void w83697xx_memw_enable(uint16_t port) * Suited for: * - Biostar M7VIQ: VIA KM266 + VT8235 */ -static int w83697xx_memw_enable_2e(void) +static int w83697xx_memw_enable_2e(struct board_cfg *cfg) { w83697xx_memw_enable(0x2E); @@ -557,7 +557,7 @@ static int w83697xx_memw_enable_2e(void) * - ASRock K7S41: SiS 741 + SiS 963 + W83697HF * - ASRock K7S41GX: SiS 741GX + SiS 963L + W83697HF */ -static int w836xx_memw_enable_2e(void) +static int w836xx_memw_enable_2e(struct board_cfg *cfg) { w836xx_memw_enable(0x2E); @@ -568,7 +568,7 @@ static int w836xx_memw_enable_2e(void) * Suited for: * - Termtek TK-3370 (rev. 2.5b) */ -static int w836xx_memw_enable_4e(void) +static int w836xx_memw_enable_4e(struct board_cfg *cfg) { w836xx_memw_enable(0x4E); @@ -650,7 +650,7 @@ int it8705f_write_enable(uint8_t port) */ ret = 1; } - msg_pdbg("Maximum IT8705F parallel flash decode size is %u.\n", + msg_pdbg("Maximum IT8705F parallel flash decode size is %"PRIu32".\n", max_rom_decode.parallel); if (ret) { msg_pinfo("Not enabling IT8705F flash write.\n"); @@ -703,7 +703,7 @@ static int it8707f_write_enable(uint8_t port) * Suited for: * - ASUS P4SC-E: SiS 651 + 962 + ITE IT8707F */ -static int it8707f_write_enable_2e(void) +static int it8707f_write_enable_2e(struct board_cfg *cfg) { return it8707f_write_enable(0x2e); } @@ -812,7 +812,7 @@ static int via_vt823x_gpio_set(uint8_t gpio, int raise) * Suited for: * - ASUS M2V-MX: VIA K8M890 + VT8237A + IT8716F */ -static int via_vt823x_gpio5_raise(void) +static int via_vt823x_gpio5_raise(struct board_cfg *cfg) { /* On M2V-MX: GPO5 is connected to WP# and TBL#. */ return via_vt823x_gpio_set(5, 1); @@ -822,7 +822,7 @@ static int via_vt823x_gpio5_raise(void) * Suited for: * - VIA EPIA EK & N & NL */ -static int via_vt823x_gpio9_raise(void) +static int via_vt823x_gpio9_raise(struct board_cfg *cfg) { return via_vt823x_gpio_set(9, 1); } @@ -834,7 +834,7 @@ static int via_vt823x_gpio9_raise(void) * We don't need to do this for EPIA M when using coreboot, GPIO15 is never * lowered there. */ -static int via_vt823x_gpio15_raise(void) +static int via_vt823x_gpio15_raise(struct board_cfg *cfg) { return via_vt823x_gpio_set(15, 1); } @@ -846,7 +846,7 @@ static int via_vt823x_gpio15_raise(void) * - MSI KT4V and KT4V-L: AMD K7 + VIA KT400 + VT8235 * - MSI KT4 Ultra: AMD K7 + VIA KT400 + VT8235 */ -static int board_msi_kt4v(void) +static int board_msi_kt4v(struct board_cfg *cfg) { int ret; @@ -863,7 +863,7 @@ static int board_msi_kt4v(void) * We are talking to a proprietary device on SMBus: the AS99127F which does * much more than the Winbond W83781D it tries to be compatible with. */ -static int board_asus_p3b_f(void) +static int board_asus_p3b_f(struct board_cfg *cfg) { /* * Find where the SMBus host is. ASUS sets it to 0xE800; coreboot sets it to 0x0F00. @@ -910,7 +910,7 @@ static int board_asus_p3b_f(void) * We're basically talking to some unknown device on SMBus, my guess * is that it is the Winbond W83781D that lives near the DIP BIOS. */ -static int board_asus_p5a(void) +static int board_asus_p5a(struct board_cfg *cfg) { uint8_t tmp; int i; @@ -984,7 +984,7 @@ static int board_asus_p5a(void) * * It's not a Super I/O but it uses the same index/data port method. */ -static int board_hp_dl145_g3_enable(void) +static int board_hp_dl145_g3_enable(struct board_cfg *cfg) { /* GPIO 0 reg from PM regs */ /* Set GPIO 2 and 5 high, connected to flash WP# and TBL# pins. */ @@ -998,7 +998,7 @@ static int board_hp_dl145_g3_enable(void) * * It's not a Super I/O but it uses the same index/data port method. */ -static int board_hp_dl165_g6_enable(void) +static int board_hp_dl165_g6_enable(struct board_cfg *cfg) { /* Variant of DL145, with slightly different pin placement. */ sio_mask(0xcd6, 0x44, 0x80, 0x80); /* TBL# */ @@ -1007,7 +1007,7 @@ static int board_hp_dl165_g6_enable(void) return 0; } -static int board_ibm_x3455(void) +static int board_ibm_x3455(struct board_cfg *cfg) { /* Raise GPIO13. */ sio_mask(0xcd6, 0x45, 0x20, 0x20); @@ -1019,7 +1019,7 @@ static int board_ibm_x3455(void) * Suited for: * - Elitegroup GeForce6100SM-M: NVIDIA MCP61 + ITE IT8726F */ -static int board_ecs_geforce6100sm_m(void) +static int board_ecs_geforce6100sm_m(struct board_cfg *cfg) { struct pci_dev *dev; uint32_t tmp; @@ -1109,7 +1109,7 @@ static int nvidia_mcp_gpio_set(int gpio, int raise) * - ASUS A8N-LA (HP OEM "Nagami-GL8E"): NVIDIA MCP51 * - ASUS M2NBP-VM CSM: NVIDIA MCP51 */ -static int nvidia_mcp_gpio0_raise(void) +static int nvidia_mcp_gpio0_raise(struct board_cfg *cfg) { return nvidia_mcp_gpio_set(0x00, 1); } @@ -1119,7 +1119,7 @@ static int nvidia_mcp_gpio0_raise(void) * - abit KN8 Ultra: NVIDIA CK804 * - abit KN9 Ultra: NVIDIA MCP55 */ -static int nvidia_mcp_gpio2_lower(void) +static int nvidia_mcp_gpio2_lower(struct board_cfg *cfg) { return nvidia_mcp_gpio_set(0x02, 0); } @@ -1131,7 +1131,7 @@ static int nvidia_mcp_gpio2_lower(void) * - MSI K8NGM2-L: NVIDIA MCP51 * - MSI K9N SLI: NVIDIA MCP55 */ -static int nvidia_mcp_gpio2_raise(void) +static int nvidia_mcp_gpio2_raise(struct board_cfg *cfg) { return nvidia_mcp_gpio_set(0x02, 1); } @@ -1140,7 +1140,7 @@ static int nvidia_mcp_gpio2_raise(void) * Suited for: * - EPoX EP-8NPA7I: Socket 754 + NVIDIA nForce4 4X */ -static int nvidia_mcp_gpio4_raise(void) +static int nvidia_mcp_gpio4_raise(struct board_cfg *cfg) { return nvidia_mcp_gpio_set(0x04, 1); } @@ -1157,7 +1157,7 @@ static int nvidia_mcp_gpio4_raise(void) * b) #TBL is hardwired on that board to a pull-down. It can be * overridden by connecting the two solder points next to F2. */ -static int nvidia_mcp_gpio5_raise(void) +static int nvidia_mcp_gpio5_raise(struct board_cfg *cfg) { return nvidia_mcp_gpio_set(0x05, 1); } @@ -1166,7 +1166,7 @@ static int nvidia_mcp_gpio5_raise(void) * Suited for: * - abit NF7-S: NVIDIA CK804 */ -static int nvidia_mcp_gpio8_raise(void) +static int nvidia_mcp_gpio8_raise(struct board_cfg *cfg) { return nvidia_mcp_gpio_set(0x08, 1); } @@ -1176,7 +1176,7 @@ static int nvidia_mcp_gpio8_raise(void) * - GIGABYTE GA-K8NS Pro-939: Socket 939 + NVIDIA nForce3 + CK8 * - Probably other versions of the GA-K8NS */ -static int nvidia_mcp_gpio0a_raise(void) +static int nvidia_mcp_gpio0a_raise(struct board_cfg *cfg) { return nvidia_mcp_gpio_set(0x0a, 1); } @@ -1186,7 +1186,7 @@ static int nvidia_mcp_gpio0a_raise(void) * - MSI K8N Neo Platinum: Socket 754 + nForce3 Ultra + CK8 * - MSI K8N Neo2 Platinum: Socket 939 + nForce3 Ultra + CK8 */ -static int nvidia_mcp_gpio0c_raise(void) +static int nvidia_mcp_gpio0c_raise(struct board_cfg *cfg) { return nvidia_mcp_gpio_set(0x0c, 1); } @@ -1195,7 +1195,7 @@ static int nvidia_mcp_gpio0c_raise(void) * Suited for: * - abit NF-M2 nView: Socket AM2 + NVIDIA MCP51 */ -static int nvidia_mcp_gpio4_lower(void) +static int nvidia_mcp_gpio4_lower(struct board_cfg *cfg) { return nvidia_mcp_gpio_set(0x04, 0); } @@ -1204,7 +1204,7 @@ static int nvidia_mcp_gpio4_lower(void) * Suited for: * - ASUS P5ND2-SLI Deluxe: LGA775 + nForce4 SLI + MCP04 */ -static int nvidia_mcp_gpio10_raise(void) +static int nvidia_mcp_gpio10_raise(struct board_cfg *cfg) { return nvidia_mcp_gpio_set(0x10, 1); } @@ -1213,7 +1213,7 @@ static int nvidia_mcp_gpio10_raise(void) * Suited for: * - GIGABYTE GA-K8N-SLI: AMD socket 939 + NVIDIA CK804 + ITE IT8712F */ -static int nvidia_mcp_gpio21_raise(void) +static int nvidia_mcp_gpio21_raise(struct board_cfg *cfg) { return nvidia_mcp_gpio_set(0x21, 0x01); } @@ -1222,7 +1222,7 @@ static int nvidia_mcp_gpio21_raise(void) * Suited for: * - EPoX EP-8RDA3+: Socket A + nForce2 Ultra 400 + MCP2 */ -static int nvidia_mcp_gpio31_raise(void) +static int nvidia_mcp_gpio31_raise(struct board_cfg *cfg) { return nvidia_mcp_gpio_set(0x31, 0x01); } @@ -1232,7 +1232,7 @@ static int nvidia_mcp_gpio31_raise(void) * - GIGABYTE GA-K8N51GMF: Socket 754 + Geforce 6100 + MCP51 * - GIGABYTE GA-K8N51GMF-9: Socket 939 + Geforce 6100 + MCP51 */ -static int nvidia_mcp_gpio3b_raise(void) +static int nvidia_mcp_gpio3b_raise(struct board_cfg *cfg) { return nvidia_mcp_gpio_set(0x3b, 1); } @@ -1241,14 +1241,14 @@ static int nvidia_mcp_gpio3b_raise(void) * Suited for: * - Sun Ultra 40 M2: Dual Socket F (1207) + MCP55 */ -static int board_sun_ultra_40_m2(void) +static int board_sun_ultra_40_m2(struct board_cfg *cfg) { int ret; uint8_t reg; uint16_t base; struct pci_dev *dev; - ret = nvidia_mcp_gpio4_lower(); + ret = nvidia_mcp_gpio4_lower(cfg); if (ret) return ret; @@ -1273,7 +1273,7 @@ static int board_sun_ultra_40_m2(void) * Suited for: * - Artec Group DBE61 and DBE62 */ -static int board_artecgroup_dbe6x(void) +static int board_artecgroup_dbe6x(struct board_cfg *cfg) { #define DBE6x_MSR_DIVIL_BALL_OPTS 0x51400015 #define DBE6x_PRI_BOOT_LOC_SHIFT 2 @@ -1317,7 +1317,7 @@ static int board_artecgroup_dbe6x(void) * Datasheet(s) used: * - AMD document 43009 "AMD SB700/710/750 Register Reference Guide" rev. 1.00 */ -static int amd_sbxxx_gpio9_raise(void) +static int amd_sbxxx_gpio9_raise(struct board_cfg *cfg) { struct pci_dev *dev; uint32_t reg; @@ -1431,7 +1431,7 @@ static int intel_piix4_gpo_set(unsigned int gpo, int raise) * - ASUS OPLX-M * - ASUS P2B-N */ -static int intel_piix4_gpo18_lower(void) +static int intel_piix4_gpo18_lower(struct board_cfg *cfg) { return intel_piix4_gpo_set(18, 0); } @@ -1440,7 +1440,7 @@ static int intel_piix4_gpo18_lower(void) * Suited for: * - MSI MS-6163 v2 (MS-6163 Pro): Intel 440BX + PIIX4E + Winbond W83977EF */ -static int intel_piix4_gpo14_raise(void) +static int intel_piix4_gpo14_raise(struct board_cfg *cfg) { return intel_piix4_gpo_set(14, 1); } @@ -1449,7 +1449,7 @@ static int intel_piix4_gpo14_raise(void) * Suited for: * - EPoX EP-BX3 */ -static int intel_piix4_gpo22_raise(void) +static int intel_piix4_gpo22_raise(struct board_cfg *cfg) { return intel_piix4_gpo_set(22, 1); } @@ -1458,7 +1458,7 @@ static int intel_piix4_gpo22_raise(void) * Suited for: * - abit BM6 */ -static int intel_piix4_gpo26_lower(void) +static int intel_piix4_gpo26_lower(struct board_cfg *cfg) { return intel_piix4_gpo_set(26, 0); } @@ -1467,7 +1467,7 @@ static int intel_piix4_gpo26_lower(void) * Suited for: * - Intel SE440BX-2 */ -static int intel_piix4_gpo27_lower(void) +static int intel_piix4_gpo27_lower(struct board_cfg *cfg) { return intel_piix4_gpo_set(27, 0); } @@ -1476,7 +1476,7 @@ static int intel_piix4_gpo27_lower(void) * Suited for: * - Dell OptiPlex GX1 */ -static int intel_piix4_gpo30_lower(void) +static int intel_piix4_gpo30_lower(struct board_cfg *cfg) { return intel_piix4_gpo_set(30, 0); } @@ -1682,7 +1682,7 @@ static int intel_ich_gpio_set(int gpio, int raise) * - ASUS P5LD2-VM DH * - ASUS P5W DH Deluxe */ -static int intel_ich_gpio16_raise(void) +static int intel_ich_gpio16_raise(struct board_cfg *cfg) { return intel_ich_gpio_set(16, 1); } @@ -1691,7 +1691,7 @@ static int intel_ich_gpio16_raise(void) * Suited for: * - HP Puffer2-UL8E (ASUS PTGD-LA OEM): LGA775 + 915 + ICH6 */ -static int intel_ich_gpio18_raise(void) +static int intel_ich_gpio18_raise(struct board_cfg *cfg) { return intel_ich_gpio_set(18, 1); } @@ -1700,7 +1700,7 @@ static int intel_ich_gpio18_raise(void) * Suited for: * - MSI MS-7046: LGA775 + 915P + ICH6 */ -static int intel_ich_gpio19_raise(void) +static int intel_ich_gpio19_raise(struct board_cfg *cfg) { return intel_ich_gpio_set(19, 1); } @@ -1710,7 +1710,7 @@ static int intel_ich_gpio19_raise(void) * - ASUS P5BV-R: LGA775 + 3200 + ICH7 * - AOpen i965GMt-LA: Intel Socket479 + 965GM + ICH8M */ -static int intel_ich_gpio20_raise(void) +static int intel_ich_gpio20_raise(struct board_cfg *cfg) { return intel_ich_gpio_set(20, 1); } @@ -1732,7 +1732,7 @@ static int intel_ich_gpio20_raise(void) * - ASUS TUSL2-C: Intel socket370 + 815 + ICH2 * - Samsung Polaris 32: socket478 + 865P + ICH5 */ -static int intel_ich_gpio21_raise(void) +static int intel_ich_gpio21_raise(struct board_cfg *cfg) { return intel_ich_gpio_set(21, 1); } @@ -1744,7 +1744,7 @@ static int intel_ich_gpio21_raise(void) * - ASUS P4B-MX variant in HP Vectra VL420 SFF: socket478 + 845D + ICH2 * - TriGem Anaheim-3: socket370 + Intel 810 + ICH */ -static int intel_ich_gpio22_raise(void) +static int intel_ich_gpio22_raise(struct board_cfg *cfg) { return intel_ich_gpio_set(22, 1); } @@ -1756,7 +1756,7 @@ static int intel_ich_gpio22_raise(void) * - HP Media Center m7270.fr Desktop PC as "Lithium-UL8E" * - Epson Endeavor MT7700 */ -static int intel_ich_gpio34_raise(void) +static int intel_ich_gpio34_raise(struct board_cfg *cfg) { return intel_ich_gpio_set(34, 1); } @@ -1766,7 +1766,7 @@ static int intel_ich_gpio34_raise(void) * - AOpen i945GMx-VFX: Intel 945GM + ICH7-M used in ... * - FSC ESPRIMO Q5010 (SMBIOS: D2544-B1) */ -static int intel_ich_gpio38_raise(void) +static int intel_ich_gpio38_raise(struct board_cfg *cfg) { return intel_ich_gpio_set(38, 1); } @@ -1775,7 +1775,7 @@ static int intel_ich_gpio38_raise(void) * Suited for: * - ASUS M6Ne (laptop): socket 479M (guessed) + Intel 855PM + ICH4-M */ -static int intel_ich_gpio43_raise(void) +static int intel_ich_gpio43_raise(struct board_cfg *cfg) { return intel_ich_gpio_set(43, 1); } @@ -1784,7 +1784,7 @@ static int intel_ich_gpio43_raise(void) * Suited for: * - HP Vectra VL400: 815 + ICH + PC87360 */ -static int board_hp_vl400(void) +static int board_hp_vl400(struct board_cfg *cfg) { int ret; ret = intel_ich_gpio_set(25, 1); /* Master write enable ? */ @@ -1799,7 +1799,7 @@ static int board_hp_vl400(void) * Suited for: * - HP e-Vectra P2706T: 810E + ICH + PC87364 */ -static int board_hp_p2706t(void) +static int board_hp_p2706t(struct board_cfg *cfg) { int ret; ret = pc8736x_gpio_set(PC87364_ID, 0x25, 1); @@ -1815,7 +1815,7 @@ static int board_hp_p2706t(void) * - ASRock 775i65G: Intel LGA 775 + 865G + ICH5 * - MSI MS-6391 (845 Pro4): Intel Socket478 + 845 + ICH2 */ -static int intel_ich_gpio23_raise(void) +static int intel_ich_gpio23_raise(struct board_cfg *cfg) { return intel_ich_gpio_set(23, 1); } @@ -1825,7 +1825,7 @@ static int intel_ich_gpio23_raise(void) * - GIGABYTE GA-6IEM: Intel Socket370 + i815 + ICH2 * - GIGABYTE GA-8IRML: Intel Socket478 + i845 + ICH2 */ -static int intel_ich_gpio25_raise(void) +static int intel_ich_gpio25_raise(struct board_cfg *cfg) { return intel_ich_gpio_set(25, 1); } @@ -1834,7 +1834,7 @@ static int intel_ich_gpio25_raise(void) * Suited for: * - IBASE MB899: i945GM + ICH7 */ -static int intel_ich_gpio26_raise(void) +static int intel_ich_gpio26_raise(struct board_cfg *cfg) { return intel_ich_gpio_set(26, 1); } @@ -1847,7 +1847,7 @@ static int intel_ich_gpio26_raise(void) * - GIGABYTE GA-8PE667 Ultra 2: socket 478 + i845PE + ICH4 * - MSI MS-6788-40 (aka 848P Neo-V) */ -static int intel_ich_gpio32_raise(void) +static int intel_ich_gpio32_raise(struct board_cfg *cfg) { return intel_ich_gpio_set(32, 1); } @@ -1856,7 +1856,7 @@ static int intel_ich_gpio32_raise(void) * Suited for: * - AOpen i975Xa-YDG: i975X + ICH7 + W83627EHF */ -static int board_aopen_i975xa_ydg(void) +static int board_aopen_i975xa_ydg(struct board_cfg *cfg) { int ret; @@ -1878,7 +1878,7 @@ static int board_aopen_i975xa_ydg(void) * Suited for: * - Acorp 6A815EPD: socket 370 + intel 815 + ICH2 */ -static int board_acorp_6a815epd(void) +static int board_acorp_6a815epd(struct board_cfg *cfg) { int ret; @@ -1894,7 +1894,7 @@ static int board_acorp_6a815epd(void) * Suited for: * - Kontron 986LCD-M: Socket478 + 915GM + ICH7R */ -static int board_kontron_986lcd_m(void) +static int board_kontron_986lcd_m(struct board_cfg *cfg) { int ret; @@ -1961,7 +1961,7 @@ static int via_apollo_gpo_set(int gpio, int raise) * - abit VT6X4: Pro133x + VT82C686A * - abit VA6: Pro133x + VT82C686A */ -static int via_apollo_gpo4_lower(void) +static int via_apollo_gpo4_lower(struct board_cfg *cfg) { return via_apollo_gpo_set(4, 0); } @@ -1970,7 +1970,7 @@ static int via_apollo_gpo4_lower(void) * Suited for: * - Soyo SY-7VCA: Pro133A + VT82C686 */ -static int via_apollo_gpo0_lower(void) +static int via_apollo_gpo0_lower(struct board_cfg *cfg) { return via_apollo_gpo_set(0, 0); } @@ -1983,7 +1983,7 @@ static int via_apollo_gpo0_lower(void) * - GIGABYTE GA-8SIMLFS 2.0 * - GIGABYTE GA-8SIMLH */ -static int sis_gpio0_raise_and_w836xx_memw(void) +static int sis_gpio0_raise_and_w836xx_memw(struct board_cfg *cfg) { struct pci_dev *dev; uint16_t base, temp; @@ -2046,7 +2046,7 @@ static uint16_t smsc_find_runtime(uint16_t sio_port, uint16_t chip_id, * Disable write protection on the Mitac 6513WU. WP# on the FWH is * connected to GP30 on the Super I/O, and TBL# is always high. */ -static int board_mitac_6513wu(void) +static int board_mitac_6513wu(struct board_cfg *cfg) { struct pci_dev *dev; uint16_t rt_port; @@ -2079,7 +2079,7 @@ static int board_mitac_6513wu(void) * Suited for: * - abit AV8: Socket939 + K8T800Pro + VT8237 */ -static int board_abit_av8(void) +static int board_abit_av8(struct board_cfg *cfg) { uint8_t val; @@ -2096,7 +2096,7 @@ static int board_abit_av8(void) * - ASUS A7V333: VIA KT333 + VT8233A + IT8703F * - ASUS A7V8X: VIA KT400 + VT8235 + IT8703F */ -static int it8703f_gpio51_raise(void) +static int it8703f_gpio51_raise(struct board_cfg *cfg) { uint16_t id, base; uint8_t tmp; @@ -2225,7 +2225,7 @@ static int it87_gpio_set(unsigned int gpio, int raise) * Suited for: * - ASUS A7N8X-VM/400: NVIDIA nForce2 IGP2 + IT8712F */ -static int it8712f_gpio12_raise(void) +static int it8712f_gpio12_raise(struct board_cfg *cfg) { return it87_gpio_set(12, 1); } @@ -2235,7 +2235,7 @@ static int it8712f_gpio12_raise(void) * - ASUS A7V600-X: VIA KT600 + VT8237 + IT8712F * - ASUS A7V8X-X: VIA KT400 + VT8235 + IT8712F */ -static int it8712f_gpio31_raise(void) +static int it8712f_gpio31_raise(struct board_cfg *cfg) { return it87_gpio_set(32, 1); } @@ -2245,7 +2245,7 @@ static int it8712f_gpio31_raise(void) * - ASUS P5N-D: NVIDIA MCP51 + IT8718F * - ASUS P5N-E SLI: NVIDIA MCP51 + IT8718F */ -static int it8718f_gpio63_raise(void) +static int it8718f_gpio63_raise(struct board_cfg *cfg) { return it87_gpio_set(63, 1); } @@ -2257,10 +2257,10 @@ static int it8718f_gpio63_raise(void) * - Intel D945GCNL * - MSC Q7 Tunnel Creek Module (Q7-TCTC) */ -static int p2_not_a_laptop(void) +static int p2_not_a_laptop(struct board_cfg *cfg) { /* label this board as not a laptop */ - is_laptop = 0; + cfg->is_laptop = 0; msg_pdbg("Laptop detection overridden by P2 board enable.\n"); return 0; } @@ -2268,10 +2268,10 @@ static int p2_not_a_laptop(void) /* * Suited for all laptops, which are known to *not* have interfering embedded controllers. */ -static int p2_whitelist_laptop(void) +static int p2_whitelist_laptop(struct board_cfg *cfg) { - is_laptop = 1; - laptop_ok = true; + cfg->is_laptop = 1; + cfg->laptop_ok = true; msg_pdbg("Whitelisted laptop detected.\n"); return 0; } @@ -2502,6 +2502,7 @@ const struct board_match board_matches[] = { #endif { 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, P3, NULL, NULL, 0, NT, NULL}, /* end marker */ }; +const size_t board_matches_size = ARRAY_SIZE(board_matches); int selfcheck_board_enables(void) { @@ -2660,7 +2661,7 @@ static const struct board_match *board_match_pci_ids(enum board_match_phase phas return NULL; } -static int board_enable_safetycheck(const struct board_match *board) +static int board_enable_safetycheck(const struct board_match *board, bool force_boardenable) { if (!board) return 1; @@ -2682,16 +2683,12 @@ static int board_enable_safetycheck(const struct board_match *board) } /* FIXME: Should this be identical to board_flash_enable? */ -static int board_handle_phase(enum board_match_phase phase) +static int board_handle_phase(struct board_cfg *cfg, + enum board_match_phase phase, bool force_boardenable) { - const struct board_match *board = NULL; - - board = board_match_pci_ids(phase); - - if (!board) - return 0; + const struct board_match *board = board_match_pci_ids(phase); - if (board_enable_safetycheck(board)) + if (board_enable_safetycheck(board, force_boardenable)) return 0; if (!board->enable) { @@ -2700,25 +2697,27 @@ static int board_handle_phase(enum board_match_phase phase) return 0; } - return board->enable(); + return board->enable(cfg); } -void board_handle_before_superio(void) +void board_handle_before_superio(struct board_cfg *cfg, bool force_boardenable) { - board_handle_phase(P1); + board_handle_phase(cfg, P1, force_boardenable); } -void board_handle_before_laptop(void) +void board_handle_before_laptop(struct board_cfg *cfg, bool force_boardenable) { - board_handle_phase(P2); + board_handle_phase(cfg, P2, force_boardenable); } -int board_flash_enable(const char *vendor, const char *model, const char *cb_vendor, const char *cb_model) +int board_flash_enable(struct board_cfg *cfg, + const char *vendor, const char *model, const char *cb_vendor, const char *cb_model, + bool force_boardenable) { const struct board_match *board = NULL; int ret = 0; - if (vendor != NULL && model != NULL) { + if (vendor && model) { board = board_match_name(vendor, model, false); if (!board) { /* If a board was given by the user it has to match, else we abort here. */ msg_perr("No suitable board enable found for vendor=\"%s\", model=\"%s\".\n", @@ -2726,31 +2725,31 @@ int board_flash_enable(const char *vendor, const char *model, const char *cb_ven return 1; } } - if (board == NULL && cb_vendor != NULL && cb_model != NULL) { + if (!board && cb_vendor && cb_model) { board = board_match_name(cb_vendor, cb_model, true); if (!board) { /* Failure is an option here, because many cb boards don't require an enable. */ msg_pdbg2("No board enable found matching coreboot IDs vendor=\"%s\", model=\"%s\".\n", cb_vendor, cb_model); } } - if (board == NULL) { + if (!board) { board = board_match_pci_ids(P3); if (!board) /* i.e. there is just no board enable available for this board */ return 0; } - if (board_enable_safetycheck(board)) + if (board_enable_safetycheck(board, force_boardenable)) return 1; /* limit the maximum size of the parallel bus */ if (board->max_rom_decode_parallel) max_rom_decode.parallel = board->max_rom_decode_parallel * 1024; - if (board->enable != NULL) { + if (board->enable) { msg_pinfo("Enabling full flash access for board \"%s %s\"... ", board->vendor_name, board->board_name); - ret = board->enable(); + ret = board->enable(cfg); if (ret) msg_pinfo("FAILED!\n"); else diff --git a/buspirate_spi.c b/buspirate_spi.c index dbaac4e5e..3a1e41437 100644 --- a/buspirate_spi.c +++ b/buspirate_spi.c @@ -178,12 +178,9 @@ static struct spi_master spi_master_buspirate = { .max_data_read = MAX_DATA_UNSPECIFIED, .max_data_write = MAX_DATA_UNSPECIFIED, .command = NULL, - .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = buspirate_spi_shutdown, - .probe_opcode = default_spi_probe_opcode, }; static const struct buspirate_speeds spispeeds[] = { @@ -328,8 +325,10 @@ static int buspirate_spi_init(const struct programmer_cfg *cfg) int spispeed = 0x7; int serialspeed_index = -1; int ret = 0; + bool hiz = false; bool pullup = false; bool psu = false; + bool aux = true; unsigned char *bp_commbuf; int bp_commbufsize; @@ -372,23 +371,60 @@ static int buspirate_spi_init(const struct programmer_cfg *cfg) tmp = extract_programmer_param_str(cfg, "pullups"); if (tmp) { - if (strcasecmp("on", tmp) == 0) + if (strcasecmp("on", tmp) == 0) { pullup = true; - else if (strcasecmp("off", tmp) == 0) + } else if (strcasecmp("off", tmp) == 0) { ; // ignore - else - msg_perr("Invalid pullups state, not using them.\n"); + } else { + msg_perr("Invalid pullups state. Use on/off.\n"); + free(tmp); + return 1; + } + } + free(tmp); + + tmp = extract_programmer_param_str(cfg, "hiz"); + if (tmp) { + if (strcasecmp("on", tmp) == 0) { + hiz = true; + } else if (strcasecmp("off", tmp) == 0) { + if (pullup) { + msg_perr("Invalid combination: pullups=on & hiz=off at same time is not possible.\n"); + free(tmp); + return 1; + } else { + ; // ignore + } + } else { + msg_perr("Invalid hiz state. Use on/off.\n"); + free(tmp); + return 1; + } } free(tmp); tmp = extract_programmer_param_str(cfg, "psus"); if (tmp) { - if (strcasecmp("on", tmp) == 0) + if (strcasecmp("on", tmp) == 0) { psu = true; - else if (strcasecmp("off", tmp) == 0) + } else if (strcasecmp("off", tmp) == 0) { ; // ignore + } else { + msg_perr("Invalid psus state. Use on/off.\n"); + free(tmp); + return 1; + } + } + free(tmp); + + tmp = extract_programmer_param_str(cfg, "aux"); + if (tmp) { + if (strcasecmp("high", tmp) == 0) + ; /* Default */ + else if (strcasecmp("low", tmp) == 0) + aux = false; else - msg_perr("Invalid psus state, not enabling.\n"); + msg_perr("Invalid AUX state, driving high by default.\n"); } free(tmp); @@ -645,8 +681,8 @@ static int buspirate_spi_init(const struct programmer_cfg *cfg) goto init_err_cleanup_exit; } - /* Initial setup (SPI peripherals config): Enable power, CS high, AUX */ - bp_commbuf[0] = 0x40 | 0x0b; + /* Initial setup (SPI peripherals config): Enable power, CS high */ + bp_commbuf[0] = 0x40 | 0x09; if (pullup) { bp_commbuf[0] |= (1 << 2); msg_pdbg("Enabling pull-up resistors.\n"); @@ -655,6 +691,12 @@ static int buspirate_spi_init(const struct programmer_cfg *cfg) bp_commbuf[0] |= (1 << 3); msg_pdbg("Enabling PSUs.\n"); } + if (aux) { + bp_commbuf[0] |= (1 << 1); + msg_pdbg("Driving AUX high.\n"); + } else { + msg_pdbg("Driving AUX low.\n"); + } ret = buspirate_sendrecv(bp_commbuf, 1, 1); if (ret) goto init_err_cleanup_exit; @@ -677,9 +719,9 @@ static int buspirate_spi_init(const struct programmer_cfg *cfg) /* Set SPI config: output type, idle, clock edge, sample */ bp_commbuf[0] = 0x80 | 0xa; - if (pullup) { + if (pullup || hiz) { bp_commbuf[0] &= ~(1 << 3); - msg_pdbg("Pull-ups enabled, so using HiZ pin output! (Open-Drain mode)\n"); + msg_pdbg("Pull-ups or HiZ enabled, so using HiZ pin output! (Open-Drain mode)\n"); } ret = buspirate_sendrecv(bp_commbuf, 1, 1); if (ret) diff --git a/cbtable.c b/cbtable.c index 2b339d533..dd6a0b956 100644 --- a/cbtable.c +++ b/cbtable.c @@ -159,7 +159,7 @@ static int lb_header_valid(struct lb_header *head, unsigned long addr) msg_pdbg("Found candidate at: %08lx-%08lx\n", addr, addr + sizeof(*head) + head->table_bytes); if (head->header_bytes != sizeof(*head)) { - msg_perr("Header bytes of %d are incorrect.\n", + msg_perr("Header bytes of %"PRId32" are incorrect.\n", head->header_bytes); return 0; } @@ -175,12 +175,12 @@ static int lb_table_valid(struct lb_header *head, struct lb_record *recs) { if (compute_checksum(recs, head->table_bytes) != head->table_checksum) { - msg_perr("Bad table checksum: %04x.\n", + msg_perr("Bad table checksum: %04"PRIx32".\n", head->table_checksum); return 0; } if (count_lb_records(head) != head->table_entries) { - msg_perr("Bad record count: %d.\n", + msg_perr("Bad record count: %"PRId32".\n", head->table_entries); return 0; } @@ -295,13 +295,10 @@ static struct lb_record *next_record(struct lb_record *rec) static void search_lb_records(struct lb_record *rec, struct lb_record *last, unsigned long addr) { struct lb_record *next; - int count; - count = 0; for (next = next_record(rec); (rec < last) && (next <= last); rec = next, addr += rec->size) { next = next_record(rec); - count++; if (rec->tag == LB_TAG_MAINBOARD) { find_mainboard(rec, addr); break; @@ -355,7 +352,7 @@ int cb_parse_table(const char **vendor, const char **model) (unsigned long)lb_table - (unsigned long)table_area + start); rec = (struct lb_record *)(((char *)lb_table) + lb_table->header_bytes); last = (struct lb_record *)(((char *)rec) + lb_table->table_bytes); - msg_pdbg("coreboot header(%d) checksum: %04x table(%d) checksum: %04x entries: %d\n", + msg_pdbg("coreboot header(%"PRId32") checksum: %04"PRIx32" table(%"PRId32") checksum: %04"PRIx32" entries: %"PRId32"\n", lb_table->header_bytes, lb_table->header_checksum, lb_table->table_bytes, lb_table->table_checksum, lb_table->table_entries); diff --git a/ch341a_spi.c b/ch341a_spi.c index 294a6a655..8f42f09c7 100644 --- a/ch341a_spi.c +++ b/ch341a_spi.c @@ -17,6 +17,7 @@ * GNU General Public License for more details. */ +#include #include #include #include "flash.h" @@ -72,16 +73,18 @@ /* Number of parallel IN transfers. 32 seems to produce the most stable throughput on Windows. */ #define USB_IN_TRANSFERS 32 -/* We need to use many queued IN transfers for any resemblance of performance (especially on Windows) - * because USB spec says that transfers end on non-full packets and the device sends the 31 reply - * data bytes to each 32-byte packet with command + 31 bytes of data... */ -static struct libusb_transfer *transfer_out = NULL; -static struct libusb_transfer *transfer_ins[USB_IN_TRANSFERS] = {0}; +struct ch341a_spi_data { + struct libusb_device_handle *handle; -/* Accumulate delays to be plucked between CS deassertion and CS assertions. */ -static unsigned int stored_delay_us = 0; + /* We need to use many queued IN transfers for any resemblance of performance (especially on Windows) + * because USB spec says that transfers end on non-full packets and the device sends the 31 reply + * data bytes to each 32-byte packet with command + 31 bytes of data... */ + struct libusb_transfer *transfer_out; + struct libusb_transfer *transfer_ins[USB_IN_TRANSFERS]; -static struct libusb_device_handle *handle = NULL; + /* Accumulate delays to be plucked between CS deassertion and CS assertions. */ + unsigned int stored_delay_us; +}; static const struct dev_entry devs_ch341a_spi[] = { {0x1A86, 0x5512, OK, "Winchiphead (WCH)", "CH341A"}, @@ -131,20 +134,18 @@ static void LIBUSB_CALL cb_in(struct libusb_transfer *transfer) cb_common(__func__, transfer); } -static int32_t usb_transfer(const char *func, unsigned int writecnt, unsigned int readcnt, const uint8_t *writearr, uint8_t *readarr) +static int32_t usb_transfer(const struct ch341a_spi_data *data, const char *func, + unsigned int writecnt, unsigned int readcnt, const uint8_t *writearr, uint8_t *readarr) { - if (handle == NULL) - return -1; - int state_out = TRANS_IDLE; - transfer_out->buffer = (uint8_t*)writearr; - transfer_out->length = writecnt; - transfer_out->user_data = &state_out; + data->transfer_out->buffer = (uint8_t*)writearr; + data->transfer_out->length = writecnt; + data->transfer_out->user_data = &state_out; /* Schedule write first */ if (writecnt > 0) { state_out = TRANS_ACTIVE; - int ret = libusb_submit_transfer(transfer_out); + int ret = libusb_submit_transfer(data->transfer_out); if (ret) { msg_perr("%s: failed to submit OUT transfer: %s\n", func, libusb_error_name(ret)); state_out = TRANS_ERR; @@ -165,10 +166,10 @@ static int32_t usb_transfer(const char *func, unsigned int writecnt, unsigned in /* Schedule new reads as long as there are free transfers and unscheduled bytes to read. */ while ((in_done + in_active) < readcnt && state_in[free_idx] == TRANS_IDLE) { unsigned int cur_todo = min(CH341_PACKET_LENGTH - 1, readcnt - in_done - in_active); - transfer_ins[free_idx]->length = cur_todo; - transfer_ins[free_idx]->buffer = in_buf; - transfer_ins[free_idx]->user_data = &state_in[free_idx]; - int ret = libusb_submit_transfer(transfer_ins[free_idx]); + data->transfer_ins[free_idx]->length = cur_todo; + data->transfer_ins[free_idx]->buffer = in_buf; + data->transfer_ins[free_idx]->user_data = &state_in[free_idx]; + int ret = libusb_submit_transfer(data->transfer_ins[free_idx]); if (ret) { state_in[free_idx] = TRANS_ERR; msg_perr("%s: failed to submit IN transfer: %s\n", @@ -223,14 +224,14 @@ static int32_t usb_transfer(const char *func, unsigned int writecnt, unsigned in (state_out == TRANS_ERR) ? writecnt : readcnt); /* First, we must cancel any ongoing requests and wait for them to be canceled. */ if ((writecnt > 0) && (state_out == TRANS_ACTIVE)) { - if (libusb_cancel_transfer(transfer_out) != 0) + if (libusb_cancel_transfer(data->transfer_out) != 0) state_out = TRANS_ERR; } if (readcnt > 0) { unsigned int i; for (i = 0; i < USB_IN_TRANSFERS; i++) { if (state_in[i] == TRANS_ACTIVE) - if (libusb_cancel_transfer(transfer_ins[i]) != 0) + if (libusb_cancel_transfer(data->transfer_ins[i]) != 0) state_in[i] = TRANS_ERR; } } @@ -256,18 +257,15 @@ static int32_t usb_transfer(const char *func, unsigned int writecnt, unsigned in /* Set the I2C bus speed (speed(b1b0): 0 = 20kHz; 1 = 100kHz, 2 = 400kHz, 3 = 750kHz). * Set the SPI bus data width (speed(b2): 0 = Single, 1 = Double). */ -static int32_t config_stream(uint32_t speed) +static int32_t config_stream(const struct ch341a_spi_data *data, uint32_t speed) { - if (handle == NULL) - return -1; - uint8_t buf[] = { CH341A_CMD_I2C_STREAM, CH341A_CMD_I2C_STM_SET | (speed & 0x7), CH341A_CMD_I2C_STM_END }; - int32_t ret = usb_transfer(__func__, sizeof(buf), 0, buf, NULL); + int32_t ret = usb_transfer(data, __func__, sizeof(buf), 0, buf, NULL); if (ret < 0) { msg_perr("Could not configure stream interface.\n"); } @@ -287,7 +285,7 @@ static int32_t config_stream(uint32_t speed) * D6/21 unused (DIN2) * D7/22 SO/2 (DIN) */ -static int32_t enable_pins(bool enable) +static int32_t enable_pins(const struct ch341a_spi_data *data, bool enable) { uint8_t buf[] = { CH341A_CMD_UIO_STREAM, @@ -296,7 +294,7 @@ static int32_t enable_pins(bool enable) CH341A_CMD_UIO_STM_END, }; - int32_t ret = usb_transfer(__func__, sizeof(buf), 0, buf, NULL); + int32_t ret = usb_transfer(data, __func__, sizeof(buf), 0, buf, NULL); if (ret < 0) { msg_perr("Could not %sable output pins.\n", enable ? "en" : "dis"); } @@ -304,14 +302,14 @@ static int32_t enable_pins(bool enable) } /* De-assert and assert CS in one operation. */ -static void pluck_cs(uint8_t *ptr) +static void pluck_cs(uint8_t *ptr, unsigned int *stored_delay_us) { /* This was measured to give a minimum deassertion time of 2.25 us, * >20x more than needed for most SPI chips (100ns). */ int delay_cnt = 2; - if (stored_delay_us) { - delay_cnt = (stored_delay_us * 4) / 3; - stored_delay_us = 0; + if (*stored_delay_us) { + delay_cnt = (*stored_delay_us * 4) / 3; + *stored_delay_us = 0; } *ptr++ = CH341A_CMD_UIO_STREAM; *ptr++ = CH341A_CMD_UIO_STM_OUT | 0x37; /* deasserted */ @@ -322,23 +320,24 @@ static void pluck_cs(uint8_t *ptr) *ptr++ = CH341A_CMD_UIO_STM_END; } -static void ch341a_spi_delay(unsigned int usecs) +static void ch341a_spi_delay(const struct flashctx *flash, unsigned int usecs) { + struct ch341a_spi_data *data = flash->mst->spi.data; + /* There is space for 28 bytes instructions of 750 ns each in the CS packet (32 - 4 for the actual CS * instructions), thus max 21 us, but we avoid getting too near to this boundary and use - * internal_delay() for durations over 20 us. */ - if ((usecs + stored_delay_us) > 20) { - unsigned int inc = 20 - stored_delay_us; - internal_delay(usecs - inc); + * default_delay() for durations over 20 us. */ + if ((usecs + data->stored_delay_us) > 20) { + unsigned int inc = 20 - data->stored_delay_us; + default_delay(usecs - inc); usecs = inc; } - stored_delay_us += usecs; + data->stored_delay_us += usecs; } static int ch341a_spi_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr) { - if (handle == NULL) - return -1; + struct ch341a_spi_data *data = flash->mst->spi.data; /* How many packets ... */ const size_t packets = (writecnt + readcnt + CH341_PACKET_LENGTH - 2) / (CH341_PACKET_LENGTH - 1); @@ -352,7 +351,7 @@ static int ch341a_spi_spi_send_command(const struct flashctx *flash, unsigned in uint8_t *ptr = wbuf[0]; /* CS usage is optimized by doing both transitions in one packet. * Final transition to deselected state is in the pin disable. */ - pluck_cs(ptr); + pluck_cs(ptr, &data->stored_delay_us); unsigned int write_left = writecnt; unsigned int read_left = readcnt; unsigned int p; @@ -371,7 +370,7 @@ static int ch341a_spi_spi_send_command(const struct flashctx *flash, unsigned in write_left -= write_now; } - int32_t ret = usb_transfer(__func__, CH341_PACKET_LENGTH + packets + writecnt + readcnt, + int32_t ret = usb_transfer(data, __func__, CH341_PACKET_LENGTH + packets + writecnt + readcnt, writecnt + readcnt, wbuf[0], rbuf); if (ret < 0) return -1; @@ -386,22 +385,19 @@ static int ch341a_spi_spi_send_command(const struct flashctx *flash, unsigned in static int ch341a_spi_shutdown(void *data) { - if (handle == NULL) - return -1; + struct ch341a_spi_data *ch341a_data = data; - enable_pins(false); - libusb_free_transfer(transfer_out); - transfer_out = NULL; + enable_pins(ch341a_data, false); + libusb_free_transfer(ch341a_data->transfer_out); int i; - for (i = 0; i < USB_IN_TRANSFERS; i++) { - libusb_free_transfer(transfer_ins[i]); - transfer_ins[i] = NULL; - } - libusb_release_interface(handle, 0); - libusb_attach_kernel_driver(handle, 0); - libusb_close(handle); + for (i = 0; i < USB_IN_TRANSFERS; i++) + libusb_free_transfer(ch341a_data->transfer_ins[i]); + libusb_release_interface(ch341a_data->handle, 0); + libusb_attach_kernel_driver(ch341a_data->handle, 0); + libusb_close(ch341a_data->handle); libusb_exit(NULL); - handle = NULL; + + free(data); return 0; } @@ -413,21 +409,14 @@ static const struct spi_master spi_master_ch341a_spi = { .max_data_read = 4 * 1024, .max_data_write = 4 * 1024, .command = ch341a_spi_spi_send_command, - .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = ch341a_spi_shutdown, - .probe_opcode = default_spi_probe_opcode, + .delay = ch341a_spi_delay, }; static int ch341a_spi_init(const struct programmer_cfg *cfg) { - if (handle != NULL) { - msg_cerr("%s: handle already set! Please report a bug at flashrom@flashrom.org\n", __func__); - return -1; - } - int32_t ret = libusb_init(NULL); if (ret < 0) { msg_perr("Couldn't initialize libusb!\n"); @@ -441,27 +430,33 @@ static int ch341a_spi_init(const struct programmer_cfg *cfg) libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO); #endif + struct ch341a_spi_data *data = calloc(1, sizeof(*data)); + if (!data) { + msg_perr("Out of memory!\n"); + return 1; + } + uint16_t vid = devs_ch341a_spi[0].vendor_id; uint16_t pid = devs_ch341a_spi[0].device_id; - handle = libusb_open_device_with_vid_pid(NULL, vid, pid); - if (handle == NULL) { + data->handle = libusb_open_device_with_vid_pid(NULL, vid, pid); + if (data->handle == NULL) { msg_perr("Couldn't open device %04x:%04x.\n", vid, pid); - return -1; + goto free_data; } - ret = libusb_detach_kernel_driver(handle, 0); + ret = libusb_detach_kernel_driver(data->handle, 0); if (ret != 0 && ret != LIBUSB_ERROR_NOT_FOUND) msg_pwarn("Cannot detach the existing USB driver. Claiming the interface may fail. %s\n", libusb_error_name(ret)); - ret = libusb_claim_interface(handle, 0); + ret = libusb_claim_interface(data->handle, 0); if (ret != 0) { msg_perr("Failed to claim interface 0: '%s'\n", libusb_error_name(ret)); goto close_handle; } struct libusb_device *dev; - if (!(dev = libusb_get_device(handle))) { + if (!(dev = libusb_get_device(data->handle))) { msg_perr("Failed to get device from device handle.\n"); goto close_handle; } @@ -479,44 +474,43 @@ static int ch341a_spi_init(const struct programmer_cfg *cfg) (desc.bcdDevice >> 0) & 0x000F); /* Allocate and pre-fill transfer structures. */ - transfer_out = libusb_alloc_transfer(0); - if (!transfer_out) { + data->transfer_out = libusb_alloc_transfer(0); + if (!data->transfer_out) { msg_perr("Failed to alloc libusb OUT transfer\n"); goto release_interface; } int i; for (i = 0; i < USB_IN_TRANSFERS; i++) { - transfer_ins[i] = libusb_alloc_transfer(0); - if (transfer_ins[i] == NULL) { + data->transfer_ins[i] = libusb_alloc_transfer(0); + if (data->transfer_ins[i] == NULL) { msg_perr("Failed to alloc libusb IN transfer %d\n", i); goto dealloc_transfers; } } /* We use these helpers but dont fill the actual buffer yet. */ - libusb_fill_bulk_transfer(transfer_out, handle, WRITE_EP, NULL, 0, cb_out, NULL, USB_TIMEOUT); + libusb_fill_bulk_transfer(data->transfer_out, data->handle, WRITE_EP, NULL, 0, cb_out, NULL, USB_TIMEOUT); for (i = 0; i < USB_IN_TRANSFERS; i++) - libusb_fill_bulk_transfer(transfer_ins[i], handle, READ_EP, NULL, 0, cb_in, NULL, USB_TIMEOUT); + libusb_fill_bulk_transfer(data->transfer_ins[i], data->handle, READ_EP, NULL, 0, cb_in, NULL, USB_TIMEOUT); - if ((config_stream(CH341A_STM_I2C_100K) < 0) || (enable_pins(true) < 0)) + if ((config_stream(data, CH341A_STM_I2C_100K) < 0) || (enable_pins(data, true) < 0)) goto dealloc_transfers; - return register_spi_master(&spi_master_ch341a_spi, NULL); + return register_spi_master(&spi_master_ch341a_spi, data); dealloc_transfers: for (i = 0; i < USB_IN_TRANSFERS; i++) { - if (transfer_ins[i] == NULL) + if (data->transfer_ins[i] == NULL) break; - libusb_free_transfer(transfer_ins[i]); - transfer_ins[i] = NULL; + libusb_free_transfer(data->transfer_ins[i]); } - libusb_free_transfer(transfer_out); - transfer_out = NULL; + libusb_free_transfer(data->transfer_out); release_interface: - libusb_release_interface(handle, 0); + libusb_release_interface(data->handle, 0); close_handle: - libusb_attach_kernel_driver(handle, 0); - libusb_close(handle); - handle = NULL; + libusb_attach_kernel_driver(data->handle, 0); + libusb_close(data->handle); +free_data: + free(data); return -1; } @@ -525,5 +519,4 @@ const struct programmer_entry programmer_ch341a_spi = { .type = USB, .devs.dev = devs_ch341a_spi, .init = ch341a_spi_init, - .delay = ch341a_spi_delay, }; diff --git a/ch347_spi.c b/ch347_spi.c new file mode 100644 index 000000000..34f2741ed --- /dev/null +++ b/ch347_spi.c @@ -0,0 +1,386 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2022 Nicholas Chin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include "platform.h" +#include "programmer.h" +#include "flash.h" + +#define CH347_CMD_SPI_SET_CFG 0xC0 +#define CH347_CMD_SPI_CS_CTRL 0xC1 +#define CH347_CMD_SPI_OUT_IN 0xC2 +#define CH347_CMD_SPI_IN 0xC3 +#define CH347_CMD_SPI_OUT 0xC4 +#define CH347_CMD_SPI_GET_CFG 0xCA + +#define CH347_CS_ASSERT 0x00 +#define CH347_CS_DEASSERT 0x40 +#define CH347_CS_CHANGE 0x80 +#define CH347_CS_IGNORE 0x00 + +#define WRITE_EP 0x06 +#define READ_EP 0x86 + +#define CH347T_IFACE 2 +#define CH347F_IFACE 4 + +/* The USB descriptor says the max transfer size is 512 bytes, but the + * vendor driver only seems to transfer a maximum of 510 bytes at once, + * leaving 507 bytes for data as the command + length take up 3 bytes + */ +#define CH347_PACKET_SIZE 510 +#define CH347_MAX_DATA_LEN (CH347_PACKET_SIZE - 3) + +struct ch347_spi_data { + struct libusb_device_handle *handle; + int interface; +}; + +struct device_speeds { + const char *name; + const int divisor; +}; + +/* TODO: Add support for HID mode */ +static const struct dev_entry devs_ch347_spi[] = { + {0x1A86, 0x55DB, OK, "QinHeng Electronics", "USB To UART+SPI+I2C"}, /* CH347T */ + {0x1A86, 0x55DE, OK, "QinHeng Electronics", "USB To UART+SPI+I2C"}, /* CH347F */ + {0} +}; + +static int ch347_interface[] = { + CH347T_IFACE, + CH347F_IFACE, +}; + +static const struct device_speeds spispeeds[] = { + {"60M", 0}, + {"30M", 1}, + {"15M", 2}, + {"7.5M", 3}, + {"3.75M", 4}, + {"1.875M", 5}, + {"937.5K", 6}, + {"468.75K", 7}, + {NULL, 0} +}; + +static int ch347_spi_shutdown(void *data) +{ + struct ch347_spi_data *ch347_data = data; + int spi_interface = ch347_data->interface; + libusb_release_interface(ch347_data->handle, spi_interface); + libusb_attach_kernel_driver(ch347_data->handle, spi_interface); + libusb_close(ch347_data->handle); + libusb_exit(NULL); + free(data); + return 0; +} + +static int ch347_cs_control(struct ch347_spi_data *ch347_data, uint8_t cs1, uint8_t cs2) +{ + uint8_t cmd[13] = { + [0] = CH347_CMD_SPI_CS_CTRL, + /* payload length, uint16 LSB: 10 */ + [1] = 10, + [3] = cs1, + [8] = cs2 + }; + + int32_t ret = libusb_bulk_transfer(ch347_data->handle, WRITE_EP, cmd, sizeof(cmd), NULL, 1000); + if (ret < 0) { + msg_perr("Could not change CS!\n"); + return -1; + } + return 0; +} + + +static int ch347_write(struct ch347_spi_data *ch347_data, unsigned int writecnt, const uint8_t *writearr) +{ + unsigned int data_len; + int packet_len; + int transferred; + int ret; + uint8_t resp_buf[4] = {0}; + uint8_t buffer[CH347_PACKET_SIZE] = {0}; + unsigned int bytes_written = 0; + + while (bytes_written < writecnt) { + data_len = min(CH347_MAX_DATA_LEN, writecnt - bytes_written ); + packet_len = data_len + 3; + + buffer[0] = CH347_CMD_SPI_OUT; + buffer[1] = (data_len) & 0xFF; + buffer[2] = ((data_len) & 0xFF00) >> 8; + memcpy(buffer + 3, writearr + bytes_written, data_len); + + ret = libusb_bulk_transfer(ch347_data->handle, WRITE_EP, buffer, packet_len, &transferred, 1000); + if (ret < 0 || transferred != packet_len) { + msg_perr("Could not send write command\n"); + return -1; + } + + ret = libusb_bulk_transfer(ch347_data->handle, READ_EP, resp_buf, sizeof(resp_buf), NULL, 1000); + if (ret < 0) { + msg_perr("Could not receive write command response\n"); + return -1; + } + bytes_written += data_len; + } + return 0; +} + +static int ch347_read(struct ch347_spi_data *ch347_data, unsigned int readcnt, uint8_t *readarr) +{ + uint8_t *read_ptr = readarr; + int ret; + int transferred; + unsigned int bytes_read = 0; + uint8_t buffer[CH347_PACKET_SIZE] = {0}; + uint8_t command_buf[7] = { + [0] = CH347_CMD_SPI_IN, + [1] = 4, + [2] = 0, + [3] = readcnt & 0xFF, + [4] = (readcnt & 0xFF00) >> 8, + [5] = (readcnt & 0xFF0000) >> 16, + [6] = (readcnt & 0xFF000000) >> 24 + }; + + ret = libusb_bulk_transfer(ch347_data->handle, WRITE_EP, command_buf, sizeof(command_buf), &transferred, 1000); + if (ret < 0 || transferred != sizeof(command_buf)) { + msg_perr("Could not send read command\n"); + return -1; + } + + while (bytes_read < readcnt) { + ret = libusb_bulk_transfer(ch347_data->handle, READ_EP, buffer, CH347_PACKET_SIZE, &transferred, 1000); + if (ret < 0) { + msg_perr("Could not read data\n"); + return -1; + } + if (transferred > CH347_PACKET_SIZE) { + msg_perr("libusb bug: bytes received overflowed buffer\n"); + return -1; + } + /* Response: u8 command, u16 data length, then the data that was read */ + if (transferred < 3) { + msg_perr("CH347 returned an invalid response to read command\n"); + return -1; + } + int ch347_data_length = read_le16(buffer, 1); + if (transferred - 3 < ch347_data_length) { + msg_perr("CH347 returned less data than data length header indicates\n"); + return -1; + } + bytes_read += ch347_data_length; + if (bytes_read > readcnt) { + msg_perr("CH347 returned more bytes than requested\n"); + return -1; + } + memcpy(read_ptr, buffer + 3, ch347_data_length); + read_ptr += ch347_data_length; + } + return 0; +} + +static int ch347_spi_send_command(const struct flashctx *flash, unsigned int writecnt, + unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr) +{ + struct ch347_spi_data *ch347_data = flash->mst->spi.data; + int ret = 0; + + ch347_cs_control(ch347_data, CH347_CS_ASSERT | CH347_CS_CHANGE, CH347_CS_IGNORE); + if (writecnt) { + ret = ch347_write(ch347_data, writecnt, writearr); + if (ret < 0) { + msg_perr("CH347 write error\n"); + return -1; + } + } + if (readcnt) { + ret = ch347_read(ch347_data, readcnt, readarr); + if (ret < 0) { + msg_perr("CH347 read error\n"); + return -1; + } + } + ch347_cs_control(ch347_data, CH347_CS_DEASSERT | CH347_CS_CHANGE, CH347_CS_IGNORE); + + return 0; +} + +static int32_t ch347_spi_config(struct ch347_spi_data *ch347_data, uint8_t divisor) +{ + int32_t ret; + uint8_t buff[29] = { + [0] = CH347_CMD_SPI_SET_CFG, + [1] = (sizeof(buff) - 3) & 0xFF, + [2] = ((sizeof(buff) - 3) & 0xFF00) >> 8, + /* Not sure what these two bytes do, but the vendor + * drivers seem to unconditionally set these values + */ + [5] = 4, + [6] = 1, + /* Clock polarity: bit 1 */ + [9] = 0, + /* Clock phase: bit 0 */ + [11] = 0, + /* Another mystery byte */ + [14] = 2, + /* Clock divisor: bits 5:3 */ + [15] = (divisor & 0x7) << 3, + /* Bit order: bit 7, 0=MSB */ + [17] = 0, + /* Yet another mystery byte */ + [19] = 7, + /* CS polarity: bit 7 CS2, bit 6 CS1. 0 = active low */ + [24] = 0 + }; + + ret = libusb_bulk_transfer(ch347_data->handle, WRITE_EP, buff, sizeof(buff), NULL, 1000); + if (ret < 0) { + msg_perr("Could not configure SPI interface\n"); + } + + /* FIXME: Not sure if the CH347 sends error responses for + * invalid config data, if so the code should check + */ + ret = libusb_bulk_transfer(ch347_data->handle, READ_EP, buff, sizeof(buff), NULL, 1000); + if (ret < 0) { + msg_perr("Could not receive configure SPI command response\n"); + } + return ret; +} + +static const struct spi_master spi_master_ch347_spi = { + .features = SPI_MASTER_4BA, + .max_data_read = MAX_DATA_READ_UNLIMITED, + .max_data_write = MAX_DATA_WRITE_UNLIMITED, + .command = ch347_spi_send_command, + .read = default_spi_read, + .write_256 = default_spi_write_256, + .write_aai = default_spi_write_aai, + .shutdown = ch347_spi_shutdown, +}; + +/* Largely copied from ch341a_spi.c */ +static int ch347_spi_init(const struct programmer_cfg *cfg) +{ + char *arg; + uint16_t vid = devs_ch347_spi[0].vendor_id; + uint16_t pid = 0; + int index = 0; + int speed_index = 2; + struct ch347_spi_data *ch347_data = calloc(1, sizeof(*ch347_data)); + if (!ch347_data) { + msg_perr("Could not allocate space for SPI data\n"); + return 1; + } + + int32_t ret = libusb_init(NULL); + if (ret < 0) { + msg_perr("Could not initialize libusb!\n"); + free(ch347_data); + return 1; + } + /* Enable information, warning, and error messages (only). */ +#if LIBUSB_API_VERSION < 0x01000106 + libusb_set_debug(NULL, 3); +#else + libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO); +#endif + while (devs_ch347_spi[index].vendor_id != 0) { + vid = devs_ch347_spi[index].vendor_id; + pid = devs_ch347_spi[index].device_id; + ch347_data->handle = libusb_open_device_with_vid_pid(NULL, vid, pid); + if (ch347_data->handle) { + ch347_data->interface = ch347_interface[index]; + break; + } + index++; + } + if (!ch347_data->handle) { + msg_perr("Couldn't find CH347.\n"); + free(ch347_data); + return 1; + } + + ret = libusb_detach_kernel_driver(ch347_data->handle, ch347_data->interface); + if (ret != 0 && ret != LIBUSB_ERROR_NOT_FOUND) + msg_pwarn("Cannot detach the existing USB driver. Claiming the interface may fail. %s\n", + libusb_error_name(ret)); + + ret = libusb_claim_interface(ch347_data->handle, ch347_data->interface); + if (ret != 0) { + msg_perr("Failed to claim interface %d: '%s'\n", ch347_data->interface, libusb_error_name(ret)); + goto error_exit; + } + + struct libusb_device *dev; + if (!(dev = libusb_get_device(ch347_data->handle))) { + msg_perr("Failed to get device from device handle.\n"); + goto error_exit; + } + + struct libusb_device_descriptor desc; + ret = libusb_get_device_descriptor(dev, &desc); + if (ret < 0) { + msg_perr("Failed to get device descriptor: '%s'\n", libusb_error_name(ret)); + goto error_exit; + } + + msg_pdbg("Device revision is %d.%01d.%01d\n", + (desc.bcdDevice >> 8) & 0x00FF, + (desc.bcdDevice >> 4) & 0x000F, + (desc.bcdDevice >> 0) & 0x000F); + + /* set CH347 clock division */ + arg = extract_programmer_param_str(cfg, "spispeed"); + if (arg) { + for (speed_index = 0; spispeeds[speed_index].name; speed_index++) { + if (!strncasecmp(spispeeds[speed_index].name, arg, strlen(spispeeds[speed_index].name))) { + break; + } + } + } + if (!spispeeds[speed_index].name || !arg) { + msg_perr("Unknown value of spispeed parameter, using default 15MHz clock spi.\n"); + speed_index = 2; + } + free(arg); + if (ch347_spi_config(ch347_data, spispeeds[speed_index].divisor) < 0) { + goto error_exit; + } else { + msg_pinfo("CH347 SPI clock set to %sHz.\n", spispeeds[speed_index].name); + } + + return register_spi_master(&spi_master_ch347_spi, ch347_data); + +error_exit: + ch347_spi_shutdown(ch347_data); + return 1; +} + +const struct programmer_entry programmer_ch347_spi = { + .name = "ch347_spi", + .type = USB, + .devs.dev = devs_ch347_spi, + .init = ch347_spi_init, +}; \ No newline at end of file diff --git a/chipset_enable.c b/chipset_enable.c index a8685c287..daf431d5f 100644 --- a/chipset_enable.c +++ b/chipset_enable.c @@ -24,8 +24,6 @@ * Contains the chipset specific flash enables. */ -#define _LARGEFILE64_SOURCE - #include #include #include @@ -275,7 +273,7 @@ static int enable_flash_ich_bios_cntl_common(enum ich_chipset ich_generation, vo switch (ich_generation) { case CHIPSET_ICH_UNKNOWN: - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; /* Non-SPI-capable */ case CHIPSET_ICH: case CHIPSET_ICH2345: @@ -409,7 +407,7 @@ static int enable_flash_ich_fwh_decode(const struct programmer_cfg *cfg, struct uint32_t ilb_base = pci_read_long(dev, 0x50) & 0xfffffe00; /* bits 31:9 */ if (ilb_base == 0) { msg_perr("Error: Invalid ILB_BASE_ADDRESS\n"); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } ilb = rphysmap("BYT IBASE", ilb_base, 512); fwh_sel1 = 0x18; @@ -468,7 +466,7 @@ static int enable_flash_ich_fwh_decode(const struct programmer_cfg *cfg, struct msg_perr("Error: fwh_idsel= specified, but no value given.\n"); idsel_garbage_out: free(idsel); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } free(idsel); @@ -550,7 +548,7 @@ static int enable_flash_ich_fwh_decode(const struct programmer_cfg *cfg, struct } } max_rom_decode.fwh = min(max_decode_fwh_idsel, max_decode_fwh_decode); - msg_pdbg("Maximum FWH chip size: 0x%x bytes\n", max_rom_decode.fwh); + msg_pdbg("Maximum FWH chip size: 0x%"PRIx32" bytes\n", max_rom_decode.fwh); return 0; } @@ -603,12 +601,14 @@ static enum chipbustype enable_flash_ich_report_gcs( break; case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_300_SERIES_CANNON_POINT: case CHIPSET_400_SERIES_COMET_POINT: case CHIPSET_500_SERIES_TIGER_POINT: case CHIPSET_600_SERIES_ALDER_POINT: case CHIPSET_700_SERIES_RAPTOR_POINT: case CHIPSET_METEOR_LAKE: + case CHIPSET_PANTHER_LAKE: case CHIPSET_ELKHART_LAKE: case CHIPSET_APOLLO_LAKE: case CHIPSET_GEMINI_LAKE: @@ -626,7 +626,7 @@ static enum chipbustype enable_flash_ich_report_gcs( break; } - msg_pdbg("%s = 0x%x: ", reg_name, gcs); + msg_pdbg("%s = 0x%"PRIx32": ", reg_name, gcs); msg_pdbg("BIOS Interface Lock-Down: %sabled, ", bild ? "en" : "dis"); struct boot_straps { @@ -716,7 +716,9 @@ static enum chipbustype enable_flash_ich_report_gcs( case CHIPSET_500_SERIES_TIGER_POINT: case CHIPSET_600_SERIES_ALDER_POINT: case CHIPSET_700_SERIES_RAPTOR_POINT: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_METEOR_LAKE: + case CHIPSET_PANTHER_LAKE: boot_straps = boot_straps_pch500; break; case CHIPSET_APOLLO_LAKE: @@ -753,6 +755,7 @@ static enum chipbustype enable_flash_ich_report_gcs( case CHIPSET_600_SERIES_ALDER_POINT: case CHIPSET_700_SERIES_RAPTOR_POINT: case CHIPSET_METEOR_LAKE: + case CHIPSET_PANTHER_LAKE: case CHIPSET_APOLLO_LAKE: case CHIPSET_GEMINI_LAKE: case CHIPSET_JASPER_LAKE: @@ -777,18 +780,18 @@ static int enable_flash_ich_spi(const struct programmer_cfg *cfg, struct pci_dev { /* Get physical address of Root Complex Register Block */ uint32_t rcra = pci_read_long(dev, 0xf0) & 0xffffc000; - msg_pdbg("Root Complex Register Block address = 0x%x\n", rcra); + msg_pdbg("Root Complex Register Block address = 0x%"PRIx32"\n", rcra); /* Map RCBA to virtual memory */ void *rcrb = rphysmap("ICH RCRB", rcra, 0x4000); if (rcrb == ERROR_PTR) - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; const enum chipbustype boot_buses = enable_flash_ich_report_gcs(dev, ich_generation, rcrb); /* Handle FWH-related parameters and initialization */ int ret_fwh = enable_flash_ich_fwh(cfg, dev, ich_generation, bios_cntl); - if (ret_fwh == ERROR_FATAL) + if (ret_fwh == ERROR_FLASHROM_FATAL) return ret_fwh; /* @@ -804,7 +807,7 @@ static int enable_flash_ich_spi(const struct programmer_cfg *cfg, struct pci_dev switch (ich_generation) { case CHIPSET_BAYTRAIL: case CHIPSET_ICH_UNKNOWN: - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; case CHIPSET_ICH7: case CHIPSET_ICH8: case CHIPSET_TUNNEL_CREEK: @@ -821,15 +824,15 @@ static int enable_flash_ich_spi(const struct programmer_cfg *cfg, struct pci_dev /* This adds BUS_SPI */ int ret_spi = ich_init_spi(cfg, spibar, ich_generation); - if (ret_spi == ERROR_FATAL) + if (ret_spi == ERROR_FLASHROM_FATAL) return ret_spi; if (((boot_buses & BUS_FWH) && ret_fwh) || ((boot_buses & BUS_SPI) && ret_spi)) - return ERROR_NONFATAL; + return ERROR_FLASHROM_NONFATAL; /* Suppress unknown laptop warning if we booted from SPI. */ if (boot_buses & BUS_SPI) - laptop_ok = true; + cfg->bcfg->laptop_ok = true; return 0; } @@ -923,7 +926,7 @@ static int enable_flash_pch100_or_c620(const struct programmer_cfg *cfg, struct pci_dev *const dev, const char *const name, const int slot, const int func, const enum ich_chipset pch_generation) { - int ret = ERROR_FATAL; + int ret = ERROR_FLASHROM_FATAL; /* * The SPI PCI device is usually hidden (by hiding PCI vendor @@ -938,7 +941,13 @@ static int enable_flash_pch100_or_c620(const struct programmer_cfg *cfg, msg_perr("Can't allocate PCI accessor.\n"); return ret; } +#if CONFIG_USE_LIBPCI_ECAM == 1 + pci_acc->method = PCI_ACCESS_ECAM; + msg_pdbg("Using libpci PCI_ACCESS_ECAM\n"); +#else pci_acc->method = PCI_ACCESS_I386_TYPE1; + msg_pdbg("Using libpci PCI_ACCESS_I386_TYPE1\n"); +#endif pci_init(pci_acc); register_shutdown(enable_flash_pch100_shutdown, pci_acc); @@ -954,27 +963,27 @@ static int enable_flash_pch100_or_c620(const struct programmer_cfg *cfg, const enum chipbustype boot_buses = enable_flash_ich_report_gcs(spi_dev, pch_generation, NULL); const int ret_bc = enable_flash_ich_bios_cntl_config_space(spi_dev, pch_generation, 0xdc); - if (ret_bc == ERROR_FATAL) + if (ret_bc == ERROR_FLASHROM_FATAL) goto _freepci_ret; const uint32_t phys_spibar = pci_read_long(spi_dev, PCI_BASE_ADDRESS_0) & 0xfffff000; void *const spibar = rphysmap("SPIBAR", phys_spibar, 0x1000); if (spibar == ERROR_PTR) goto _freepci_ret; - msg_pdbg("SPIBAR = 0x%0*" PRIxPTR " (phys = 0x%08x)\n", PRIxPTR_WIDTH, (uintptr_t)spibar, phys_spibar); + msg_pdbg("SPIBAR = 0x%0*" PRIxPTR " (phys = 0x%08"PRIx32")\n", PRIxPTR_WIDTH, (uintptr_t)spibar, phys_spibar); /* This adds BUS_SPI */ const int ret_spi = ich_init_spi(cfg, spibar, pch_generation); - if (ret_spi != ERROR_FATAL) { + if (ret_spi != ERROR_FLASHROM_FATAL) { if (ret_bc || ret_spi) - ret = ERROR_NONFATAL; + ret = ERROR_FLASHROM_NONFATAL; else ret = 0; } /* Suppress unknown laptop warning if we booted from SPI. */ if (!ret && (boot_buses & BUS_SPI)) - laptop_ok = true; + cfg->bcfg->laptop_ok = true; _freepci_ret: pci_free_dev(spi_dev); @@ -992,6 +1001,11 @@ static int enable_flash_c620(const struct programmer_cfg *cfg, struct pci_dev *c return enable_flash_pch100_or_c620(cfg, dev, name, 0x1f, 5, CHIPSET_C620_SERIES_LEWISBURG); } +static int enable_flash_c740(const struct programmer_cfg *cfg, struct pci_dev *const dev, const char *const name) +{ + return enable_flash_pch100_or_c620(cfg, dev, name, 0x1f, 5, CHIPSET_C740_SERIES_EMMITSBURG); +} + static int enable_flash_pch300(const struct programmer_cfg *cfg, struct pci_dev *const dev, const char *const name) { return enable_flash_pch100_or_c620(cfg, dev, name, 0x1f, 5, CHIPSET_300_SERIES_CANNON_POINT); @@ -1022,6 +1036,11 @@ static int enable_flash_mtl(const struct programmer_cfg *cfg, struct pci_dev *co return enable_flash_pch100_or_c620(cfg, dev, name, 0x1f, 5, CHIPSET_METEOR_LAKE); } +static int enable_flash_ptl(const struct programmer_cfg *cfg, struct pci_dev *const dev, const char *const name) +{ + return enable_flash_pch100_or_c620(cfg, dev, name, 0x1f, 5, CHIPSET_PANTHER_LAKE); +} + static int enable_flash_mcc(const struct programmer_cfg *cfg, struct pci_dev *const dev, const char *const name) { return enable_flash_pch100_or_c620(cfg, dev, name, 0x1f, 5, CHIPSET_ELKHART_LAKE); @@ -1058,28 +1077,28 @@ static int enable_flash_silvermont(const struct programmer_cfg *cfg, struct pci_ /* Get physical address of Root Complex Register Block */ uint32_t rcba = pci_read_long(dev, 0xf0) & 0xfffffc00; - msg_pdbg("Root Complex Register Block address = 0x%x\n", rcba); + msg_pdbg("Root Complex Register Block address = 0x%"PRIx32"\n", rcba); /* Handle GCS (in RCRB) */ void *rcrb = physmap("BYT RCRB", rcba, 4); if (rcrb == ERROR_PTR) - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; const enum chipbustype boot_buses = enable_flash_ich_report_gcs(dev, ich_generation, rcrb); physunmap(rcrb, 4); /* Handle fwh_idsel parameter */ int ret_fwh = enable_flash_ich_fwh_decode(cfg, dev, ich_generation); - if (ret_fwh == ERROR_FATAL) + if (ret_fwh == ERROR_FLASHROM_FATAL) return ret_fwh; internal_buses_supported &= BUS_FWH; /* Get physical address of SPI Base Address and map it */ uint32_t sbase = pci_read_long(dev, 0x54) & 0xfffffe00; - msg_pdbg("SPI_BASE_ADDRESS = 0x%x\n", sbase); + msg_pdbg("SPI_BASE_ADDRESS = 0x%"PRIx32"\n", sbase); void *spibar = rphysmap("BYT SBASE", sbase, 512); /* Last defined address on Bay Trail is 0x100 */ if (spibar == ERROR_PTR) - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; /* Enable Flash Writes. * Silvermont-based: BCR at SBASE + 0xFC (some bits of BCR are also accessible via BC at IBASE + 0x1C). @@ -1087,15 +1106,15 @@ static int enable_flash_silvermont(const struct programmer_cfg *cfg, struct pci_ enable_flash_ich_bios_cntl_memmapped(ich_generation, spibar + 0xFC); int ret_spi = ich_init_spi(cfg, spibar, ich_generation); - if (ret_spi == ERROR_FATAL) + if (ret_spi == ERROR_FLASHROM_FATAL) return ret_spi; if (((boot_buses & BUS_FWH) && ret_fwh) || ((boot_buses & BUS_SPI) && ret_spi)) - return ERROR_NONFATAL; + return ERROR_FLASHROM_NONFATAL; /* Suppress unknown laptop warning if we booted from SPI. */ if (boot_buses & BUS_SPI) - laptop_ok = true; + cfg->bcfg->laptop_ok = true; return 0; } @@ -1145,7 +1164,7 @@ static int enable_flash_vt_vx(const struct programmer_cfg *cfg, struct pci_dev * struct pci_dev *south_north = pcidev_find(0x1106, 0xa353); if (south_north == NULL) { msg_perr("Could not find South-North Module Interface Control device!\n"); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } msg_pdbg("Strapped to "); @@ -1165,7 +1184,7 @@ static int enable_flash_vt_vx(const struct programmer_cfg *cfg, struct pci_dev * spi0_mm_base = pci_read_long(dev, 0xbc) << 8; if (spi0_mm_base == 0x0) { msg_pdbg ("MMIO not enabled!\n"); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } break; case 0x8409: /* VX855/VX875 */ @@ -1173,18 +1192,18 @@ static int enable_flash_vt_vx(const struct programmer_cfg *cfg, struct pci_dev * mmio_base = pci_read_long(dev, 0xbc) << 8; if (mmio_base == 0x0) { msg_pdbg ("MMIO not enabled!\n"); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } mmio_base_physmapped = physmap("VIA VX MMIO register", mmio_base, SPI_CNTL_LEN); if (mmio_base_physmapped == ERROR_PTR) - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; /* Offset 0 - Bit 0 holds SPI Bus0 Enable Bit. */ spi_cntl = mmio_readl(mmio_base_physmapped) + 0x00; if ((spi_cntl & 0x01) == 0) { msg_pdbg ("SPI Bus0 disabled!\n"); physunmap(mmio_base_physmapped, SPI_CNTL_LEN); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } /* Offset 1-3 has SPI Bus Memory Map Base Address: */ spi0_mm_base = spi_cntl & 0xFFFFFF00; @@ -1198,7 +1217,7 @@ static int enable_flash_vt_vx(const struct programmer_cfg *cfg, struct pci_dev * break; default: msg_perr("%s: Unsupported chipset %x:%x!\n", __func__, dev->vendor_id, dev->device_id); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } return via_init_spi(spi0_mm_base); @@ -1354,7 +1373,7 @@ static int enable_flash_amd_via(const struct programmer_cfg *cfg, struct pci_dev if (pci_read_byte(dev, AMD_ENREG) != new) { msg_pwarn("Setting register 0x%x to 0x%02x on %s failed (WARNING ONLY).\n", AMD_ENREG, new, name); - return ERROR_NONFATAL; + return ERROR_FLASHROM_NONFATAL; } msg_pdbg2("Set ROM enable bit successfully.\n"); @@ -1395,7 +1414,7 @@ static int enable_flash_sb600(const struct programmer_cfg *cfg, struct pci_dev * /* No protection flags for this region?*/ if ((prot & 0x3) == 0) continue; - msg_pdbg("Chipset %s%sprotected flash from 0x%08x to 0x%08x, unlocking...", + msg_pdbg("Chipset %s%sprotected flash from 0x%08"PRIx32" to 0x%08"PRIx32", unlocking...", (prot & 0x2) ? "read " : "", (prot & 0x1) ? "write " : "", (prot & 0xfffff800), @@ -1404,7 +1423,7 @@ static int enable_flash_sb600(const struct programmer_cfg *cfg, struct pci_dev * rpci_write_byte(dev, reg, prot); prot = pci_read_long(dev, reg); if ((prot & 0x3) != 0) { - msg_perr("Disabling %s%sprotection of flash addresses from 0x%08x to 0x%08x failed.\n", + msg_perr("Disabling %s%sprotection of flash addresses from 0x%08"PRIx32" to 0x%08"PRIx32" failed.\n", (prot & 0x2) ? "read " : "", (prot & 0x1) ? "write " : "", (prot & 0xfffff800), @@ -1467,14 +1486,14 @@ static int enable_flash_fch(const struct programmer_cfg *cfg, struct pci_dev *de uint32_t spibar = pci_read_long(dev, 0xa0) & 0xffffffc0; /* bits 31:6, SB600 has 31:5 */ if (spibar == 0) { msg_perr("Error: Invalid SPI BASE\n"); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } /* Physical memory has to be mapped at page (4k) boundaries. */ fch_spi = rphysmap("FCH SPIBASE", spibar & 0xfffff000, 0x1000); if (fch_spi == NULL) { msg_perr("Error: Failed to map SPI BASE\n"); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } /* The low bits of the SPI base address are used as offset into @@ -1613,7 +1632,7 @@ static int enable_flash_nvidia_nforce2(const struct programmer_cfg *cfg, struct { rpci_write_byte(dev, 0x92, 0); if (enable_flash_nvidia_common(cfg, dev, name)) - return ERROR_NONFATAL; + return ERROR_FLASHROM_NONFATAL; else return 0; } @@ -1637,7 +1656,7 @@ static int enable_flash_ck804(const struct programmer_cfg *cfg, struct pci_dev * segctrl = pci_read_byte(dev, reg); if ((segctrl & 0x3) != 0x0) { - msg_pinfo("Could not unlock protection in register 0x%02x (new value: 0x%x).\n", + msg_pinfo("Could not unlock protection in register 0x%02x (new value: 0x%"PRIx32").\n", reg, segctrl); err++; } else @@ -1661,7 +1680,7 @@ static int enable_flash_ck804(const struct programmer_cfg *cfg, struct pci_dev * segctrl = pci_read_long(dev, reg); if ((segctrl & 0x33333333) != 0x00000000) { - msg_pinfo("Could not unlock protection in register 0x%02x (new value: 0x%08x).\n", + msg_pinfo("Could not unlock protection in register 0x%02x (new value: 0x%08"PRIx32").\n", reg, segctrl); err++; } else @@ -1688,7 +1707,7 @@ static int enable_flash_ck804(const struct programmer_cfg *cfg, struct pci_dev * err++; if (err > 0) - return ERROR_NONFATAL; + return ERROR_FLASHROM_NONFATAL; else return 0; } @@ -1721,7 +1740,7 @@ static int enable_flash_sb400(const struct programmer_cfg *cfg, struct pci_dev * if (!smbusdev) { msg_perr("ERROR: SMBus device not found. Aborting.\n"); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } /* Enable some SMBus stuff. */ @@ -1763,7 +1782,7 @@ static int enable_flash_mcp55(const struct programmer_cfg *cfg, struct pci_dev * rpci_write_word(dev, 0x90, wordval); if (enable_flash_nvidia_common(cfg, dev, name)) - return ERROR_NONFATAL; + return ERROR_FLASHROM_NONFATAL; else return 0; } @@ -1804,7 +1823,7 @@ static int enable_flash_mcp6x_7x(const struct programmer_cfg *cfg, struct pci_de msg_pinfo("Please send the log files created by \"flashrom -p internal -o logfile\" to\n" "flashrom@flashrom.org with \"your board name: flashrom -V\" as the subject to\n" "help us finish support for your chipset. Thanks.\n"); - return ERROR_NONFATAL; + return ERROR_FLASHROM_NONFATAL; } /* Force enable SPI and disable LPC? Not a good idea. */ @@ -1819,7 +1838,7 @@ static int enable_flash_mcp6x_7x(const struct programmer_cfg *cfg, struct pci_de /* Suppress unknown laptop warning if we booted from SPI. */ if (!ret && want_spi) - laptop_ok = true; + cfg->bcfg->laptop_ok = true; return ret; } @@ -1856,7 +1875,7 @@ static int get_flashbase_sc520(const struct programmer_cfg *cfg, struct pci_dev /* 1. Map MMCR */ mmcr = physmap("Elan SC520 MMCR", 0xfffef000, getpagesize()); if (mmcr == ERROR_PTR) - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; /* 2. Scan PAR0 (0x88) - PAR15 (0xc4) for * BOOTCS region (PARx[31:29] = 100b)e @@ -2163,7 +2182,7 @@ const struct penable chipset_enables[] = { {0x8086, 0x8cc2, B_FS, NT, "Intel", "9 Series Engineering Sample", enable_flash_pch9}, {0x8086, 0x8cc3, B_FS, NT, "Intel", "9 Series", enable_flash_pch9}, {0x8086, 0x8cc4, B_FS, DEP, "Intel", "Z97", enable_flash_pch9}, - {0x8086, 0x8cc6, B_FS, NT, "Intel", "H97", enable_flash_pch9}, + {0x8086, 0x8cc6, B_FS, DEP, "Intel", "H97", enable_flash_pch9}, {0x8086, 0x8d40, B_FS, NT, "Intel", "C610/X99 (Wellsburg)", enable_flash_pch8_wb}, {0x8086, 0x8d41, B_FS, NT, "Intel", "C610/X99 (Wellsburg)", enable_flash_pch8_wb}, {0x8086, 0x8d42, B_FS, NT, "Intel", "C610/X99 (Wellsburg)", enable_flash_pch8_wb}, @@ -2223,6 +2242,7 @@ const struct penable chipset_enables[] = { {0x8086, 0x0284, B_S, DEP, "Intel", "Comet Lake U Premium", enable_flash_pch400}, {0x8086, 0x0285, B_S, DEP, "Intel", "Comet Lake U Base", enable_flash_pch400}, {0x8086, 0xa082, B_S, DEP, "Intel", "Tiger Lake U Premium", enable_flash_pch500}, + {0x8086, 0xa088, B_S, DEP, "Intel", "Tiger Lake UP3", enable_flash_pch500}, {0x8086, 0xa0a4, B_S, DEP, "Intel", "Tiger Lake LP", enable_flash_pch500}, {0x8086, 0x43a4, B_S, DEP, "Intel", "Tiger Lake H", enable_flash_pch500}, {0x8086, 0xa141, B_S, NT, "Intel", "Sunrise Point Desktop Sample", enable_flash_pch100}, @@ -2269,7 +2289,7 @@ const struct penable chipset_enables[] = { {0x8086, 0xa247, B_S, NT, "Intel", "C620 Series Chipset Supersku", enable_flash_c620}, {0x8086, 0xa248, B_S, NT, "Intel", "C620 Series Chipset Supersku", enable_flash_c620}, {0x8086, 0xa249, B_S, NT, "Intel", "C620 Series Chipset Supersku", enable_flash_c620}, - {0x8086, 0x1bca, B_S, NT, "Intel", "Emmitsburg Chipset SKU", enable_flash_c620}, + {0x8086, 0x1bca, B_S, DEP, "Intel", "Emmitsburg Chipset SKU", enable_flash_c740}, {0x8086, 0xa2c4, B_S, NT, "Intel", "H270", enable_flash_pch100}, {0x8086, 0xa2c5, B_S, NT, "Intel", "Z270", enable_flash_pch100}, {0x8086, 0xa2c6, B_S, NT, "Intel", "Q270", enable_flash_pch100}, @@ -2290,12 +2310,13 @@ const struct penable chipset_enables[] = { {0x8086, 0xa305, B_S, DEP, "Intel", "Z390", enable_flash_pch300}, {0x8086, 0xa306, B_S, NT, "Intel", "Q370", enable_flash_pch300}, {0x8086, 0xa308, B_S, NT, "Intel", "B360", enable_flash_pch300}, - {0x8086, 0xa309, B_S, NT, "Intel", "C246", enable_flash_pch300}, + {0x8086, 0xa309, B_S, DEP, "Intel", "C246", enable_flash_pch300}, {0x8086, 0xa30a, B_S, NT, "Intel", "C242", enable_flash_pch300}, {0x8086, 0xa30c, B_S, NT, "Intel", "QM370", enable_flash_pch300}, {0x8086, 0xa30d, B_S, NT, "Intel", "HM370", enable_flash_pch300}, {0x8086, 0xa30e, B_S, DEP, "Intel", "CM246", enable_flash_pch300}, {0x8086, 0x3482, B_S, DEP, "Intel", "Ice Lake U Premium", enable_flash_pch300}, + {0x8086, 0xa3c8, B_S, OK, "Intel", "B460", enable_flash_pch400}, {0x8086, 0x0684, B_S, NT, "Intel", "H470", enable_flash_pch400}, {0x8086, 0x0685, B_S, NT, "Intel", "Z490", enable_flash_pch400}, {0x8086, 0x0687, B_S, NT, "Intel", "Q470", enable_flash_pch400}, @@ -2334,6 +2355,8 @@ const struct penable chipset_enables[] = { {0x8086, 0x7a14, B_S, NT, "Intel", "C262", enable_flash_pch700}, {0x8086, 0x7a13, B_S, NT, "Intel", "C266", enable_flash_pch700}, {0x8086, 0x7e23, B_S, DEP, "Intel", "Meteor Lake-P/M", enable_flash_mtl}, + {0x8086, 0xe323, B_S, DEP, "Intel", "Panther Lake-U/H 12Xe", enable_flash_ptl}, + {0x8086, 0xe423, B_S, DEP, "Intel", "Panther Lake-H 4Xe", enable_flash_ptl}, #endif {0}, }; @@ -2371,7 +2394,7 @@ int chipset_flash_enable(const struct programmer_cfg *cfg) if (chipset_enables[i].status == BAD) { msg_perr("ERROR: This chipset is not supported yet.\n"); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } if (chipset_enables[i].status == NT) { msg_pinfo("This chipset is marked as untested. If " @@ -2395,9 +2418,9 @@ int chipset_flash_enable(const struct programmer_cfg *cfg) msg_pinfo("FAILED!\n"); else if (ret == 0) msg_pinfo("OK.\n"); - else if (ret == ERROR_NONFATAL) + else if (ret == ERROR_FLASHROM_NONFATAL) msg_pinfo("PROBLEMS, continuing anyway\n"); - if (ret == ERROR_FATAL) { + if (ret == ERROR_FLASHROM_FATAL) { msg_perr("FATAL ERROR!\n"); return ret; } diff --git a/cli_classic.c b/cli_classic.c index 3de00206f..334343849 100644 --- a/cli_classic.c +++ b/cli_classic.c @@ -24,19 +24,60 @@ #include #include #include -#include +#include #include "flash.h" #include "flashchips.h" #include "fmap.h" #include "programmer.h" #include "libflashrom.h" +enum { + OPTION_IFD = 0x0100, + OPTION_FMAP, + OPTION_FMAP_FILE, + OPTION_FLASH_CONTENTS, + OPTION_FLASH_NAME, + OPTION_FLASH_SIZE, + OPTION_WP_STATUS, + OPTION_WP_SET_RANGE, + OPTION_WP_SET_REGION, + OPTION_WP_ENABLE, + OPTION_WP_DISABLE, + OPTION_WP_LIST, + OPTION_PROGRESS, +}; + +struct cli_options { + bool read_it, extract_it, write_it, erase_it, verify_it; + bool dont_verify_it, dont_verify_all; + bool list_supported; + char *filename; + + const struct programmer_entry *prog; + char *pparam; + + bool ifd, fmap; + struct flashrom_layout *layout; + struct layout_include_args *include_args; + char *layoutfile; + char *fmapfile; + + unsigned int wp_start, wp_len; + bool enable_wp, disable_wp, print_wp_status; + bool set_wp_range, set_wp_region, print_wp_ranges; + char *wp_region; + + bool force; + bool flash_name, flash_size; + bool show_progress; + char *logfile; + char *referencefile; + const char *chip_to_probe; +}; + static void cli_classic_usage(const char *name) { printf("Usage: %s [-h|-R|-L|" -#if CONFIG_PRINT_WIKI == 1 - "-z|" -#endif "\n\t-p [:] [-c ]\n" "\t\t(--flash-name|--flash-size|\n" "\t\t [-E|-x|(-r|-w|-v) ]\n" @@ -71,21 +112,16 @@ static void cli_classic_usage(const char *name) " --fmap read ROM layout from fmap embedded in ROM\n" " --fmap-file read ROM layout from fmap in \n" " --ifd read layout from an Intel Firmware Descriptor\n" - " -i | --image [:] only read/write image from layout\n" + " -i | --include [:] only read/write image from layout\n" " (optionally with data from )\n" + " --image [:] deprecated, please use --include\n" " -o | --output log output to \n" " --flash-contents assume flash contents to be \n" " -L | --list-supported print supported devices\n" -#if CONFIG_PRINT_WIKI == 1 - " -z | --list-supported-wiki print supported devices in wiki syntax\n" -#endif " --progress show progress percentage on the standard output\n" " -p | --programmer [:] specify the programmer device. One of\n"); list_programmers_linebreak(4, 80, 0); printf(".\n\nYou can specify one of -h, -R, -L, " -#if CONFIG_PRINT_WIKI == 1 - "-z, " -#endif "-E, -r, -w, -v or no operation.\n" "If no operation is specified, flashrom will only probe for flash chips.\n"); } @@ -127,7 +163,7 @@ static bool check_file(FILE *file) return true; } -static int parse_wp_range(uint32_t *start, uint32_t *len) +static int parse_wp_range(unsigned int *start, unsigned int *len) { char *endptr = NULL, *token = NULL; @@ -202,6 +238,8 @@ static const char *get_wp_error_str(int err) return "the requested protection range is not supported"; case FLASHROM_WP_ERR_RANGE_LIST_UNAVAILABLE: return "could not determine what protection ranges are available"; + case FLASHROM_WP_ERR_UNSUPPORTED_STATE: + return "can't operate on current WP configuration of the chip"; } return "unknown WP error"; } @@ -385,8 +423,9 @@ static int read_buf_from_include_args(const struct flashrom_layout *const layout while ((entry = layout_next_included(layout, entry))) { if (!entry->file) continue; - if (read_buf_from_file(buf + entry->start, - entry->end - entry->start + 1, entry->file)) + const struct flash_region *region = &entry->region; + if (read_buf_from_file(buf + region->start, + region->end - region->start + 1, entry->file)) return 1; } return 0; @@ -411,8 +450,9 @@ static int write_buf_to_include_args(const struct flashrom_layout *const layout, while ((entry = layout_next_included(layout, entry))) { if (!entry->file) continue; - if (write_buf_to_file(buf + entry->start, - entry->end - entry->start + 1, entry->file)) + const struct flash_region *region = &entry->region; + if (write_buf_to_file(buf + region->start, + region->end - region->start + 1, entry->file)) return 1; } @@ -516,113 +556,58 @@ static int do_verify(struct flashctx *const flash, const char *const filename) return ret; } -int main(int argc, char *argv[]) +/* Returns the number of buses commonly supported by the current programmer and flash chip where the latter + * can not be completely accessed due to size/address limits of the programmer. */ +static unsigned int count_max_decode_exceedings(const struct flashctx *flash, + const struct decode_sizes *max_rom_decode_) { - const struct flashchip *chip = NULL; - /* Probe for up to eight flash chips. */ - struct flashctx flashes[8] = {{0}}; - struct flashctx *fill_flash; - const char *name; - int namelen, opt, i, j; - int startchip = -1, chipcount = 0, option_index = 0; - int operation_specified = 0; - uint32_t wp_start = 0, wp_len = 0; - bool force = false, ifd = false, fmap = false; -#if CONFIG_PRINT_WIKI == 1 - bool list_supported_wiki = false; -#endif - bool flash_name = false, flash_size = false; - bool enable_wp = false, disable_wp = false, print_wp_status = false; - bool set_wp_range = false, set_wp_region = false, print_wp_ranges = false; - bool read_it = false, extract_it = false, write_it = false, erase_it = false, verify_it = false; - bool dont_verify_it = false, dont_verify_all = false; - bool list_supported = false; - bool show_progress = false; - struct flashrom_layout *layout = NULL; - static const struct programmer_entry *prog = NULL; - enum { - OPTION_IFD = 0x0100, - OPTION_FMAP, - OPTION_FMAP_FILE, - OPTION_FLASH_CONTENTS, - OPTION_FLASH_NAME, - OPTION_FLASH_SIZE, - OPTION_WP_STATUS, - OPTION_WP_SET_RANGE, - OPTION_WP_SET_REGION, - OPTION_WP_ENABLE, - OPTION_WP_DISABLE, - OPTION_WP_LIST, - OPTION_PROGRESS, - }; - int ret = 0; - - static const char optstring[] = "r:Rw:v:nNVEfc:l:i:p:Lzho:x"; - static const struct option long_options[] = { - {"read", 1, NULL, 'r'}, - {"write", 1, NULL, 'w'}, - {"erase", 0, NULL, 'E'}, - {"verify", 1, NULL, 'v'}, - {"noverify", 0, NULL, 'n'}, - {"noverify-all", 0, NULL, 'N'}, - {"extract", 0, NULL, 'x'}, - {"chip", 1, NULL, 'c'}, - {"verbose", 0, NULL, 'V'}, - {"force", 0, NULL, 'f'}, - {"layout", 1, NULL, 'l'}, - {"ifd", 0, NULL, OPTION_IFD}, - {"fmap", 0, NULL, OPTION_FMAP}, - {"fmap-file", 1, NULL, OPTION_FMAP_FILE}, - {"image", 1, NULL, 'i'}, - {"flash-contents", 1, NULL, OPTION_FLASH_CONTENTS}, - {"flash-name", 0, NULL, OPTION_FLASH_NAME}, - {"flash-size", 0, NULL, OPTION_FLASH_SIZE}, - {"get-size", 0, NULL, OPTION_FLASH_SIZE}, // (deprecated): back compatibility. - {"wp-status", 0, NULL, OPTION_WP_STATUS}, - {"wp-list", 0, NULL, OPTION_WP_LIST}, - {"wp-range", 1, NULL, OPTION_WP_SET_RANGE}, - {"wp-region", 1, NULL, OPTION_WP_SET_REGION}, - {"wp-enable", 0, NULL, OPTION_WP_ENABLE}, - {"wp-disable", 0, NULL, OPTION_WP_DISABLE}, - {"list-supported", 0, NULL, 'L'}, - {"list-supported-wiki", 0, NULL, 'z'}, - {"programmer", 1, NULL, 'p'}, - {"help", 0, NULL, 'h'}, - {"version", 0, NULL, 'R'}, - {"output", 1, NULL, 'o'}, - {"progress", 0, NULL, OPTION_PROGRESS}, - {NULL, 0, NULL, 0}, - }; - - char *filename = NULL; - char *referencefile = NULL; - char *layoutfile = NULL; - char *fmapfile = NULL; - char *logfile = NULL; - char *tempstr = NULL; - char *pparam = NULL; - struct layout_include_args *include_args = NULL; - char *wp_region = NULL; - - /* - * Safety-guard against a user who has (mistakenly) closed - * stdout or stderr before exec'ing flashrom. We disable - * logging in this case to prevent writing log data to a flash - * chip when a flash device gets opened with fd 1 or 2. - */ - if (check_file(stdout) && check_file(stderr)) { - flashrom_set_log_callback( - (flashrom_log_callback *)&flashrom_print_cb); + unsigned int limitexceeded = 0; + uint32_t size = flash->chip->total_size * 1024; + enum chipbustype buses = flash->mst->buses_supported & flash->chip->bustype; + + if ((buses & BUS_PARALLEL) && (max_rom_decode_->parallel < size)) { + limitexceeded++; + msg_pdbg("Chip size %"PRIu32" kB is bigger than supported " + "size %"PRIu32" kB of chipset/board/programmer " + "for %s interface, " + "probe/read/erase/write may fail. ", size / 1024, + max_rom_decode_->parallel / 1024, "Parallel"); } + if ((buses & BUS_LPC) && (max_rom_decode_->lpc < size)) { + limitexceeded++; + msg_pdbg("Chip size %"PRIu32" kB is bigger than supported " + "size %"PRIu32" kB of chipset/board/programmer " + "for %s interface, " + "probe/read/erase/write may fail. ", size / 1024, + max_rom_decode_->lpc / 1024, "LPC"); + } + if ((buses & BUS_FWH) && (max_rom_decode_->fwh < size)) { + limitexceeded++; + msg_pdbg("Chip size %"PRIu32" kB is bigger than supported " + "size %"PRIu32" kB of chipset/board/programmer " + "for %s interface, " + "probe/read/erase/write may fail. ", size / 1024, + max_rom_decode_->fwh / 1024, "FWH"); + } + if ((buses & BUS_SPI) && (max_rom_decode_->spi < size)) { + limitexceeded++; + msg_pdbg("Chip size %"PRIu32" kB is bigger than supported " + "size %"PRIu32" kB of chipset/board/programmer " + "for %s interface, " + "probe/read/erase/write may fail. ", size / 1024, + max_rom_decode_->spi / 1024, "SPI"); + } + return limitexceeded; +} - print_version(); - print_banner(); - - /* FIXME: Delay calibration should happen in programmer code. */ - if (flashrom_init(1)) - exit(1); +static void parse_options(int argc, char **argv, const char *optstring, + const struct option *long_options, + struct cli_options *options) +{ + const char *name; + int namelen, opt; + int option_index = 0, operation_specified = 0; - setbuf(stdout, NULL); /* FIXME: Delay all operation_specified checks until after command * line parsing to allow --help overriding everything else. */ @@ -631,38 +616,38 @@ int main(int argc, char *argv[]) switch (opt) { case 'r': cli_classic_validate_singleop(&operation_specified); - filename = strdup(optarg); - read_it = true; + options->filename = strdup(optarg); + options->read_it = true; break; case 'w': cli_classic_validate_singleop(&operation_specified); - filename = strdup(optarg); - write_it = true; + options->filename = strdup(optarg); + options->write_it = true; break; case 'v': //FIXME: gracefully handle superfluous -v cli_classic_validate_singleop(&operation_specified); - if (dont_verify_it) { + if (options->dont_verify_it) { cli_classic_abort_usage("--verify and --noverify are mutually exclusive. Aborting.\n"); } - filename = strdup(optarg); - verify_it = true; + options->filename = strdup(optarg); + options->verify_it = true; break; case 'n': - if (verify_it) { + if (options->verify_it) { cli_classic_abort_usage("--verify and --noverify are mutually exclusive. Aborting.\n"); } - dont_verify_it = true; + options->dont_verify_it = true; break; case 'N': - dont_verify_all = true; + options->dont_verify_all = true; break; case 'x': cli_classic_validate_singleop(&operation_specified); - extract_it = true; + options->extract_it = true; break; case 'c': - chip_to_probe = strdup(optarg); + options->chip_to_probe = strdup(optarg); break; case 'V': verbose_screen++; @@ -671,103 +656,94 @@ int main(int argc, char *argv[]) break; case 'E': cli_classic_validate_singleop(&operation_specified); - erase_it = true; + options->erase_it = true; break; case 'f': - force = true; + options->force = true; break; case 'l': - if (layoutfile) + if (options->layoutfile) cli_classic_abort_usage("Error: --layout specified more than once. Aborting.\n"); - if (ifd) + if (options->ifd) cli_classic_abort_usage("Error: --layout and --ifd both specified. Aborting.\n"); - if (fmap) + if (options->fmap) cli_classic_abort_usage("Error: --layout and --fmap-file both specified. Aborting.\n"); - layoutfile = strdup(optarg); + options->layoutfile = strdup(optarg); break; case OPTION_IFD: - if (layoutfile) + if (options->layoutfile) cli_classic_abort_usage("Error: --layout and --ifd both specified. Aborting.\n"); - if (fmap) + if (options->fmap) cli_classic_abort_usage("Error: --fmap-file and --ifd both specified. Aborting.\n"); - ifd = true; + options->ifd = true; break; case OPTION_FMAP_FILE: - if (fmap) + if (options->fmap) cli_classic_abort_usage("Error: --fmap or --fmap-file specified " "more than once. Aborting.\n"); - if (ifd) + if (options->ifd) cli_classic_abort_usage("Error: --fmap-file and --ifd both specified. Aborting.\n"); - if (layoutfile) + if (options->layoutfile) cli_classic_abort_usage("Error: --fmap-file and --layout both specified. Aborting.\n"); - fmapfile = strdup(optarg); - fmap = true; + options->fmapfile = strdup(optarg); + options->fmap = true; break; case OPTION_FMAP: - if (fmap) + if (options->fmap) cli_classic_abort_usage("Error: --fmap or --fmap-file specified " "more than once. Aborting.\n"); - if (ifd) + if (options->ifd) cli_classic_abort_usage("Error: --fmap and --ifd both specified. Aborting.\n"); - if (layoutfile) + if (options->layoutfile) cli_classic_abort_usage("Error: --layout and --fmap both specified. Aborting.\n"); - fmap = true; + options->fmap = true; break; case 'i': - if (register_include_arg(&include_args, optarg)) + if (register_include_arg(&options->include_args, optarg)) cli_classic_abort_usage(NULL); break; case OPTION_FLASH_CONTENTS: - if (referencefile) + if (options->referencefile) cli_classic_abort_usage("Error: --flash-contents specified more than once." "Aborting.\n"); - referencefile = strdup(optarg); + options->referencefile = strdup(optarg); break; case OPTION_FLASH_NAME: cli_classic_validate_singleop(&operation_specified); - flash_name = true; + options->flash_name = true; break; case OPTION_FLASH_SIZE: cli_classic_validate_singleop(&operation_specified); - flash_size = true; + options->flash_size = true; break; case OPTION_WP_STATUS: - print_wp_status = true; + options->print_wp_status = true; break; case OPTION_WP_LIST: - print_wp_ranges = true; + options->print_wp_ranges = true; break; case OPTION_WP_SET_RANGE: - if (parse_wp_range(&wp_start, &wp_len) < 0) + if (parse_wp_range(&options->wp_start, &options->wp_len) < 0) cli_classic_abort_usage("Incorrect wp-range arguments provided.\n"); - set_wp_range = true; + options->set_wp_range = true; break; case OPTION_WP_SET_REGION: - set_wp_region = true; - wp_region = strdup(optarg); + options->set_wp_region = true; + options->wp_region = strdup(optarg); break; case OPTION_WP_ENABLE: - enable_wp = true; + options->enable_wp = true; break; case OPTION_WP_DISABLE: - disable_wp = true; + options->disable_wp = true; break; case 'L': cli_classic_validate_singleop(&operation_specified); - list_supported = true; - break; - case 'z': -#if CONFIG_PRINT_WIKI == 1 - cli_classic_validate_singleop(&operation_specified); - list_supported_wiki = true; -#else - cli_classic_abort_usage("Error: Wiki output was not " - "compiled in. Aborting.\n"); -#endif + options->list_supported = true; break; case 'p': - if (prog != NULL) { + if (options->prog != NULL) { cli_classic_abort_usage("Error: --programmer specified " "more than once. You can separate " "multiple\nparameters for a programmer " @@ -781,15 +757,15 @@ int main(int argc, char *argv[]) if (strncmp(optarg, name, namelen) == 0) { switch (optarg[namelen]) { case ':': - pparam = strdup(optarg + namelen + 1); - if (!strlen(pparam)) { - free(pparam); - pparam = NULL; + options->pparam = strdup(optarg + namelen + 1); + if (!strlen(options->pparam)) { + free(options->pparam); + options->pparam = NULL; } - prog = programmer_table[p]; + options->prog = programmer_table[p]; break; case '\0': - prog = programmer_table[p]; + options->prog = programmer_table[p]; break; default: /* The continue refers to the @@ -802,7 +778,7 @@ int main(int argc, char *argv[]) break; } } - if (prog == NULL) { + if (options->prog == NULL) { fprintf(stderr, "Error: Unknown programmer \"%s\". Valid choices are:\n", optarg); list_programmers_linebreak(0, 80, 0); @@ -821,18 +797,18 @@ int main(int argc, char *argv[]) exit(0); break; case 'o': - if (logfile) { + if (options->logfile) { fprintf(stderr, "Warning: -o/--output specified multiple times.\n"); - free(logfile); + free(options->logfile); } - logfile = strdup(optarg); - if (logfile[0] == '\0') { + options->logfile = strdup(optarg); + if (options->logfile[0] == '\0') { cli_classic_abort_usage("No log filename specified.\n"); } break; case OPTION_PROGRESS: - show_progress = true; + options->show_progress = true; break; default: cli_classic_abort_usage(NULL); @@ -842,27 +818,101 @@ int main(int argc, char *argv[]) if (optind < argc) cli_classic_abort_usage("Error: Extra parameter found.\n"); - if ((read_it | write_it | verify_it) && check_filename(filename, "image")) +} + +static void free_options(struct cli_options *options) +{ + cleanup_include_args(&options->include_args); + free(options->filename); + free(options->fmapfile); + free(options->referencefile); + free(options->layoutfile); + free(options->pparam); + free(options->wp_region); + free(options->logfile); + free((char *)options->chip_to_probe); +} + +int main(int argc, char *argv[]) +{ + const struct flashchip *chip = NULL; + /* Probe for up to eight flash chips. */ + struct flashctx flashes[8] = {{0}}; + struct flashctx *fill_flash; + char *tempstr = NULL; + int startchip = -1, chipcount = 0; + int i, j; + int ret = 0; + + struct cli_options options = { 0 }; + static const char optstring[] = "r:Rw:v:nNVEfc:l:i:p:Lzho:x"; + static const struct option long_options[] = { + {"read", 1, NULL, 'r'}, + {"write", 1, NULL, 'w'}, + {"erase", 0, NULL, 'E'}, + {"verify", 1, NULL, 'v'}, + {"noverify", 0, NULL, 'n'}, + {"noverify-all", 0, NULL, 'N'}, + {"extract", 0, NULL, 'x'}, + {"chip", 1, NULL, 'c'}, + {"verbose", 0, NULL, 'V'}, + {"force", 0, NULL, 'f'}, + {"layout", 1, NULL, 'l'}, + {"ifd", 0, NULL, OPTION_IFD}, + {"fmap", 0, NULL, OPTION_FMAP}, + {"fmap-file", 1, NULL, OPTION_FMAP_FILE}, + {"image", 1, NULL, 'i'}, // (deprecated): back compatibility. + {"include", 1, NULL, 'i'}, + {"flash-contents", 1, NULL, OPTION_FLASH_CONTENTS}, + {"flash-name", 0, NULL, OPTION_FLASH_NAME}, + {"flash-size", 0, NULL, OPTION_FLASH_SIZE}, + {"get-size", 0, NULL, OPTION_FLASH_SIZE}, // (deprecated): back compatibility. + {"wp-status", 0, NULL, OPTION_WP_STATUS}, + {"wp-list", 0, NULL, OPTION_WP_LIST}, + {"wp-range", 1, NULL, OPTION_WP_SET_RANGE}, + {"wp-region", 1, NULL, OPTION_WP_SET_REGION}, + {"wp-enable", 0, NULL, OPTION_WP_ENABLE}, + {"wp-disable", 0, NULL, OPTION_WP_DISABLE}, + {"list-supported", 0, NULL, 'L'}, + {"programmer", 1, NULL, 'p'}, + {"help", 0, NULL, 'h'}, + {"version", 0, NULL, 'R'}, + {"output", 1, NULL, 'o'}, + {"progress", 0, NULL, OPTION_PROGRESS}, + {NULL, 0, NULL, 0}, + }; + + /* + * Safety-guard against a user who has (mistakenly) closed + * stdout or stderr before exec'ing flashrom. We disable + * logging in this case to prevent writing log data to a flash + * chip when a flash device gets opened with fd 1 or 2. + */ + if (check_file(stdout) && check_file(stderr)) { + flashrom_set_log_callback(&flashrom_print_cb); + } + + print_version(); + print_banner(); + + setbuf(stdout, NULL); + + parse_options(argc, argv, optstring, long_options, &options); + + if ((options.read_it | options.write_it | options.verify_it) && check_filename(options.filename, "image")) cli_classic_abort_usage(NULL); - if (layoutfile && check_filename(layoutfile, "layout")) + if (options.layoutfile && check_filename(options.layoutfile, "layout")) cli_classic_abort_usage(NULL); - if (fmapfile && check_filename(fmapfile, "fmap")) + if (options.fmapfile && check_filename(options.fmapfile, "fmap")) cli_classic_abort_usage(NULL); - if (referencefile && check_filename(referencefile, "reference")) + if (options.referencefile && check_filename(options.referencefile, "reference")) cli_classic_abort_usage(NULL); - if (logfile && check_filename(logfile, "log")) + if (options.logfile && check_filename(options.logfile, "log")) cli_classic_abort_usage(NULL); - if (logfile && open_logfile(logfile)) + if (options.logfile && open_logfile(options.logfile)) cli_classic_abort_usage(NULL); -#if CONFIG_PRINT_WIKI == 1 - if (list_supported_wiki) { - print_supported_wiki(); - goto out; - } -#endif - - if (list_supported) { + if (options.list_supported) { if (print_supported()) ret = 1; goto out; @@ -877,22 +927,22 @@ int main(int argc, char *argv[]) } msg_gdbg("\n"); - if (layoutfile && layout_from_file(&layout, layoutfile)) { + if (options.layoutfile && layout_from_file(&options.layout, options.layoutfile)) { ret = 1; goto out; } - if (!ifd && !fmap && process_include_args(layout, include_args)) { + if (!options.ifd && !options.fmap && process_include_args(options.layout, options.include_args)) { ret = 1; goto out; } /* Does a chip with the requested name exist in the flashchips array? */ - if (chip_to_probe) { + if (options.chip_to_probe) { for (chip = flashchips; chip && chip->name; chip++) - if (!strcmp(chip->name, chip_to_probe)) + if (!strcmp(chip->name, options.chip_to_probe)) break; if (!chip || !chip->name) { - msg_cerr("Error: Unknown chip '%s' specified.\n", chip_to_probe); + msg_cerr("Error: Unknown chip '%s' specified.\n", options.chip_to_probe); msg_gerr("Run flashrom -L to view the hardware supported in this flashrom version.\n"); ret = 1; goto out; @@ -900,15 +950,15 @@ int main(int argc, char *argv[]) /* Keep chip around for later usage in case a forced read is requested. */ } - if (prog == NULL) { + if (options.prog == NULL) { const struct programmer_entry *const default_programmer = CONFIG_DEFAULT_PROGRAMMER_NAME; if (default_programmer) { - prog = default_programmer; + options.prog = default_programmer; /* We need to strdup here because we free(pparam) unconditionally later. */ - pparam = strdup(CONFIG_DEFAULT_PROGRAMMER_ARGS); + options.pparam = strdup(CONFIG_DEFAULT_PROGRAMMER_ARGS); msg_pinfo("Using default programmer \"%s\" with arguments \"%s\".\n", - default_programmer->name, pparam); + default_programmer->name, options.pparam); } else { msg_perr("Please select a programmer with the --programmer parameter.\n" #if CONFIG_INTERNAL == 1 @@ -922,19 +972,23 @@ int main(int argc, char *argv[]) } } - if (programmer_init(prog, pparam)) { + /* FIXME: Delay calibration should happen in programmer code. */ + if (flashrom_init(1)) + exit(1); + + if (programmer_init(options.prog, options.pparam)) { msg_perr("Error: Programmer initialization failed.\n"); ret = 1; goto out_shutdown; } tempstr = flashbuses_to_text(get_buses_supported()); - msg_pdbg("The following protocols are supported: %s.\n", tempstr); + msg_pdbg("The following protocols are supported: %s.\n", tempstr ? tempstr : "?"); free(tempstr); for (j = 0; j < registered_master_count; j++) { startchip = 0; while (chipcount < (int)ARRAY_SIZE(flashes)) { - startchip = probe_flash(®istered_masters[j], startchip, &flashes[chipcount], 0); + startchip = probe_flash(®istered_masters[j], startchip, &flashes[chipcount], 0, options.chip_to_probe); if (startchip == -1) break; chipcount++; @@ -952,11 +1006,11 @@ int main(int argc, char *argv[]) goto out_shutdown; } else if (!chipcount) { msg_cinfo("No EEPROM/flash device found.\n"); - if (!force || !chip_to_probe) { + if (!options.force || !options.chip_to_probe) { msg_cinfo("Note: flashrom can never write if the flash chip isn't found " "automatically.\n"); } - if (force && read_it && chip_to_probe) { + if (options.force && options.read_it && options.chip_to_probe) { struct registered_master *mst; int compatible_masters = 0; msg_cinfo("Force read (-f -r -c) requested, pretending the chip is there:\n"); @@ -977,29 +1031,30 @@ int main(int argc, char *argv[]) "chip, using the first one.\n"); for (j = 0; j < registered_master_count; j++) { mst = ®istered_masters[j]; - startchip = probe_flash(mst, 0, &flashes[0], 1); + startchip = probe_flash(mst, 0, &flashes[0], 1, options.chip_to_probe); if (startchip != -1) break; } if (startchip == -1) { // FIXME: This should never happen! Ask for a bug report? - msg_cinfo("Probing for flash chip '%s' failed.\n", chip_to_probe); + msg_cinfo("Probing for flash chip '%s' failed.\n", options.chip_to_probe); ret = 1; goto out_shutdown; } msg_cinfo("Please note that forced reads most likely contain garbage.\n"); - flashrom_flag_set(&flashes[0], FLASHROM_FLAG_FORCE, force); - ret = do_read(&flashes[0], filename); + flashrom_flag_set(&flashes[0], FLASHROM_FLAG_FORCE, options.force); + ret = do_read(&flashes[0], options.filename); free(flashes[0].chip); goto out_shutdown; } ret = 1; goto out_shutdown; - } else if (!chip_to_probe) { + } else if (!options.chip_to_probe) { /* repeat for convenience when looking at foreign logs */ tempstr = flashbuses_to_text(flashes[0].chip->bustype); msg_gdbg("Found %s flash chip \"%s\" (%d kB, %s).\n", - flashes[0].chip->vendor, flashes[0].chip->name, flashes[0].chip->total_size, tempstr); + flashes[0].chip->vendor, flashes[0].chip->name, flashes[0].chip->total_size, + tempstr ? tempstr : "?"); free(tempstr); } @@ -1009,13 +1064,13 @@ int main(int argc, char *argv[]) struct flashrom_progress progress_state = { .user_data = progress_user_data }; - if (show_progress) + if (options.show_progress) flashrom_set_progress_callback(fill_flash, &flashrom_progress_cb, &progress_state); print_chip_support_status(fill_flash->chip); - unsigned int limitexceeded = count_max_decode_exceedings(fill_flash); - if (limitexceeded > 0 && !force) { + unsigned int limitexceeded = count_max_decode_exceedings(fill_flash, &max_rom_decode); + if (limitexceeded > 0 && !options.force) { enum chipbustype commonbuses = fill_flash->mst->buses_supported & fill_flash->chip->bustype; /* Sometimes chip and programmer have more than one bus in common, @@ -1031,29 +1086,30 @@ int main(int argc, char *argv[]) } const bool any_wp_op = - set_wp_range || set_wp_region || enable_wp || - disable_wp || print_wp_status || print_wp_ranges; + options.set_wp_range || options.set_wp_region || options.enable_wp || + options.disable_wp || options.print_wp_status || options.print_wp_ranges; - const bool any_op = read_it || write_it || verify_it || erase_it || - flash_name || flash_size || extract_it || any_wp_op; + const bool any_op = options.read_it || options.write_it || options.verify_it || + options.erase_it || options.flash_name || options.flash_size || + options.extract_it || any_wp_op; if (!any_op) { msg_ginfo("No operations were specified.\n"); goto out_shutdown; } - if (enable_wp && disable_wp) { + if (options.enable_wp && options.disable_wp) { msg_ginfo("Error: --wp-enable and --wp-disable are mutually exclusive\n"); ret = 1; goto out_shutdown; } - if (set_wp_range && set_wp_region) { + if (options.set_wp_range && options.set_wp_region) { msg_gerr("Error: Cannot use both --wp-range and --wp-region simultaneously.\n"); ret = 1; goto out_shutdown; } - if (flash_name) { + if (options.flash_name) { if (fill_flash->chip->vendor && fill_flash->chip->name) { printf("vendor=\"%s\" name=\"%s\"\n", fill_flash->chip->vendor, @@ -1064,19 +1120,19 @@ int main(int argc, char *argv[]) goto out_shutdown; } - if (flash_size) { + if (options.flash_size) { printf("%zu\n", flashrom_flash_getsize(fill_flash)); goto out_shutdown; } - if (ifd && (flashrom_layout_read_from_ifd(&layout, fill_flash, NULL, 0) || - process_include_args(layout, include_args))) { + if (options.ifd && (flashrom_layout_read_from_ifd(&options.layout, fill_flash, NULL, 0) || + process_include_args(options.layout, options.include_args))) { ret = 1; goto out_shutdown; - } else if (fmap && fmapfile) { + } else if (options.fmap && options.fmapfile) { struct stat s; - if (stat(fmapfile, &s) != 0) { - msg_gerr("Failed to stat fmapfile \"%s\"\n", fmapfile); + if (stat(options.fmapfile, &s) != 0) { + msg_gerr("Failed to stat fmapfile \"%s\"\n", options.fmapfile); ret = 1; goto out_shutdown; } @@ -1088,72 +1144,73 @@ int main(int argc, char *argv[]) goto out_shutdown; } - if (read_buf_from_file(fmapfile_buffer, fmapfile_size, fmapfile)) { + if (read_buf_from_file(fmapfile_buffer, fmapfile_size, options.fmapfile)) { ret = 1; free(fmapfile_buffer); goto out_shutdown; } - if (flashrom_layout_read_fmap_from_buffer(&layout, fill_flash, fmapfile_buffer, fmapfile_size) || - process_include_args(layout, include_args)) { + if (flashrom_layout_read_fmap_from_buffer(&options.layout, fill_flash, fmapfile_buffer, fmapfile_size) || + process_include_args(options.layout, options.include_args)) { ret = 1; free(fmapfile_buffer); goto out_shutdown; } free(fmapfile_buffer); - } else if (fmap && (flashrom_layout_read_fmap_from_rom(&layout, fill_flash, 0, - flashrom_flash_getsize(fill_flash)) || process_include_args(layout, include_args))) { + } else if (options.fmap && (flashrom_layout_read_fmap_from_rom(&options.layout, fill_flash, 0, + flashrom_flash_getsize(fill_flash)) || + process_include_args(options.layout, options.include_args))) { ret = 1; goto out_shutdown; } - flashrom_layout_set(fill_flash, layout); + flashrom_layout_set(fill_flash, options.layout); if (any_wp_op) { - if (set_wp_region && wp_region) { - if (!layout) { + if (options.set_wp_region && options.wp_region) { + if (!options.layout) { msg_gerr("Error: A flash layout must be specified to use --wp-region.\n"); ret = 1; goto out_release; } - ret = flashrom_layout_get_region_range(layout, wp_region, &wp_start, &wp_len); + ret = flashrom_layout_get_region_range(options.layout, options.wp_region, &options.wp_start, &options.wp_len); if (ret) { - msg_gerr("Error: Region %s not found in flash layout.\n", wp_region); + msg_gerr("Error: Region %s not found in flash layout.\n", options.wp_region); goto out_release; } - set_wp_range = true; + options.set_wp_range = true; } ret = wp_cli( fill_flash, - enable_wp, - disable_wp, - print_wp_status, - print_wp_ranges, - set_wp_range, - wp_start, - wp_len + options.enable_wp, + options.disable_wp, + options.print_wp_status, + options.print_wp_ranges, + options.set_wp_range, + options.wp_start, + options.wp_len ); if (ret) goto out_release; } - flashrom_flag_set(fill_flash, FLASHROM_FLAG_FORCE, force); + flashrom_flag_set(fill_flash, FLASHROM_FLAG_FORCE, options.force); #if CONFIG_INTERNAL == 1 flashrom_flag_set(fill_flash, FLASHROM_FLAG_FORCE_BOARDMISMATCH, force_boardmismatch); #endif - flashrom_flag_set(fill_flash, FLASHROM_FLAG_VERIFY_AFTER_WRITE, !dont_verify_it); - flashrom_flag_set(fill_flash, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, !dont_verify_all); + flashrom_flag_set(fill_flash, FLASHROM_FLAG_VERIFY_AFTER_WRITE, !options.dont_verify_it); + flashrom_flag_set(fill_flash, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, !options.dont_verify_all); /* FIXME: We should issue an unconditional chip reset here. This can be * done once we have a .reset function in struct flashchip. * Give the chip time to settle. */ - programmer_delay(100000); - if (read_it) - ret = do_read(fill_flash, filename); - else if (extract_it) + programmer_delay(fill_flash, 100000); + if (options.read_it) + ret = do_read(fill_flash, options.filename); + else if (options.extract_it) ret = do_extract(fill_flash); - else if (erase_it) { + else if (options.erase_it) { ret = flashrom_flash_erase(fill_flash); /* * FIXME: Do we really want the scary warning if erase failed? @@ -1165,13 +1222,13 @@ int main(int argc, char *argv[]) if (ret) emergency_help_message(); } - else if (write_it) - ret = do_write(fill_flash, filename, referencefile); - else if (verify_it) - ret = do_verify(fill_flash, filename); + else if (options.write_it) + ret = do_write(fill_flash, options.filename, options.referencefile); + else if (options.verify_it) + ret = do_verify(fill_flash, options.filename); out_release: - flashrom_layout_release(layout); + flashrom_layout_release(options.layout); out_shutdown: flashrom_programmer_shutdown(NULL); out: @@ -1180,17 +1237,7 @@ int main(int argc, char *argv[]) free(flashes[i].chip); } - cleanup_include_args(&include_args); - free(filename); - free(fmapfile); - free(referencefile); - free(layoutfile); - free(pparam); - free(wp_region); - /* clean up global variables */ - free((char *)chip_to_probe); /* Silence! Freeing is not modifying contents. */ - chip_to_probe = NULL; - free(logfile); + free_options(&options); ret |= close_logfile(); return ret; } diff --git a/cli_common.c b/cli_common.c index 93758590b..afcd1f34e 100644 --- a/cli_common.c +++ b/cli_common.c @@ -35,12 +35,14 @@ void print_chip_support_status(const struct flashchip *chip) if ((chip->tested.probe == BAD) || (chip->tested.probe == NT) || (chip->tested.read == BAD) || (chip->tested.read == NT) || (chip->tested.erase == BAD) || (chip->tested.erase == NT) || - (chip->tested.write == BAD) || (chip->tested.write == NT)){ + (chip->tested.write == BAD) || (chip->tested.write == NT) || + (chip->tested.wp == BAD) || (chip->tested.wp == NT)){ msg_cinfo("===\n"); if ((chip->tested.probe == BAD) || (chip->tested.read == BAD) || (chip->tested.erase == BAD) || - (chip->tested.write == BAD)) { + (chip->tested.write == BAD) || + (chip->tested.wp == BAD)) { msg_cinfo("This flash part has status NOT WORKING for operations:"); if (chip->tested.probe == BAD) msg_cinfo(" PROBE"); @@ -50,12 +52,15 @@ void print_chip_support_status(const struct flashchip *chip) msg_cinfo(" ERASE"); if (chip->tested.write == BAD) msg_cinfo(" WRITE"); + if (chip->tested.wp == BAD) + msg_cinfo(" WP"); msg_cinfo("\n"); } if ((chip->tested.probe == NT) || (chip->tested.read == NT) || (chip->tested.erase == NT) || - (chip->tested.write == NT)) { + (chip->tested.write == NT) || + (chip->tested.wp == NT)) { msg_cinfo("This flash part has status UNTESTED for operations:"); if (chip->tested.probe == NT) msg_cinfo(" PROBE"); @@ -65,6 +70,8 @@ void print_chip_support_status(const struct flashchip *chip) msg_cinfo(" ERASE"); if (chip->tested.write == NT) msg_cinfo(" WRITE"); + if (chip->tested.wp == NT) + msg_cinfo(" WP"); msg_cinfo("\n"); } msg_cinfo("The test status of this chip may have been updated in the latest development\n" @@ -73,6 +80,8 @@ void print_chip_support_status(const struct flashchip *chip) "work correctly for you with this flash chip. Please include the flashrom log\n" "file for all operations you tested (see the man page for details), and mention\n" "which mainboard or programmer you tested in the subject line.\n" + "You can also try to follow the instructions here:\n" + "https://www.flashrom.org/contrib_howtos/how_to_mark_chip_tested.html\n" "Thanks for your help!\n"); } } diff --git a/cli_getopt.c b/cli_getopt.c new file mode 100644 index 000000000..fc51fcf92 --- /dev/null +++ b/cli_getopt.c @@ -0,0 +1,263 @@ +/* + * This file is part of the flashrom project. + * It comes originally from the musl libc project and is licensed under the + * terms of the MIT license. + * + * Copyringht (C) 2023 Rich Felker and the musl authors + * Adjusted for flashrom by Thomas Heijligen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include "cli_classic.h" +#include "flash.h" + +char *optarg; +int optind=1, opterr=1, optopt, optpos; + +static void getopt_msg(const char *a, const char *b, const char *c, size_t l) +{ + msg_gerr("%s%s%*c\n", a, b, l, c); +} + +int getopt(int argc, char * const argv[], const char *optstring) +{ + int i; + wchar_t c, d; + int k, l; + char *optchar; + + if (!optind) { + optind = 1; + optpos = 0; + } + + if (optind >= argc || !argv[optind]) + return -1; + + if (argv[optind][0] != '-') { + if (optstring[0] == '-') { + optarg = argv[optind++]; + return 1; + } + return -1; + } + + if (!argv[optind][1]) + return -1; + + if (argv[optind][1] == '-' && !argv[optind][2]) + return optind++, -1; + + if (!optpos) + optpos++; + if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) { + k = 1; + c = 0xfffd; /* replacement char */ + } + optchar = argv[optind]+optpos; + optpos += k; + + if (!argv[optind][optpos]) { + optind++; + optpos = 0; + } + + if (optstring[0] == '-' || optstring[0] == '+') + optstring++; + + i = 0; + d = 0; + do { + l = mbtowc(&d, optstring+i, MB_LEN_MAX); + if (l>0) i+=l; else i++; + } while (l && d != c); + + if (d != c || c == ':') { + optopt = c; + if (optstring[0] != ':' && opterr) + getopt_msg(argv[0], ": unrecognized option: ", optchar, k); + return '?'; + } + if (optstring[i] == ':') { + optarg = 0; + if (optstring[i+1] != ':' || optpos) { + optarg = argv[optind++] + optpos; + optpos = 0; + } + if (optind > argc) { + optopt = c; + if (optstring[0] == ':') + return ':'; + if (opterr) getopt_msg(argv[0], + ": option requires an argument: ", + optchar, k); + return '?'; + } + } + return c; +} + +static int __getopt_long_core(int argc, char *const *argv, const char *optstring, + const struct option *longopts, int *idx, int longonly) +{ + optarg = 0; + if (longopts && argv[optind][0] == '-' && + ((longonly && argv[optind][1] && argv[optind][1] != '-') || + (argv[optind][1] == '-' && argv[optind][2]))) + { + int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':'; + int i, cnt, match = 0; + char *arg = NULL, *opt, *start = argv[optind]+1; + for (cnt=i=0; longopts[i].name; i++) { + const char *name = longopts[i].name; + opt = start; + if (*opt == '-') opt++; + while (*opt && *opt != '=' && *opt == *name) + name++, opt++; + if (*opt && *opt != '=') continue; + arg = opt; + match = i; + if (!*name) { + cnt = 1; + break; + } + cnt++; + } + if (cnt==1 && longonly && arg-start == mblen(start, MB_LEN_MAX)) { + int l = arg-start; + for (i=0; optstring[i]; i++) { + int j; + for (j=0; jdest; i--) + av[i] = av[i-1]; + av[dest] = tmp; +} + +static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly) +{ + int ret, skipped, resumed; + if (!optind) { + optind = 1; + optpos = 0; + } + + if (optind >= argc || !argv[optind]) + return -1; + skipped = optind; + if (optstring[0] != '+' && optstring[0] != '-') { + int i; + for (i=optind; ; i++) { + if (i >= argc || !argv[i]) + return -1; + if (argv[i][0] == '-' && argv[i][1]) + break; + } + optind = i; + } + resumed = optind; + ret = __getopt_long_core(argc, argv, optstring, longopts, idx, longonly); + if (resumed > skipped) { + int i, cnt = optind-resumed; + for (i=0; i + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +#include "custom_baud.h" + +int use_custom_baud(unsigned int baud, const struct baudentry *baudtable) +{ + int i; + + if (baud > 230400) + return 1; + + for (i = 0; baudtable[i].baud; i++) { + if (baudtable[i].baud == baud) + return 0; + + if (baudtable[i].baud > baud) + return 1; + } + + return 1; +} + +int set_custom_baudrate(int fd, unsigned int baud, const enum custom_baud_stage stage, void *tio_wanted) +{ + struct termios *wanted; + speed_t speed; + + switch (stage) { + case BEFORE_FLAGS: + break; + + case WITH_FLAGS: + wanted = tio_wanted; + return cfsetspeed(wanted, B19200); + + case AFTER_FLAGS: + speed = baud; + return ioctl(fd, IOSSIOSPEED, &speed); + } + + return 0; +} diff --git a/custom_baud_linux.c b/custom_baud_linux.c index 2d5f261d1..761d49611 100644 --- a/custom_baud_linux.c +++ b/custom_baud_linux.c @@ -29,9 +29,13 @@ * for more info. */ -int set_custom_baudrate(int fd, unsigned int baud) +int set_custom_baudrate(int fd, unsigned int baud, const enum custom_baud_stage stage, void *tio_wanted) { struct termios2 tio; + + if (stage != BEFORE_FLAGS) + return 0; + if (ioctl(fd, TCGETS2, &tio)) { return -1; } diff --git a/dediprog.c b/dediprog.c index ae9e4486a..aa3a1cf0c 100644 --- a/dediprog.c +++ b/dediprog.c @@ -316,7 +316,7 @@ static int dediprog_set_spi_voltage(libusb_device_handle *dediprog_handle, int m if (voltage_selector == 0) { /* Wait some time as the original driver does. */ - programmer_delay(200 * 1000); + default_delay(200 * 1000); } ret = dediprog_write(dediprog_handle, CMD_SET_VCC, voltage_selector, 0, NULL, 0); if (ret != 0x0) { @@ -326,7 +326,7 @@ static int dediprog_set_spi_voltage(libusb_device_handle *dediprog_handle, int m } if (voltage_selector != 0) { /* Wait some time as the original driver does. */ - programmer_delay(200 * 1000); + default_delay(200 * 1000); } return 0; } @@ -593,7 +593,7 @@ static int dediprog_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int static int dediprog_spi_bulk_write(struct flashctx *flash, const uint8_t *buf, unsigned int chunksize, unsigned int start, unsigned int len, uint8_t dedi_spi_cmd) { - /* USB transfer size must be 512, other sizes will NOT work at all. + /* USB transfer size must be 256, other sizes will NOT work at all. * chunksize is the real data size per USB bulk transfer. The remaining * space in a USB bulk transfer must be filled with 0xff padding. */ @@ -1034,12 +1034,10 @@ static struct spi_master spi_master_dediprog = { .max_data_read = 16, /* 18 seems to work fine as well, but 19 times out sometimes with FW 5.15. */ .max_data_write = 16, .command = dediprog_spi_send_command, - .multicommand = default_spi_send_multicommand, .read = dediprog_spi_read, .write_256 = dediprog_spi_write_256, .write_aai = dediprog_spi_write_aai, .shutdown = dediprog_shutdown, - .probe_opcode = default_spi_probe_opcode, }; /* diff --git a/digilent_spi.c b/digilent_spi.c index 6575cbffd..ef0d23cf7 100644 --- a/digilent_spi.c +++ b/digilent_spi.c @@ -333,12 +333,9 @@ static const struct spi_master spi_master_digilent_spi = { .max_data_read = 252, .max_data_write = 252, .command = digilent_spi_send_command, - .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = digilent_spi_shutdown, - .probe_opcode = default_spi_probe_opcode, }; static bool default_reset(struct libusb_device_handle *handle) diff --git a/dirtyjtag_spi.c b/dirtyjtag_spi.c new file mode 100644 index 000000000..19764f62b --- /dev/null +++ b/dirtyjtag_spi.c @@ -0,0 +1,318 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2021-2022 Jean THOMAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * Driver for the DirtyJTAG project. + * See https://github.com/jeanthom/dirtyjtag for more info. + * + * SPI-JTAG Pin Mapping + * |=========|==========| + * | SPI pin | JTAG pin | + * |=========|==========| + * | #CS | TMS | + * | #WP | SRST | + * | #HOLD | TRST | + * | MISO | TDO | + * | MOSI | TDI | + * | CLK | TCK | + * |=========|==========| + */ + +#include +#include +#include +#include +#include +#include "programmer.h" + +struct dirtyjtag_spi_data { + struct libusb_context *libusb_ctx; + struct libusb_device_handle *libusb_handle; +}; + +static const struct dev_entry devs_dirtyjtag_spi[] = { + { 0x1209, 0xc0ca, OK, "DirtyJTAG", "JTAG probe" }, + { 0 }, +}; + +static const char dirtyjtag_write_endpoint = 0x01; +static const char dirtyjtag_read_endpoint = 0x82; +static const int dirtyjtag_timeout = 100 * 10; /* 100 ms */ + +enum dirtyjtag_command_identifier { + CMD_STOP = 0x00, + CMD_INFO = 0x01, + CMD_FREQ = 0x02, + CMD_XFER = 0x03, + CMD_SETSIG = 0x04, + CMD_GETSIG = 0x05, + CMD_CLK = 0x06 +}; + +enum dirtyjtag_signal_identifier { + SIG_TCK = 1 << 1, + SIG_TDI = 1 << 2, + SIG_TDO = 1 << 3, + SIG_TMS = 1 << 4, + SIG_TRST = 1 << 5, + SIG_SRST = 1 << 6 +}; + +static int dirtyjtag_send(struct dirtyjtag_spi_data *djtag_data, uint8_t *data, size_t len) +{ + int transferred; + int ret = libusb_bulk_transfer(djtag_data->libusb_handle, + dirtyjtag_write_endpoint, + data, + len, + &transferred, + dirtyjtag_timeout); + if (ret != 0) { + msg_perr("%s: failed to send query command\n", __func__); + return -1; + } + if (transferred != (int)len) { + msg_perr("%s: failed to send whole packet\n", __func__); + return -1; + } + + return 0; +} + +static int dirtyjtag_receive(struct dirtyjtag_spi_data *djtag_data, uint8_t *data, size_t buffer_len, int expected) +{ + int transferred; + int ret = libusb_bulk_transfer(djtag_data->libusb_handle, + dirtyjtag_read_endpoint, + data, + buffer_len, + &transferred, + dirtyjtag_timeout); + if (ret != 0) { + msg_perr("%s: Failed to read SPI commands\n", __func__); + return -1; + } + + if (expected != -1 && transferred != expected) { + msg_perr("%s: failed to meet expected\n", __func__); + return -1; + } + + return transferred; +} + +static int dirtyjtag_spi_shutdown(void *data) +{ + struct dirtyjtag_spi_data *djtag_data = (struct dirtyjtag_spi_data*)data; + libusb_release_interface(djtag_data->libusb_handle, 0); + libusb_attach_kernel_driver(djtag_data->libusb_handle, 0); + libusb_close(djtag_data->libusb_handle); + libusb_exit(djtag_data->libusb_ctx); + free(data); + return 0; +} + +static int dirtyjtag_djtag1_spi_send_command(struct dirtyjtag_spi_data *context, + unsigned int writecnt, unsigned int readcnt, + const unsigned char *writearr, unsigned char *readarr) +{ + const size_t max_xfer_size = 30; // max transfer size in DJTAG1 + size_t len = writecnt + readcnt; + size_t num_xfer = (len + max_xfer_size - 1 ) / max_xfer_size; // ceil(len/max_xfer_size) + + uint8_t *rxtx_buffer = malloc(max_xfer_size * num_xfer); + if (!rxtx_buffer) { + msg_perr("%s: Failed rxtx_buffer allocation\n", __func__); + return -1; + } + + memcpy(rxtx_buffer, writearr, writecnt); + for (size_t i = 0; i < num_xfer; i++) { + const size_t xfer_offset = i * max_xfer_size; + size_t txn_size = max_xfer_size; + if (i == num_xfer-1 && len % max_xfer_size != 0) + txn_size = len % max_xfer_size; + + uint8_t transfer_buffer[32] = { + CMD_XFER, + txn_size * 8 + }; + memcpy(transfer_buffer + 2, rxtx_buffer + xfer_offset, txn_size); + + if (dirtyjtag_send(context, transfer_buffer, sizeof(transfer_buffer))) + goto cleanup_fail; + + if (dirtyjtag_receive(context, transfer_buffer, sizeof(transfer_buffer), 32) < 0) + goto cleanup_fail; + + memcpy(rxtx_buffer + xfer_offset, transfer_buffer, txn_size); + } + memcpy(readarr, rxtx_buffer + writecnt, readcnt); + + free(rxtx_buffer); + + uint8_t tms_reset_buffer[] = { + CMD_SETSIG, + SIG_TMS, + SIG_TMS, + + CMD_STOP, + }; + dirtyjtag_send(context, tms_reset_buffer, sizeof(tms_reset_buffer)); + + return 0; + +cleanup_fail: + free(rxtx_buffer); + return -1; +} + +static int dirtyjtag_spi_spi_send_command(const struct flashctx *flash, + unsigned int writecnt, unsigned int readcnt, + const unsigned char *writearr, unsigned char *readarr) +{ + struct dirtyjtag_spi_data *djtag_data = flash->mst->spi.data; + return dirtyjtag_djtag1_spi_send_command(djtag_data, writecnt, readcnt, writearr, readarr); +} + +static const struct spi_master spi_master_dirtyjtag_spi = { + .features = SPI_MASTER_4BA, + .max_data_read = MAX_DATA_READ_UNLIMITED, + .max_data_write = MAX_DATA_WRITE_UNLIMITED, + .command = dirtyjtag_spi_spi_send_command, + .read = default_spi_read, + .write_256 = default_spi_write_256, + .write_aai = default_spi_write_aai, + .shutdown = dirtyjtag_spi_shutdown, +}; + +static int dirtyjtag_spi_init(const struct programmer_cfg *cfg) +{ + struct libusb_device_handle *handle = NULL; + struct dirtyjtag_spi_data *djtag_data = NULL; + + djtag_data = calloc(1, sizeof(struct dirtyjtag_spi_data)); + if (djtag_data == NULL) { + msg_perr("%s: failed to allocate internal driver data structure\n", __func__); + return -1; + } + + int ret = libusb_init(&djtag_data->libusb_ctx); + if (ret < 0) { + msg_perr("%s: couldn't initialize libusb!\n", __func__); + goto cleanup_djtag_struct; + } + +#if LIBUSB_API_VERSION < 0x01000106 + libusb_set_debug(djtag_data->libusb_ctx, 3); +#else + libusb_set_option(djtag_data->libusb_ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO); +#endif + + uint16_t vid = devs_dirtyjtag_spi[0].vendor_id; + uint16_t pid = devs_dirtyjtag_spi[0].device_id; + handle = libusb_open_device_with_vid_pid(djtag_data->libusb_ctx, vid, pid); + if (handle == NULL) { + msg_perr("%s: couldn't open device %04x:%04x.\n", __func__, vid, pid); + goto cleanup_libusb_ctx; + } + + ret = libusb_detach_kernel_driver(handle, 0); + if (ret != 0 && ret != LIBUSB_ERROR_NOT_FOUND) { + msg_pwarn("Cannot detach the existing USB driver. Claiming the interface may fail. %s\n", + libusb_error_name(ret)); + } + + ret = libusb_claim_interface(handle, 0); + if (ret != 0) { + msg_perr("%s: failed to claim interface 0: '%s'\n", __func__, libusb_error_name(ret)); + goto cleanup_libusb_handle; + } + + djtag_data->libusb_handle = handle; + + unsigned long int freq = 100; + char *tmp = extract_programmer_param_str(cfg, "spispeed"); + if (tmp) { + char *units = tmp; + + errno = 0; + freq = strtoul(tmp, &units, 0); + if (errno) { + msg_perr("Invalid frequency \"%s\", %s\n", tmp, strerror(errno)); + free(tmp); + goto cleanup_libusb_handle; + } + + if (!strcasecmp(units, "hz")) { + freq /= 1000; + } else if (!strcasecmp(units, "khz")) { + /* Do nothing, already in the right unit */ + } else if (!strcasecmp(units, "mhz")) { + freq *= 1000; + } else { + msg_perr("Invalid unit: %s, use hz, khz or mhz\n", units); + free(tmp); + goto cleanup_libusb_handle; + } + + if (freq > UINT16_MAX) { + msg_perr("%s: Frequency set above DJTAG1 limits (%d kHz)", __func__, UINT16_MAX); + free(tmp); + goto cleanup_libusb_handle; + } + + msg_pinfo("%s: programmer speed set to %lu kHz\n", __func__, freq); + } + free(tmp); + + uint8_t commands[] = { + CMD_SETSIG, /* Set TDI/TCK to low, SRST/TRST/TMS to high */ + SIG_TDI | SIG_TMS | SIG_TCK | SIG_SRST | SIG_TRST, + SIG_SRST | SIG_TRST | SIG_TMS, + + CMD_FREQ, /* Set frequency */ + (freq >> 8) & 0xff, + freq & 0xff, + + CMD_STOP, + }; + ret = dirtyjtag_send(djtag_data, commands, sizeof(commands)); + if (ret != 0) { + msg_perr("%s: failed to configure DirtyJTAG into initialized state\n", __func__); + goto cleanup_libusb_handle; + } + + return register_spi_master(&spi_master_dirtyjtag_spi, (void*)djtag_data); + +cleanup_libusb_handle: + libusb_attach_kernel_driver(handle, 0); + libusb_close(handle); + +cleanup_libusb_ctx: + libusb_exit(djtag_data->libusb_ctx); + +cleanup_djtag_struct: + free(djtag_data); + return -1; +} + +const struct programmer_entry programmer_dirtyjtag_spi = { + .name = "dirtyjtag_spi", + .type = USB, + .devs.dev = devs_dirtyjtag_spi, + .init = dirtyjtag_spi_init, +}; diff --git a/dmi.c b/dmi.c index beeb10f35..94e47fb49 100644 --- a/dmi.c +++ b/dmi.c @@ -151,11 +151,11 @@ static char *dmi_string(const char *buf, uint8_t string_id, const char *limit) return newbuf; } -static void dmi_chassis_type(uint8_t code) +static int dmi_chassis_type(uint8_t code) { unsigned int i; code &= 0x7f; /* bits 6:0 are chassis type, 7th bit is the lock bit */ - is_laptop = 2; + int is_laptop = 2; for (i = 0; i < ARRAY_SIZE(dmi_chassis_types); i++) { if (code == dmi_chassis_types[i].type) { msg_pdbg("DMI string chassis-type: \"%s\"\n", dmi_chassis_types[i].name); @@ -163,9 +163,10 @@ static void dmi_chassis_type(uint8_t code) break; } } + return is_laptop; } -static void dmi_table(uint32_t base, uint16_t len, uint16_t num) +static void dmi_table(uint32_t base, uint16_t len, uint16_t num, int *is_laptop) { unsigned int i = 0, j = 0; @@ -198,7 +199,7 @@ static void dmi_table(uint32_t base, uint16_t len, uint16_t num) if(data[0] == 3) { if (data + 5 < limit) - dmi_chassis_type(data[5]); + *is_laptop = dmi_chassis_type(data[5]); else /* the table is broken, but laptop detection is optional, hence continue. */ msg_pwarn("DMI table is broken (chassis_type out of bounds)!\n"); } else @@ -232,7 +233,7 @@ static void dmi_table(uint32_t base, uint16_t len, uint16_t num) } #if SM_SUPPORT -static int smbios_decode(uint8_t *buf) +static int smbios_decode(uint8_t *buf, int *is_laptop) { /* TODO: other checks mentioned in the conformance guidelines? */ if (!dmi_checksum(buf, buf[0x05]) || @@ -240,23 +241,23 @@ static int smbios_decode(uint8_t *buf) !dmi_checksum(buf + 0x10, 0x0F)) return 0; - dmi_table(mmio_readl(buf + 0x18), mmio_readw(buf + 0x16), mmio_readw(buf + 0x1C)); + dmi_table(mmio_readl(buf + 0x18), mmio_readw(buf + 0x16), mmio_readw(buf + 0x1C), is_laptop); return 1; } #endif -static int legacy_decode(uint8_t *buf) +static int legacy_decode(uint8_t *buf, int *is_laptop) { if (!dmi_checksum(buf, 0x0F)) return 1; - dmi_table(mmio_readl(buf + 0x08), mmio_readw(buf + 0x06), mmio_readw(buf + 0x0C)); + dmi_table(mmio_readl(buf + 0x08), mmio_readw(buf + 0x06), mmio_readw(buf + 0x0C), is_laptop); return 0; } -static int dmi_fill(void) +static int dmi_fill(int *is_laptop) { size_t fp; uint8_t *dmi_mem; @@ -274,12 +275,12 @@ static int dmi_fill(void) for (fp = 0; fp <= 0xFFF0; fp += 16) { #if SM_SUPPORT if (memcmp(dmi_mem + fp, "_SM_", 4) == 0 && fp <= 0xFFE0) { - if (smbios_decode(dmi_mem + fp)) // FIXME: length check + if (smbios_decode(dmi_mem + fp), is_laptop) // FIXME: length check goto out; } else #endif if (memcmp(dmi_mem + fp, "_DMI_", 5) == 0) - if (legacy_decode(dmi_mem + fp) == 0) { + if (legacy_decode(dmi_mem + fp, is_laptop) == 0) { ret = 0; goto out; } @@ -350,7 +351,7 @@ static char *get_dmi_string(const char *string_name) return result; } -static int dmi_fill(void) +static int dmi_fill(int *is_laptop) { unsigned int i; char *chassis_type; @@ -367,10 +368,10 @@ static int dmi_fill(void) return 0; /* chassis-type handling is optional anyway */ msg_pdbg("DMI string chassis-type: \"%s\"\n", chassis_type); - is_laptop = 2; + *is_laptop = 2; for (i = 0; i < ARRAY_SIZE(dmi_chassis_types); i++) { if (strcasecmp(chassis_type, dmi_chassis_types[i].name) == 0) { - is_laptop = dmi_chassis_types[i].is_laptop; + *is_laptop = dmi_chassis_types[i].is_laptop; break; } } @@ -391,7 +392,7 @@ static int dmi_shutdown(void *data) return 0; } -void dmi_init(void) +void dmi_init(int *is_laptop) { /* Register shutdown function before we allocate anything. */ if (register_shutdown(dmi_shutdown, NULL)) { @@ -399,11 +400,11 @@ void dmi_init(void) return; } - /* dmi_fill fills the dmi_strings array, and if possible sets the global is_laptop variable. */ - if (dmi_fill() != 0) + /* dmi_fill fills the dmi_strings array, and if possible set the is_laptop parameter. */ + if (dmi_fill(is_laptop) != 0) return; - switch (is_laptop) { + switch (*is_laptop) { case 1: msg_pdbg("Laptop detected via DMI.\n"); break; diff --git a/doc/about_flashrom/code_of_conduct.rst b/doc/about_flashrom/code_of_conduct.rst new file mode 100644 index 000000000..296709548 --- /dev/null +++ b/doc/about_flashrom/code_of_conduct.rst @@ -0,0 +1,138 @@ +=============== +Code of Conduct +=============== + +This code of conduct outlines our rules and expectations for everybody +participating in the flashrom community. + +flashrom community etiquette +============================ + +We have a friendly and productive atmosphere on our mailing lists, +development / code review tools, real time chat rooms and when we meet in +person. Our principles evolve around the following: + +* It's not the user's fault if something goes wrong. +* Attempt collaboration before conflict. +* People who intentionally insult others (users, developers, corporations, + other projects, or the flashrom project itself) will be dealt with. See + policy below. +* We are dealing with hardware with lots of undocumented pitfalls. It is quite + possible that you did everything right, but flashrom still won't work for you. + +Refrain from insulting anyone or the group they belong to. Remember that +people might be sensitive to other things than you are. + +Most of our community members are not native English speakers, thus +misunderstandings can (and do) happen. Assume that others are friendly +and may have picked less-than-stellar wording by accident as long as +you possibly can. + +Reporting Issues +================ + +If you have a grievance due to conduct in this community, we're sorry +that you have had a bad experience, and we want to hear about it so +we can resolve the situation. + +Please contact members of our arbitration team (listed below) promptly +and directly, in person (if available) or by email: They will listen +to you and react in a timely fashion. + +If you feel uncomfortable, please don't wait it out, ask for help, +so we can work on setting things right. + +For transparency there is no alias or private mailing list address for +you to reach out to, since we want to make sure that you know who will +and who won't read your message. + +However since people might be on travel or otherwise be unavailable +at times, please reach out to multiple persons at once, especially +when using email. + +The team will treat your messages confidential as far as the law permits. +For the purpose of knowing what law applies, the list provides the usual +country of residence of each team member. + +Unacceptable Behavior +===================== + +Unacceptable behaviors include: intimidating, harassing, abusive, +discriminatory, derogatory or demeaning speech or actions by any +participant in our community online, at all related events and in +one-on-one communications carried out in the context of community +business. Community event venues may be shared with members of the public; +please be respectful to all patrons of these locations. + +Examples of behaviors we do not accept in our community: + +* harmful or prejudicial verbal or written comments related to gender, + sexual orientation, race, religion, disability; +* inappropriate physical contact, and unwelcome sexual advances; +* deliberate intimidation, stalking or following; +* harassing photography or recording; +* sustained disruption of talks or other events. + +Using this code of conduct aggressively against other people in the +community might also be harassment. Be considerate when enforcing the code +of conduct and always try to listen to both sides before passing judgment. + +Consequences of Unacceptable Behavior +===================================== + +Unacceptable behavior from any community member, including sponsors and +those with decision-making authority, will not be tolerated. + +Anyone asked to stop unacceptable behavior is expected to comply +immediately. + +If a community member engages in unacceptable behavior, the community +organizers may take any action they deem appropriate, up to and including +a temporary ban or permanent expulsion from the community without warning +(and without refund in the case of a paid event). + +Community organizers can be members of the arbitration team, or organizers +of events and online communities. + +Addressing Grievances +===================== + +If you feel you have been falsely or unfairly accused of violating this +Code of Conduct, you should notify the arbitration team with a concise +description of your grievance. + +Legal action +============ + +Threatening or starting legal action against the project, sibling +projects hosted on coreboot.org infrastructure, project or infrastructure +maintainers leads to an immediate ban from coreboot.org and related +systems. + +The ban can be reconsidered, but it's the default action because the +people who pour lots of time and money into the projects aren't interested +in seeing their resources used against them. + +Scope +========== + +We expect all community participants (contributors, paid or otherwise; +sponsors; and other guests) to abide by this Code of Conduct in all +community venues, online and in-person, as well as in all one-on-one +communications pertaining to community business. + +Contact info +============ + +Our arbitration team consists of the following people + +* Anastasia Klimchuk (Australia) +* Stefan Reinauer (USA) + +License and attribution +======================= + +This Code of Conduct is distributed under +a `Creative Commons Attribution-ShareAlike +license `_. It is based +on the `Citizen Code of Conduct `_ diff --git a/doc/about_flashrom/index.rst b/doc/about_flashrom/index.rst new file mode 100644 index 000000000..49c984983 --- /dev/null +++ b/doc/about_flashrom/index.rst @@ -0,0 +1,8 @@ +About flashrom +============== + +.. toctree:: + :maxdepth: 1 + + team + code_of_conduct diff --git a/doc/about_flashrom/team.rst b/doc/about_flashrom/team.rst new file mode 100644 index 000000000..215d9309f --- /dev/null +++ b/doc/about_flashrom/team.rst @@ -0,0 +1,64 @@ +========= +Team +========= + +flashrom development process is happening in Gerrit. +All contributors and users who have a Gerrit account can send patches, +add comments to patches and vote +1..-1 on patches. + +All contributors and users are expected to follow Development guidelines and +:doc:`code_of_conduct`. + +There are two special groups in Gerrit. + +"flashrom reviewers" group +========================== + +Members of the group (see `flashrom reviewers `_) +can do full approval of patches (i.e. vote +2). + +In general, members of the group have some area of responsibility in the +`MAINTAINERS `_ file, +and are automatically added as reviewers to patches when the patch touches this area. + +The responsibilities are the following. + +* React to patches when added as a reviewer. + +* Try to respond to technical questions on the mailing list if the topic is something you know about + and can provide a useful response. + +* Know development guidelines and check the patches you are reviewing align with the guidelines. + +"flashrom developers" group +=========================== + +Members of the group (see `flashrom developers `_) +can merge patches. +The responsibilities for the members of the group are described in more details below. + +There is no expectation on how much time you spend on your duties, some non-zero amount of time, +whatever capacity you have. But in general, you stay around on flashrom. + +If you disappear for some time (life happens), especially for a longer time, like several months, +especially without a warning: you implicitly agree that the others will handle the duties and make decisions if needed +(potentially without waiting for you to come back, if the decision is needed quickly). + +* Merge all contributors's patches (when they are ready), not just your own. + +* Be at least vaguely aware what development efforts are ongoing, this helps to make decisions + in what order the patches should be merged, and where could be merge conflicts. + +* Know development guidelines, and educate other contributors if needed (e.g. give links). + +* React to patches when added as a reviewer. + +* Try to respond to technical questions on the mailing list if the topic is something you know about + and can provide a useful response. + +* From time to time show up in real-time channel(s) and/or dev meetings. + +* Follow the :doc:`code_of_conduct`, be a good example for others. + +* Bonus point: if you work in a [software] company, educate and help contributors from your company + with upstream culture and dev guidelines. diff --git a/doc/classic_cli_manpage.rst b/doc/classic_cli_manpage.rst new file mode 100644 index 000000000..cdb70601c --- /dev/null +++ b/doc/classic_cli_manpage.rst @@ -0,0 +1,1436 @@ +Manual page +=========== + + +NAME +---- + +**flashrom** - detect, read, write, verify and erase flash chips + + +SYNOPSIS +-------- + +| **flashrom** [-h|-R|-L| +| -p [:] [-c ] +| (--flash-name|--flash-size| +| [-E|-x|-r |-w |-v ] +| [(-l |--ifd|--fmap|--fmap-file ) +| [-i [:]]] +| [--wp-status] [--wp-list] [--wp-enable|--wp-disable] +| [--wp-range ,|--wp-region ] +| [-n] [-N] [-f])] +| [-V[V[V]]] [-o ] [--progress] + + +DESCRIPTION +----------- + +**flashrom** is a utility for detecting, reading, writing, verifying and erasing flash chips. +It's often used to flash BIOS/EFI/coreboot/firmware images in-system using a supported mainboard. +However, it also supports various external PCI/USB/parallel-port/serial-port based devices which can program flash +chips, including some network cards (NICs), SATA/IDE controller cards, graphics cards, the Bus Pirate device, +various FTDI FT2232/FT4232H/FT4233H/FT232H based USB devices, and more. + +It supports a wide range of DIP32, PLCC32, DIP8, SO8/SOIC8, TSOP32, TSOP40, TSOP48, and BGA chips, +which use various protocols such as LPC, FWH, parallel flash, or SPI. + + +OPTIONS +------- + +You can specify one of ``-h``, ``-R``, ``-L``, ``-E``, ``-r``, ``-w``, ``-v`` or no operation. +If no operation is specified, **flashrom** will only probe for flash chips. It is recommended that if you try **flashrom** the +first time on a system, you run it in probe-only mode and check the output. +Also you are advised to make a backup of your current ROM contents with ``-r`` before you try to write a new image. +All operations involving any chip access (probe/read/write/...) require the ``-p/--programmer`` option to be used (please see below). + + +**-r, --read ** + Read flash ROM contents and save them into the given ****. + If the file already exists, it will be overwritten. + + +**-w, --write (|-)** + Write **** into flash ROM. If **-** is provided instead, contents will be read from stdin. + This will first automatically erase the chip, then write to it. + + In the process the chip is also read several times. First an in-memory backup is made for disaster recovery and to be + able to skip regions that are already equal to the image file. + This copy is updated along with the write operation. In case of erase errors it is even re-read completely. + After writing has finished and if verification is enabled, the whole flash chip is read out and compared with the input image. + + +**-n, --noverify** + Skip the automatic verification of flash ROM contents after writing. Using this option is **not** recommended, + you should only use it if you know what you are doing and if you feel that the time for verification takes too long. + + Typical usage is:: + + flashrom -p prog -n -w + + This option is only useful in combination with ``--write``. + + +**-N, --noverify-all** + Skip not included regions during automatic verification after writing (cf. ``-l`` and ``-i``). + You should only use this option if you are sure that communication with the flash chip is reliable + (e.g. when using the **internal** programmer). + Even if **flashrom** is instructed not to touch parts of the flash chip, their contents could be damaged + (e.g. due to misunderstood erase commands). + + This option is required to flash an Intel system with locked ME flash region using the **internal** programmer. + It may be enabled by default in this case in the future. + + +**-v, --verify (|-)** + Verify the flash ROM contents against the given ****. + If **-** is provided instead, contents will be written to the stdout. + + +**-E, --erase** + Erase the flash ROM chip. + + +**-x, --extract** + Extract every region defined on the layout from flash ROM chip to a file with the same name as the extracted region + (replacing spaces with underscores). + + +**-V, --verbose** + More verbose output. This option can be supplied multiple times (max. 3 times, i.e. ``-VVV`` ) for even more debug output. + + +**-c, --chip ** + Probe only for the specified flash ROM chip. This option takes the chip name as printed by ``flashrom -L`` without the + vendor name as parameter. Please note that the chip name is case sensitive. + + +**-f, --force** + Force one or more of the following actions: + + * Force chip read and pretend the chip is there. + * Force chip access even if the chip is bigger than the maximum supported size for the flash bus. + * Force erase even if erase is known bad. + * Force write even if write is known bad. + + +**-l, --layout ** + Read ROM layout from ****. + + **flashrom** supports ROM layouts. This allows you to flash certain parts of the flash chip only. + A ROM layout file contains multiple lines with the following syntax:: + + startaddr:endaddr imagename + + ``startaddr`` and ``endaddr`` are hexadecimal addresses within the ROM file and do not refer to any physical address. + Please note that using a 0x prefix for those hexadecimal numbers is not necessary, but you can't specify decimal/octal numbers. + ``imagename`` is an arbitrary name for the region/image from ``startaddr`` to ``endaddr`` (both addresses included). + + Example:: + + 00000000:00008fff gfxrom + 00009000:0003ffff normal + 00040000:0007ffff fallback + + If you only want to update the image named **normal** in a ROM based on the layout above, run:: + + flashrom -p prog --layout rom.layout --image normal -w some.rom + + To update only the images named **normal** and **fallback**, run:: + + flashrom -p prog -l rom.layout -i normal -i fallback -w some.rom + + Overlapping sections are not supported. + + +**--fmap** + Read layout from fmap in flash chip. + + **flashrom** supports the fmap binary format which is commonly used by coreboot for partitioning a flash chip. + The on-chip fmap will be read and used to generate the layout. + + If you only want to update the **COREBOOT** region defined in the fmap, run:: + + flashrom -p prog --fmap --image COREBOOT -w some.rom + + +**--fmap-file ** + Read layout from a **** containing binary fmap (e.g. coreboot roms). + + **flashrom** supports the fmap binary format which is commonly used by coreboot for partitioning a flash chip. + The fmap in the specified file will be read and used to generate the layout. + + If you only want to update the **COREBOOT** region defined in the binary fmap file, run:: + + flashrom -p prog --fmap-file some.rom --image COREBOOT -w some.rom + + +**--ifd** + Read ROM layout from Intel Firmware Descriptor. + + **flashrom** supports ROM layouts given by an Intel Firmware Descriptor (IFD). + The on-chip descriptor will be read and used to generate the layout. If you need to change the layout, + you have to update the IFD only first. + + The following ROM images may be present in an IFD: + + | ``fd`` - the IFD itself + | ``bios`` - the host firmware aka. BIOS + | ``me`` - Intel Management Engine firmware + | ``gbe`` - gigabit ethernet firmware + | ``pd`` - platform specific data + + +**-i, --include [:]** + Read or write only **** to or from ROM. + The **-i** option may be used multiple times if the user wishes to read or write multiple regions using a single command. + + The user may optionally specify a corresponding **** for any region they wish to read or write. + A read operation will read the corresponding regions from ROM and write individual files for each one. + A write option will read file(s) and write to the corresponding region(s) in ROM. + + For write operations, files specified using ``-i`` take precedence over content from the argument to ``-w``. + + Examples: + To read regions named **foo** and **bar** in layout file **** into region-sized files **foo.bin** and **bar.bin**, run:: + + flashrom -p prog -l -i foo:foo.bin -i bar:bar.bin -r rom.bin + + To write files **foo.bin** and **bar.bin** into regions named **foo** and **bar** in layout file **** to the ROM, run:: + + flashrom -p prog -l -i foo:foo.bin -i bar:bar.bin -w rom.bin + + +**--wp-status** + Prints the flash's current status register protection mode and write protection range. + + +**--wp-list** + Prints a list of all protection ranges that the flash supports. + + +**--wp-enable** + Enables hardware status register protection (SRP) if the flash supports it. + Once SRP is enabled, operations that change the flash's status registers (including ``--wp-disable`` and ``--wp-range``) + can only be performed if the flash's #WP pin is at an inactive logic level. + + +**--wp-disable** + Disables status register protection if the flash allows it. + + +**--wp-range ,** + Configures the flash to protect a range of addresses from to ( + - 1), bounds inclusive. + The range must be supported by the flash, see ``--wp-list``. + + +**--wp-region ** + Same as ``--wp-range`` but protects the range occupied by an image region. + This option requires a image layout to be specified, see ``--layout``. + The region must be supported by the flash, see ``--wp-list``. + + +**--flash-name** + Prints out the detected flash chip's name. + + +**--flash-size** + Prints out the detected flash chip's size. + + +**--flash-contents ** + The file contents of **** will be used to decide which parts of the flash need to be written. + Providing this saves an initial read of the full flash chip. + Be careful, if the provided data doesn't actually match the flash contents, results are undefined. + + +**-L, --list-supported** + List the flash chips, chipsets, mainboards, and external programmers (including PCI, USB, parallel port, and serial port based devices) + supported by **flashrom**. + + There are many unlisted boards which will work out of the box, without special support in **flashrom**. + Please let us know if you can verify that other boards work or do not work out of the box. + + **IMPORTANT**: + For verification you have to test an ERASE and/or WRITE operation, so make sure you only do that if you have proper means to recover from failure! + + +**-p, --programmer [:parameter[,parameter[,parameter]]]** + Specify the programmer device. This is mandatory for all operations involving any chip access (probe/read/write/...). + Currently supported are: + + * ``internal`` (for in-system flashing in the mainboard) + * ``dummy`` (virtual programmer for testing **flashrom**) + * ``nic3com`` (for flash ROMs on 3COM network cards) + * ``nicrealtek`` (for flash ROMs on Realtek and SMC 1211 network cards) + * ``nicnatsemi`` (for flash ROMs on National Semiconductor DP838* network cards) + * ``nicintel`` (for parallel flash ROMs on Intel 10/100Mbit network cards) + * ``gfxnvidia`` (for flash ROMs on NVIDIA graphics cards) + * ``drkaiser`` (for flash ROMs on Dr. Kaiser PC-Waechter PCI cards) + * ``satasii`` (for flash ROMs on Silicon Image SATA/IDE controllers) + * ``satamv`` (for flash ROMs on Marvell SATA controllers) + * ``atahpt`` (for flash ROMs on Highpoint ATA/RAID controllers) + * ``atavia`` (for flash ROMs on VIA VT6421A SATA controllers) + * ``atapromise`` (for flash ROMs on Promise PDC2026x ATA/RAID controllers) + * ``it8212`` (for flash ROMs on ITE IT8212F ATA/RAID controller) + * ``ft2232_spi`` (for SPI flash ROMs attached to an FT2232/FT4232H/FT232H family based USB SPI programmer) + * ``serprog`` (for flash ROMs attached to a programmer speaking serprog, including some Arduino-based devices) + * ``buspirate_spi`` (for SPI flash ROMs attached to a Bus Pirate) + * ``dediprog`` (for SPI flash ROMs attached to a Dediprog SF100) + * ``rayer_spi`` (for SPI flash ROMs attached to a parallel port by one of various cable types) + * ``raiden_debug_spi`` (For Chrome EC based debug tools - SuzyQable, Servo V4, C2D2 & uServo) + * ``pony_spi`` (for SPI flash ROMs attached to a SI-Prog serial port bitbanging adapter) + * ``nicintel_spi`` (for SPI flash ROMs on Intel Gigabit network cards) + * ``ogp_spi`` (for SPI flash ROMs on Open Graphics Project graphics card) + * ``linux_mtd`` (for SPI flash ROMs accessible via /dev/mtdX on Linux) + * ``linux_spi`` (for SPI flash ROMs accessible via /dev/spidevX.Y on Linux) + * ``usbblaster_spi`` (for SPI flash ROMs attached to an Altera USB-Blaster compatible cable) + * ``nicintel_eeprom`` (for SPI EEPROMs on Intel Gigabit network cards) + * ``mstarddc_spi`` (for SPI flash ROMs accessible through DDC in MSTAR-equipped displays) + * ``pickit2_spi`` (for SPI flash ROMs accessible via Microchip PICkit2) + * ``ch341a_spi`` (for SPI flash ROMs attached to WCH CH341A) + * ``ch347_api`` (for SPI flash ROMs attached to WHC CH347) + * ``digilent_spi`` (for SPI flash ROMs attached to iCEblink40 development boards) + * ``jlink_spi`` (for SPI flash ROMs attached to SEGGER J-Link and compatible devices) + * ``ni845x_spi`` (for SPI flash ROMs attached to National Instruments USB-8451 or USB-8452) + * ``stlinkv3_spi`` (for SPI flash ROMs attached to STMicroelectronics STLINK V3 devices) + * ``realtek_mst_i2c_spi`` (for SPI flash ROMs attached to Realtek DisplayPort hubs accessible through I2C) + * ``parade_lspcon`` (for SPI flash ROMs attached to Parade Technologies LSPCONs (PS175)) + * ``mediatek_i2c_spi`` (for SPI flash ROMs attached to some Mediatek display devices accessible over I2C) + * ``dirtyjtag_spi`` (for SPI flash ROMs attached to DirtyJTAG-compatible devices) + * ``asm106x`` (for SPI flash ROMs attached to asm106x PCI SATA controllers) + + Some programmers have optional or mandatory parameters which are described in detail in the + **PROGRAMMER-SPECIFIC INFORMATION** section. Support for some programmers can be disabled at compile time. + ``flashrom -h`` lists all supported programmers. + + +**-h, --help** + Show a help text and exit. + + +**-o, --output ** + Save the full debug log to ****. + If the file already exists, it will be overwritten. This is the recommended way to gather logs from **flashrom** + because they will be verbose even if the on-screen messages are not verbose and don't require output redirection. + + +**--progress** + [Experimental feature] Show progress percentage of operations on the standard output. + + +**-R, --version** + Show version information and exit. + +.. _programmer-specific information: + +PROGRAMMER-SPECIFIC INFORMATION +------------------------------- +Some programmer drivers accept further parameters to set programmer-specific parameters. These parameters are separated +from the programmer name by a colon. While some programmers take arguments atfixed positions, other programmers use a +key/value interface in which the key and value is separated by an equal sign and different pairs are separated by a +comma or a colon. + + +internal programmer +^^^^^^^^^^^^^^^^^^^ + + +**Board Enables** + Some mainboards require to run mainboard specific code to enable flash erase and write support + (and probe support on old systems with parallel flash). + The mainboard brand and model (if it requires specific code) is usually autodetected using one of the following mechanisms: + If your system is running coreboot, the mainboard type is determined from the coreboot table. + Otherwise, the mainboard is detected by examining the onboard PCI devices and possibly DMI info. + If PCI and DMI do not contain information to uniquely identify the mainboard (which is the exception), + or if you want to override the detected mainboard model, you can specify the mainboard using the:: + + flashrom -p internal:mainboard=: + + syntax. + + See the **Known boards** or **Known laptops** section in the output of ``flashrom -L`` for a list of boards + which require the specification of the board name, if no coreboot table is found. + + Some of these board-specific flash enabling functions (called **board enables** ) in **flashrom** have not yet been tested. + If your mainboard is detected needing an untested board enable function, a warning message is printed and the board enableis not executed, + because a wrong board enable function might cause the system to behave erratically, as board enable functions touch the + low-level internals of a mainboard. + Not executing a board enable function (if one is needed) might cause detection or erasing failure. + If your board protects only part of the flash (commonly the top end, called boot block), + **flashrom** might encounter an error only after erasing the unprotected part, so running without the board-enable function + might be dangerous for erase and write (which includes erase). + + The suggested procedure for a mainboard with untested board specific code is to first try to probe the ROM + (just invoke **flashrom** and check that it detects your flash chip type) without running the board enable code + (i.e. without any parameters). If it finds your chip, fine. Otherwise, retry probing your chip with the board-enable code running, using:: + + flashrom -p internal:boardenable=force + + If your chip is still not detected, the board enable code seems to be broken or the flash chip unsupported. + Otherwise, make a backup of your current ROM contents (using ``-r``) and store it to a medium outside of your computer, + like a USB drive or a network share. If you needed to run the board enable code already for probing, use it for reading too. + If reading succeeds and the contents of the read file look legit you can try to write the new image. + You should enable the board enable code in any case now, as it has been written because it is known that writing/erasing + without the board enable is going to fail. In any case (success or failure), please report to the **flashrom** mailing list, see below. + +**Coreboot** + On systems running coreboot, **flashrom** checks whether the desired image matches your mainboard. + This needs some special board ID to be present in the image. + If **flashrom** detects that the image you want to write and the current board do not match, + it will refuse to write the image unless you specify:: + + flashrom -p internal:boardmismatch=force + + +**ITE IT87 Super I/O** + If your mainboard is manufactured by GIGABYTE and supports DualBIOS it is very likely that it uses an + ITE IT87 series Super I/O to switch between the two flash chips. + Only one of them can be accessed at a time and you can manually select which one to use with the:: + + flashrom -p internal:dualbiosindex=chip + + syntax where ``chip`` is the index of the chip to use (0 = main, 1 = backup). + You can check which one is currently selected by leaving out the ``chip`` parameter. + + If your mainboard uses an ITE IT87 series Super I/O for LPC<->SPI flash bus translation, **flashrom** should autodetect that configuration. + If you want to set the I/O base port of the IT87 series SPI controller manually instead of using the value provided by the BIOS, + use the:: + + flashrom -p internal:it87spiport=portnum + + syntax where ``portnum`` is the I/O port number (must be a multiple of 8). + In the unlikely case **flashrom** doesn't detect an active IT87 LPC<->SPI bridge, please send a bug report so we can diagnose the problem. + + +**AMD chipsets** + Beginning with the SB700 chipset there is an integrated microcontroller (IMC) based on the 8051 embedded in every AMD southbridge. + Its firmware resides in the same flash chip as the host's which makes writing to the flash risky if the IMC is active. + Flashrom tries to temporarily disable the IMC but even then changing the contents of the flash can have unwanted effects: + when the IMC continues (at the latest after a reboot) it will continue executing code from the flash. + If the code was removed or changed in an unfortunate way it is unpredictable what the IMC will do. + Therefore, if **flashrom** detects an active IMC it will disable write support unless the user forces it with the:: + + flashrom -p internal:amd_imc_force=yes + + syntax. The user is responsible for supplying a suitable image or leaving out the IMC region with the help of a layout file. + This limitation might be removed in the future when we understand the details better and have received enough feedback from users. + Please report the outcome if you had to use this option to write a chip. + + An optional ``spispeed`` parameter specifies the frequency of the SPI bus where applicable + (i.e.SB600 or later with an SPI flash chip directly attached to the chipset). + Syntax is:: + + flashrom -p internal:spispeed=frequency + + where ``frequency`` can be ``'16.5 MHz'``, ``'22 MHz'``, ``'33 MHz'``, ``'66 MHz'``, ``'100 MHZ'``, or ``'800 kHz'``. + Support of individual frequencies depends on the generation of the chipset: + + * SB6xx, SB7xx, SP5xxx: from 16.5 MHz up to and including 33 MHz. + The default is to use 16.5 MHz and disable Fast Reads. + * SB8xx, SB9xx, Hudson: from 16.5 MHz up to and including 66 MHz. + The default is to use 16.5 MHz and disable Fast Reads. + * Yangtze (with SPI 100 engine as found in Kabini and Tamesh): all of them. + The default is to use the frequency that is currently configured. + + An optional ``spireadmode`` parameter specifies the read mode of the SPI bus where applicable (Bolton or later). + Syntax is:: + + flashrom -p internal:spireadmode=mode + + where ``mode`` can be ``'Normal (up to 33 MHz)'``, ``'Normal (up to 66 MHz)'``, ``'Dual IO (1-1-2)'``, ``'Quad IO (1-1-4)'``, + ``'Dual IO (1-2-2)'``, ``'Quad IO (1-4-4)'``, or ``'Fast Read'``. + + The default is to use the read mode that is currently configured. + + +**Intel chipsets** + If you have an Intel chipset with an ICH8 or later southbridge with SPI flash attached, and if a valid descriptor was written + to it (e.g. by the vendor), the chipset provides an alternative way to access the flash chip(s) named **Hardware Sequencing**. + It is much simpler than the normal access method (called **Software Sequencing**), but does not allow the software to + choose the SPI commands to be sent. You can use the:: + + flashrom -p internal:ich_spi_mode=value + + syntax where ``value`` can be ``auto``, ``swseq`` or ``hwseq``. By default (or when setting ``ich_spi_mode=auto``) the + module tries to use swseq and only activates hwseq if need be (e.g. if important opcodes are inaccessible due to lockdown; + or if more than one flash chip is attached). The other options (swseq, hwseq) select the respective mode (if possible). + + ICH8 and later southbridges may also have locked address ranges of different kinds if a valid descriptor was written to it. + The flash address space is then partitioned in multiple so called "Flash Regions" containing the host firmware, + the ME firmware and so on respectively. The flash descriptor can also specify up to 5 so called **Protected Regions**, + which are freely chosen address ranges independent from the aforementioned **Flash Regions**. + All of them can be write and/or read protected individually. + + If you have an Intel chipset with an ICH2 or later southbridge and if you want to set specific IDSEL values for a + non-default flash chip or an embedded controller (EC), you can use the:: + + flashrom -p internal:fwh_idsel=value + + syntax where ``value`` is the 48-bit hexadecimal raw value to be written in the IDSEL registers of the Intel southbridge. + The upper 32 bits use one hex digit each per 512 kB range between 0xffc00000 and 0xffffffff, and the lower 16 bits + use one hex digit each per 1024 kB range between 0xff400000 and 0xff7fffff. + The rightmost hex digit corresponds with the lowest address range. All address ranges have a corresponding sister range + 4 MB below with identical IDSEL settings. The default value for ICH7 is given in the example below. + + Example:: + + flashrom -p internal:fwh_idsel=0x001122334567 + + +**Laptops** + Using **flashrom** on older laptops that don't boot from the SPI bus is dangerous and may easily make your hardware unusable + (see also the **BUGS** section). The embedded controller (EC) in some machines may interact badly with flashing. + More information is `in the wiki `_. + Problems occur when the flash chip is shared between BIOS and EC firmware, and the latter does not expect **flashrom** + to access the chip. While **flashrom** tries to change the contents of that memory the EC might need to fetch new + instructions or data from it and could stop working correctly. Probing for and reading from the chip may also irritate + your EC and cause fan failure, backlight failure, sudden poweroff, and other nasty effects. **flashrom** will attempt to + detect if it is running on such a laptop and limit probing to SPI buses. If you want to probe the LPC bus anyway at your own risk, use:: + + flashrom -p internal:laptop=force_I_want_a_brick + + We will not help you if you force flashing on a laptop because this is a really dumb idea. + + You have been warned. + + Currently we rely on the chassis type encoded in the DMI/SMBIOS data to detect laptops. Some vendors did not implement + those bits correctly or set them to generic and/or dummy values. **flashrom** will then issue a warning and restrict buses like above. + In this case you can use:: + + flashrom -p internal:laptop=this_is_not_a_laptop + + to tell **flashrom** (at your own risk) that it is not running on a laptop. + + +dummy programmer +^^^^^^^^^^^^^^^^ + +The dummy programmer operates on a buffer in memory only. It provides a safe and fast way to test various aspects of +**flashrom** and is mainly used in development and while debugging. +It is able to emulate some chips to a certain degree (basic identify/read/erase/write operations work). + +An optional parameter specifies the bus types it should support. For that you have to use the:: + + flashrom -p dummy:bus=[type[+type[+type]]] + +syntax where ``type`` can be ``parallel``, ``lpc``, ``fwh``, ``spi`` in any order. If you specify bus without type, +all buses will be disabled. If you do not specify bus, all buses will be enabled. + +Example:: + + flashrom -p dummy:bus=lpc+fwh + +The dummy programmer supports flash chip emulation for automated self-tests without hardware access. +If you want to emulate a flash chip, use the:: + + flashrom -p dummy:emulate=chip + +syntax where ``chip`` is one of the following chips (please specify only the chip name, not the vendor): + +* ST ``M25P10.RES`` SPI flash chip (128 kB, RES, page write) +* SST ``SST25VF040.REMS`` SPI flash chip (512 kB, REMS, byte write) +* SST ``SST25VF032B`` SPI flash chip (4096 kB, RDID, AAI write) +* Macronix ``MX25L6436`` SPI flash chip (8192 kB, RDID, SFDP) +* Winbond ``W25Q128FV`` SPI flash chip (16384 kB, RDID) +* Spansion ``S25FL128L`` SPI flash chip (16384 kB, RDID) +* Dummy vendor ``VARIABLE_SIZE`` SPI flash chip (configurable size, page write) + +Example:: + + flashrom -p dummy:emulate=SST25VF040.REMS + +To use ``VARIABLE_SIZE`` chip, ``size`` must be specified to configure the size of the flash chip as a power of two. + +Example:: + + flashrom -p dummy:emulate=VARIABLE_SIZE,size=16777216,image=dummy.bin + + +**Persistent images** + If you use flash chip emulation, flash image persistence is available as well by using the:: + + flashrom -p dummy:emulate=chip,image=image.rom + + syntax where ``image.rom`` is the file where the simulated chip contents are read on **flashrom** startup and where the + chip contents on **flashrom** shutdown are written to. + + Example:: + + flashrom -p dummy:emulate=M25P10.RES,image=dummy.bin + + +**SPI write chunk size** + If you use SPI flash chip emulation for a chip which supports SPI page write with the default opcode, + you can set the maximum allowed write chunk size with the:: + + flashrom -p dummy:emulate=chip,spi_write_256_chunksize=size + + syntax where ``size`` is the number of bytes (min.\& 1, max.\& 256). + Example:: + + flashrom -p dummy:emulate=M25P10.RES,spi_write_256_chunksize=5 + + +**SPI blacklist** + To simulate a programmer which refuses to send certain SPI commands to the flash chip, you can specify a blacklist of + SPI commands with the:: + + flashrom -p dummy:spi_blacklist=commandlist + + syntax where ``ommandlist`` is a list of two-digit hexadecimal representations of SPI commands. + If commandlist is e.g. 0302, **flashrom** will behave as if the SPI controller refuses to run command 0x03 (READ) and command 0x02 (WRITE). + commandlist may be up to 512 characters (256 commands) long. + Implementation note: **flashrom** will detect an error during command execution. + + +**SPI ignorelist** + To simulate a flash chip which ignores (doesn't support) certain SPI commands, you can specify an ignorelist of SPI commands with the:: + + flashrom -p dummy:spi_ignorelist=commandlist + + syntax where ``commandlist`` is a list of two-digit hexadecimal representations of SPI commands. + If commandlist is e.g. 0302, the emulated flash chip will ignore command 0x03 (READ) and command 0x02 (WRITE). + ``commandlist`` may be up to 512 characters (256 commands) long. + Implementation note: **flashrom** won't detect an error during command execution. + + +**SPI status register** + You can specify the initial content of the chip's status register with the:: + + flashrom -p dummy:spi_status=content" + + syntax where ``content`` is a hexadecimal value of up to 24 bits. For example, ``0x332211`` assigns 0x11 to SR1, + 0x22 to SR2 and 0x33 to SR3. Shorter value is padded to 24 bits with zeroes on the left. + See datasheet for chosen chip for details about the registers content. + + +**Write protection** + Chips with emulated WP: **W25Q128FV**, **S25FL128L**. + + You can simulate state of hardware protection pin (WP) with the:: + + flashrom -p dummy:hwwp=state + + syntax where ``state`` is ``yes`` or ``no`` (default value). ``yes`` means active state of the pin implies that chip is + write-protected (on real hardware the pin is usually negated, but not here). + +**Frequency** + Frequency can be specified in ``Hz`` (default), ``KHz``, or ``MHz`` (not case sensitive). + If ``freq`` parameter is passed in from command line, commands will delay for certain time before returning, + so that to emulate the requested frequency. + + Valid range is [1Hz, 8000Mhz] and there is no delay by default. + + The delay of an SPI command is proportional to the number of bits send over SPI bus in both directions + and is calculated based on the assumption that we transfer at 1 bit/Hz:: + + flashrom -p dummy:emulate=W25Q128FV,freq=64mhz + + +nic3com, nicrealtek, nicnatsemi, nicintel, nicintel_eeprom, nicintel_spi, gfxnvidia, ogp_spi, drkaiser, satasii, satamv, atahpt, atavia, atapromise, it8212 programmers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These programmers have an option to specify the PCI address of the card your want to use, which must be specified if +more than one card supported by the selected programmer is installed in your system. The syntax is:: + + flashrom -p xxxx:pci=bb:dd.f + +where ``xxxx`` is the name of the programmer, ``bb`` is the PCI bus number, ``dd`` is the PCI device number, and ``b`` +is the PCI function number of the desired device. Example:: + + flashrom -p nic3com:pci=05:04.0 + +Some of these programmers have more info below. + +atavia programmer +^^^^^^^^^^^^^^^^^ + +Due to the mysterious address handling of the VIA VT6421A controller the user can specify an offset with the:: + + flashrom -p atavia:offset=addr + +syntax where ``addr`` will be interpreted as usual (leading 0x (0) for hexadecimal (octal) values, or else decimal). +For more information please see `its wiki page `_. + + +atapromise programmer +^^^^^^^^^^^^^^^^^^^^^ + +This programmer is currently limited to 32 kB, regardless of the actual size of the flash chip. This stems from the +fact that, on the tested device (a Promise Ultra100), not all of the chip's address lines were actually connected. +You may use this programmer to flash firmware updates, since these are only 16 kB in size (padding to 32 kB is required). + +nic3com programmer +^^^^^^^^^^^^^^^^^^ + +flashrom supports some 3Com network cards to reflash the (parallel) flash attached to these cards, +but it is also possible to use these cards to reflash other chips which fit in there electrically. +Please note that the small number of address lines connected to the chip may make accessing large chips impossible. +The maximum supported chip size is 128KB. + +nicintel_spi programmer +^^^^^^^^^^^^^^^^^^^^^^^ + +Programmer for SPI flash ROMs on Intel Gigabit network cards. Tested on 32-bit hardware/PCI only. + +nicintel_eeprom programmer +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This is the first programmer module in **flashrom** that does not provide access to NOR flash chips but EEPROMs mounted on +gigabit Ethernet cards based on Intel's 82580 NIC. Because EEPROMs normally do not announce their size nor allow +themselves to be identified, the controller relies on correct size values written to predefined addresses within the chip. +**Flashrom** follows this scheme but assumes the minimum size of 16 kB (128 kb) if an unprogrammed EEPROM/card is detected. +Intel specifies following EEPROMs to be compatible: +Atmel AT25128, AT25256, Micron (ST) M95128, M95256 and OnSemi (Catalyst) CAT25CS128. + +gfxnvidia programmer +^^^^^^^^^^^^^^^^^^^^ + +Flashrom supports some Nvidia graphic cards to reflash the (parallel) flash attached to these cards, +but it is also possible to use these cards to reflash other chips which fit in there electrically. + +satasii programmer +^^^^^^^^^^^^^^^^^^ + +Flashrom supports some SiI ATA/SATA controllers to reflash the flash attached to these controller cards, +but it is also possible to use these cards to reflash other chips which fit in there electrically. +Please note that the small number of address lines connected to the chip may make accessing large chips impossible. + +ft2232_spi programmer +^^^^^^^^^^^^^^^^^^^^^ + +This module supports various programmers based on FTDI FT2232/FT4232H/FT232H chips including the DLP Design DLP-USB1232H, +openbiosprog-spi, Amontec JTAGkey/JTAGkey-tiny/JTAGkey-2, Dangerous Prototypes Bus Blaster, Olimex ARM-USB-TINY/-H, +Olimex ARM-USB-OCD/-H, OpenMoko Neo1973 Debug board (V2+), TIAO/DIYGADGET USB Multi-Protocol Adapter (TUMPA), TUMPA Lite, +GOEPEL PicoTAP, Google Servo v1/v2, Tin Can Tools Flyswatter/Flyswatter 2 and Kristech KT-LINK. + +An optional parameter specifies the controller type, channel/interface/port it should support. For that you have to use the:: + + flashrom \-p ft2232_spi:type=model,port=interface + +syntax where ``model`` can be ``2232H``, ``4232H``, ``232H``, ``jtagkey``, ``busblaster``, ``openmoko``, ``arm-usb-tiny``, +``arm-usb-tiny-h``, ``arm-usb-ocd``, ``arm-usb-ocd-h``, ``tumpa``, ``tumpalite``, ``picotap``, ``google-servo, +``google-servo-v2``, ``google-servo-v2-legacy`` or ``kt-link``. +``interface`` can be ``A``, ``B``, ``C``, or ``D``. The default model is ``4232H``, the default interface is ``A`` and +GPIO is not used by default. + +If there is more than one ft2232_spi-compatible device connected, you can select which one should be used by specifying +its serial number with the:: + + flashrom -p ft2232_spi:serial=number + +syntax where ``number`` is the serial number of the device (which can be found for example in the output of lsusb -v). + +All models supported by the **ft2232_spi** driver can configure the SPI clock rate by setting a divisor. The expressible +divisors are all **even** numbers between 2 and 2^17 (=131072) resulting in SPI clock frequencies of 6 MHz down to about +92 Hz for 12 MHz inputs (non-H chips) and 30 MHz down to about 458 Hz for 60 MHz inputs ('H' chips). The default divisor +is set to 2, but you can use another one by specifying the optional ``divisor`` parameter with the:: + + flashrom -p ft2232_spi:divisor=div + +syntax. Using the parameter ``csgpiol`` (DEPRECATED - use ``gpiol`` instead) an additional CS# pin can be chosen, +where the value can be a number between 0 and 3, denoting GPIOL0-GPIOL3 correspondingly. Example:: + + flashrom -p ft2232_spi:csgpiol=3 + +The parameter ``gpiolX=[HLC]`` allows use of the GPIOL pins either as generic gpios with a fixed value during flashing +or as additional CS# signal, where ``X`` can be a number between 0 and 3, denoting GPIOL0-GPIOL3 correspondingly. +The parameter may be specified multiple times, one time per GPIOL pin. Valid values are ``H``, ``L`` and ``C``: + +* ``H`` - Set GPIOL output high +* ``L`` - Set GPIOL output low +* ``C`` - Use GPIOL as additional CS# output + +Example:: + + flashrom -p ft2232_spi:gpiol0=H + +**Note** that not all GPIOL pins are freely usable with all programmers as some have special functionality. + + +serprog programmer +^^^^^^^^^^^^^^^^^^ + +This module supports all programmers speaking the serprog protocol. This includes some Arduino-based devices as well as +various programmers by Urja Rannikko, Juhana Helovuo, Stefan Tauner, Chi Zhang and many others. + +A mandatory parameter specifies either a serial device (and baud rate) or an IP/port combination for communicating with +the programmer. The device/baud combination has to start with ``dev=`` and separate the optional baud rate with a colon. +For example:: + + flashrom -p serprog:dev=/dev/ttyS0:115200 + +If no baud rate is given the default values by the operating system/hardware will be used. +For IP connections you have to use the:: + + flashrom -p serprog:ip=ipaddr:port + +syntax. In case the device supports it, you can set the SPI clock frequency with the optional ``spispeed`` parameter. +The frequency is parsed as hertz, unless an ``M``, or ``k`` suffix is given, then megahertz or kilohertz are used respectively. +Example that sets the frequency to 2 MHz:: + + flashrom -p serprog:dev=/dev/device:baud,spispeed=2M + +Optional ``cs`` parameter can be used to switch which chip select number is used. This allows connecting multiple +chips at once and selecting which one to flash by software means (rather than rewiring):: + + flashrom -p serprog:dev=/dev/device:baud,cs=0 + +The particular programmer implementation needs to support this feature, for it to work. If the requested chip +select isn't available, flashrom will fail safely. + +More information about serprog is available in this document: :doc:`/supported_hw/supported_prog/serprog/serprog-protocol`. + + +buspirate_spi programmer +^^^^^^^^^^^^^^^^^^^^^^^^ + +A required ``dev`` parameter specifies the Bus Pirate device node and an optional ``spispeed`` parameter specifies the +frequency of the SPI bus. The parameter delimiter is a comma. Syntax is:: + + flashrom -p buspirate_spi:dev=/dev/device,spispeed=frequency + +where ``frequency`` can be ``30k``, ``125k``, ``250k``, ``1M``, ``2M``, ``2.6M``, ``4M`` or ``8M`` (in Hz). +The default is the maximum frequency of 8 MHz. + +The baud rate for communication between the host and the Bus Pirate can be specified with the optional ``serialspeed`` +parameter. Syntax is:: + + flashrom -p buspirate_spi:serialspeed=baud + +where ``baud`` can be ``115200``, ``230400``, ``250000`` or ``2000000`` (``2M``). +The default is ``2M`` baud for Bus Pirate hardware version 3.0 and greater, and 115200 otherwise. + +An optional pullups parameter specifies the use of the Bus Pirate internal pull-up resistors. This may be needed if you +are working with a flash ROM chip that you have physically removed from the board. Syntax is:: + + flashrom -p buspirate_spi:pullups=state + +where ``state`` can be ``on`` or ``off``. +More information about the Bus Pirate pull-up resistors and their purpose is available +`in a guide by dangerousprototypes `_. + +When working with low-voltage chips, the internal 10k pull-ups of the Bus Pirate might be too high. In such cases, it's necessary to create an external pull-up using lower-value resistors. + +For this, you can use the ``hiz`` parameter. This way, the Bus Pirate will operate as an open drain. Syntax is:: + + flashrom -p buspirate_spi:hiz=state + +where ``state`` can be ``on`` or ``off``. + +The state of the Bus Pirate power supply pins is controllable through an optional ``psus`` parameter. Syntax is:: + + flashrom -p buspirate_spi:psus=state + +where ``state`` can be ``on`` or ``off``. +This allows the bus pirate to power the ROM chip directly. This may also be used to provide the required pullup voltage +(when using the **pullups** option), by connecting the Bus Pirate's Vpu input to the appropriate Vcc pin. + +An optional aux parameter specifies the state of the Bus Pirate auxiliary pin. +This may be used to drive the auxiliary pin high or low before a transfer. +Syntax is:: + + flashrom -p buspirate_spi:aux=state + +where ``state`` can be ``high`` or ``low``. The default ``state`` is ``high``. + + +pickit2_spi programmer +^^^^^^^^^^^^^^^^^^^^^^ + +An optional ``voltage`` parameter specifies the voltage the PICkit2 should use. The default unit is Volt if no unit is specified. +You can use ``mV``, ``millivolt``, ``V`` or ``Volt`` as unit specifier. Syntax is:: + + flashrom \-p pickit2_spi:voltage=value + +where ``value`` can be ``0V``, ``1.8V``, ``2.5V``, ``3.5V`` or the equivalent in mV. + +An optional ``spispeed`` parameter specifies the frequency of the SPI bus. Syntax is:: + + flashrom -p pickit2_spi:spispeed=frequency + +where ``frequency`` can be ``250k``, ``333k``, ``500k`` or ``1M`` (in Hz). The default is a frequency of 1 MHz. + + +dediprog programmer +^^^^^^^^^^^^^^^^^^^ + +An optional ``voltage`` parameter specifies the voltage the Dediprog should use. The default unit is Volt if no unit is specified. +You can use ``mV``, ``milliVolt``, ``V`` or ``Volt`` as unit specifier. Syntax is:: + + flashrom -p dediprog:voltage=value + +where ``value`` can be ``0V``, ``1.8V``, ``2.5V``, ``3.5V`` or the equivalent in mV. + +An optional ``device`` parameter specifies which of multiple connected Dediprog devices should be used. +Please be aware that the order depends on libusb's usb_get_busses() function and that the numbering starts at 0. +Usage example to select the second device:: + + flashrom -p dediprog:device=1 + +An optional ``spispeed`` parameter specifies the frequency of the SPI bus. The firmware on the device needs to be 5.0.0 or newer. +Syntax is:: + + flashrom -p dediprog:spispeed=frequency + +where ``frequency`` can be ``375k``, ``750k``, ``1.5M``, ``2.18M``, ``3M``, ``8M``, ``12M`` or ``24M`` (in Hz). +The default is a frequency of 12 MHz. + +An optional ``target`` parameter specifies which target chip should be used. Syntax is:: + + flashrom -p dediprog:target=value + +where ``value`` can be ``1`` or ``2`` to select target chip 1 or 2 respectively. The default is target chip 1. + + +rayer_spi programmer +^^^^^^^^^^^^^^^^^^^^ + +The default I/O base address used for the parallel port is 0x378 and you can use the optional ``iobase`` parameter to +specify an alternate base I/O address with the:: + + flashrom -p rayer_spi:iobase=baseaddr + +syntax where ``baseaddr`` is base I/O port address of the parallel port, which must be a multiple of four. +Make sure to not forget the "0x" prefix for hexadecimal port addresses. + +The default cable type is the RayeR cable. You can use the optional ``type`` parameter to specify the cable type with the:: + + flashrom -p rayer_spi:type=model + +syntax where ``model`` can be ``rayer`` for the RayeR cable, ``byteblastermv`` for the Altera ByteBlasterMV, +``stk200`` for the Atmel, ``STK200/300``, ``wiggler`` for the Macraigor Wiggler, ``xilinx`` for the Xilinx Parallel Cable III (DLC 5), +or ``spi_tt`` for SPI Tiny Tools-compatible hardware. + +More information about the RayeR hardware is available at `RayeR's website `_. +The Altera ByteBlasterMV datasheet can be obtained from `Altera `_. +For more information about the Macraigor Wiggler see `their company homepage `_. +The schematic of the Xilinx DLC 5 was published in `a Xilinx guide `_. + + +raiden_debug_spi programmer +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some devices such as the GSC knows how it is wired to AP and EC flash chips, and can be told which specific device to talk to using the ``target`` parameter:: + + flashrom -p raiden_debug_spi:target={ap,ec} + +Other devices such as Servo Micro and HyperDebug are generic, and do not know how they are wired, the caller is responsible for first configure the appropriate MUXes or buffers, and then tell the debugger which port to use (Servo Micro has just one SPI port, HyperDebug is the first of this kind to have multiple):: + + flashrom -p raiden_debug_spi:target=N + +where ``N`` is an non-negative integer (default ``0``). + +The default is to use the first available servo. You can use the optional ``serial`` parameter to specify the servo +USB device serial number to use specifically with:: + + flashrom -p raiden_debug_spi:serial=XXX + +The servo device serial number can be found via ``lsusb``. +Raiden will poll the ``ap`` target waiting for the system power to settle on the AP and EC flash devices. + +The optional ``custom_rst=true`` parameter alters the behavior of the reset process:: + + flashrom -p raiden_debug_spi:custom_rst= + +syntax, where: + +``custom_rst=false`` is the implicit default timeout of 3ms + +and ``custom_rst=true`` set ``RAIDEN_DEBUG_SPI_REQ_ENABLE_AP_CUSTOM`` instead of ``RAIDEN_DEBUG_SPI_REQ_ENABLE_AP``. +This custom reset will modify the timeout from 3ms to 10ms and will not set ``EC_RST_L``, meaning neither the EC nor the AP will be reset. With this setting, it's the user's responsibility to manage the reset signal manually or by configuring the GPIO. +Failure to handle the reset signal appropriately will likely result in flashing errors. + +More information about the ChromiumOS servo +hardware is available at `servos website `_. + + +pony_spi programmer +^^^^^^^^^^^^^^^^^^^ + +The serial port (like /dev/ttyS0, /dev/ttyUSB0 on Linux or COM3 on windows) is specified using the mandatory ``dev`` +parameter. The adapter type is selectable between SI-Prog (used for SPI devices with PonyProg 2000) or a custom made +serial bitbanging programmer named "serbang". The optional ``type`` parameter accepts the values ``si_prog`` (default) +or ``serbang``. + +Information about the SI-Prog adapter can be found at `its website `_. + +An example call to **flashrom** is:: + + flashrom -p pony_spi:dev=/dev/ttyS0,type=serbang + +Please note that while USB-to-serial adapters work under certain circumstances, this slows down operation considerably. + + +ogp_spi programmer +^^^^^^^^^^^^^^^^^^ + +The flash ROM chip to access must be specified with the ``rom`` parameter:: + + flashrom -p ogp_spi:rom=name + +Where ``name`` is either ``cprom`` or ``s3`` for the configuration ROM and ``bprom`` or ``bios`` for the BIOS ROM. +If more than one card supported by the **ogp_spi** programmer is installed in your system, you have to specify the PCI +address of the card you want to use with the ``pci=`` parameter as explained in the **nic3com** et al. section above. + + +linux_mtd programmer +^^^^^^^^^^^^^^^^^^^^ + +You may specify the MTD device to use with the:: + + flashrom -p linux_mtd:dev=/dev/mtdX + +syntax where ``/dev/mtdX`` is the Linux device node for your MTD device. If left unspecified the first MTD device found +(e.g. /dev/mtd0) will be used by default. + +Please note that the linux_mtd driver only works on Linux. + + +linux_spi programmer +^^^^^^^^^^^^^^^^^^^^ + +You have to specify the SPI controller to use with the:: + + flashrom -p linux_spi:dev=/dev/spidevX.Y + +syntax where ``/dev/spidevX.Y`` is the Linux device node for your SPI controller. + +In case the device supports it, you can set the SPI clock frequency with the optional ``spispeed`` parameter. +The frequency is parsed as kilohertz. Example that sets the frequency to 8 MHz:: + + flashrom -p linux_spi:dev=/dev/spidevX.Y,spispeed=8000 + +Please note that the linux_spi driver only works on Linux. + + +mstarddc_spi programmer +^^^^^^^^^^^^^^^^^^^^^^^ + +The Display Data Channel (DDC) is an I2C bus present on VGA and DVI connectors, that allows exchanging information +between a computer and attached displays. Its most common uses are getting display capabilities through EDID +(at I2C address 0x50) and sending commands to the display using the DDC/CI protocol (at address 0x37). +On displays driven by MSTAR SoCs, it is also possible to access the SoC firmware flash (connected to the Soc through another SPI bus) +using an In-System Programming (ISP) port, usually at address 0x49. This **flashrom** module allows the latter via Linux's I2C driver. + +**IMPORTANT:** +Before using this programmer, the display **MUST** be in standby mode, and only connected to the computer that will run +**flashrom** using a VGA cable, to an inactive VGA output. It absolutely **MUST NOT** be used as a display during the procedure! + +You have to specify the DDC/I2C controller and I2C address to use with the:: + + flashrom -p mstarddc_spi:dev=/dev/i2c-X:YY + +syntax where ``/dev/i2c-X`` is the Linux device node for your I2C controller connected to the display's DDC channel, and +``YY`` is the (hexadecimal) address of the MSTAR ISP port (address 0x49 is usually used). +Example that uses I2C controller /dev/i2c-1 and address 0x49:: + + flashrom -p mstarddc_spi:dev=/dev/i2c-1:49 + +It is also possible to inhibit the reset command that is normally sent to the display once the **flashrom** operation is +completed using the optional ``noreset`` parameter. A value of 1 prevents **flashrom** from sending the reset command. +Example that does not reset the display at the end of the operation:: + + flashrom -p mstarddc_spi:dev=/dev/i2c-1:49,noreset=1 + +Please note that sending the reset command is also inhibited if an error occurred during the operation. +To send the reset command afterwards, you can simply run **flashrom** once more, in chip probe mode (not specifying an operation), +without the ``noreset`` parameter, once the flash read/write operation you intended to perform has completed successfully. + +Please also note that the mstarddc_spi driver only works on Linux. + + +ch341a_spi programmer +^^^^^^^^^^^^^^^^^^^^^ + +The WCH CH341A programmer does not support any parameters currently. SPI frequency is fixed at 2 MHz, and CS0 is used +as per the device. + + +ch347_spi programmer +^^^^^^^^^^^^^^^^^^^^ + +An optional ``spispeed`` parameter could be used to specify the SPI speed. This parameter is available for the CH347T and CH347F device. +The default SPI speed is 15MHz if no value is specified. +Syntax is:: + + flashrom -p ch347_spi:spispeed=value + +where ``value`` can be ``60M``, ``30M``, ``15M``, ``7.5M``, ``3.75M``, ``1.875M``, ``937.5K``, ``468.75K``. + + +ni845x_spi programmer +^^^^^^^^^^^^^^^^^^^^^ + +An optional ``voltage`` parameter could be used to specify the IO voltage. This parameter is available for the NI USB-8452 device. +The default unit is Volt if no unit is specified. You can use ``mV``, ``milliVolt``, ``V`` or ``Volt`` as unit specifier. +Syntax is:: + + flashrom -p ni845x_spi:voltage=value + +where ``value`` can be ``1.2V``, ``1.5V``, ``1.8V``, ``2.5V``, ``3.3V`` or the equivalent in mV. + +In the case if none of the programmer's supported IO voltage is within the supported voltage range of the detected flash +chip the **flashrom** will abort the operation (to prevent damaging the flash chip). +You can override this behaviour by passing ``yes`` to the ``ignore_io_voltage_limits`` parameter +(for e.g. if you are using an external voltage translator circuit). Syntax is:: + + flashrom -p ni845x_spi:ignore_io_voltage_limits=yes + +You can use the ``serial`` parameter to explicitly specify which connected NI USB-845x device should be used. You should +use your device's 7 digit hexadecimal serial number. Usage example to select the device with 1230A12 serial number:: + + flashrom -p ni845x_spi:serial=1230A12 + +An optional ``spispeed`` parameter specifies the frequency of the SPI bus. Syntax is:: + + flashrom -p ni845x_spi:spispeed=frequency + +where ``frequency`` should a number corresponding to the desired frequency in kHz. +The maximum ``frequency`` is 12 MHz (12000 kHz) for the USB-8451 and 50 MHz (50000 kHz) for the USB-8452. +The default is a frequency of 1 MHz (1000 kHz). + +An optional ``cs`` parameter specifies which target chip select line should be used. Syntax is:: + + flashrom -p ni845x_spi:csnumber=value + +where ``value`` should be between ``0`` and ``7``. By default the CS0 is used. + + +digilent_spi programmer +^^^^^^^^^^^^^^^^^^^^^^^ + +An optional ``spispeed`` parameter specifies the frequency of the SPI bus. Syntax is:: + + flashrom -p digilent_spi:spispeed=frequency + +where ``frequency`` can be ``62.5k``, ``125k``, ``250k``, ``500k``, ``1M``, ``2M`` or ``4M`` (in Hz). +The default is a frequency of 4 MHz. + + +dirtyjtag_spi programmer +^^^^^^^^^^^^^^^^^^^^^^^^ + +An optional ``freq`` parameter specifies the frequency of the SPI bus. Syntax is:: + + flashrom -p dirtyjtag_spi:spispeed=frequency + +where ``spispeed`` can be any value in hertz, kilohertz or megahertz supported by the programmer. +The default is a frequency of 100 KHz. + + +jlink_spi programmer +^^^^^^^^^^^^^^^^^^^^ + +This module supports SEGGER J-Link and compatible devices. + +The **MOSI** signal of the flash chip must be attached to **TDI** pin of the programmer, **MISO** to **TDO** and +**SCK** to **TCK**. The chip select (**CS**) signal of the flash chip can be attached to different pins of the +programmer which can be selected with the:: + + flashrom -p jlink_spi:cs=pin + +syntax where ``pin`` can be either ``TRST``, ``RESET`` or ``TMS``. The default pin for chip select is ``RESET``. +Note that, when using ``RESET``, it is normal that the indicator LED blinks orange or red. + +Additionally, the ``Tref`` pin of the programmer must be attached to the logic level of the flash chip. +The programmer measures the voltage on this pin and generates the reference +voltage for its input comparators and adapts its output voltages to it. + +Pinout for devices with 20-pin JTAG connector:: + + +-------+ + | 1 2 | 1: VTref 2: + | 3 4 | 3: TRST 4: GND + | 5 6 | 5: TDI 6: GND + +-+ 7 8 | 7: TMS 8: GND + | 9 10 | 9: TCK 10: GND + | 11 12 | 11: 12: GND + +-+ 13 14 | 13: TDO 14: + | 15 16 | 15: RESET 16: + | 17 18 | 17: 18: + | 19 20 | 19: PWR_5V 20: + +-------+ + +If there is more than one compatible device connected, you can select which one should be used by specifying its serial +number with the:: + + flashrom -p jlink_spi:serial=number + +syntax where ``number`` is the serial number of the device (which can be found for example in the output of ``lsusb -v``). + +The SPI speed can be selected by using the:: + + flashrom -p jlink_spi:spispeed=frequency + +syntax where ``frequency`` is the SPI clock frequency in kHz. The maximum speed depends on the device in use. + +The ``power=on`` option can be used to activate the 5 V power supply (PWR_5V) of the J-Link during a flash operation. + + +stlinkv3_spi programmer +^^^^^^^^^^^^^^^^^^^^^^^ + +This module supports SPI flash programming through the STMicroelectronics STLINK V3 programmer/debugger's SPI bridge interface:: + + flashrom -p stlinkv3_spi + +If there is more than one compatible device connected, you can select which one should be used by specifying its +serial number with the:: + + flashrom -p stlinkv3_spi:serial=number + +syntax where ``number`` is the serial number of the device (which can be found for example in the output of ``lsusb -v``). + +The SPI speed can be selected by using the:: + + flashrom -p stlinkv3_spi:spispeed=frequency + +syntax where ``frequency`` is the SPI clock frequency in kHz. If the passed frequency is not supported by the adapter +the nearest lower supported frequency will be used. + + +realtek_mst_i2c_spi, parade_lspcon and mediatek_i2c_spi programmers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These programmers tunnel SPI commands through I2C-connected devices. The I2C bus over which communication occurs must be +specified either by device path with the ``devpath`` option:: + + flashrom -p realtek_mst_i2c_spi:devpath=/dev/i2c-8 + +or by a bus number with the ``bus`` option, which implies a device path like ``/dev/i2c-N`` where ``N`` is the specified +bus number:: + + flashrom -p parade_lspcon:bus=8 + + +realtek_mst_i2c_spi programmer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This programmer supports SPI flash programming for chips attached to Realtek DisplayPort MST hubs, themselves accessed +through I2C (tunneling SPI flash commands through the MST hub's I2C connection with the host). + + +In-system programming (ISP) mode +"""""""""""""""""""""""""""""""" + +The ``reset_mcu`` and ``enter_isp`` options provide control over device mode changes, where each can be set to ``0`` +or ``1`` to enable or disable the corresponding mode transition. + +``enter_isp`` defaults to ``1``, and if enabled will issue commands to the MST hub when beginning operation to put it +into ISP mode. + +``reset_mcu`` defaults to ``0``, and if enabled will issue a reset command to the MST hub on programming completion, +causing it to exit ISP mode and to reload its own firmware from flash. + +``allow_brick`` defaults to ``no``, however must be set explicitly to ``yes`` to allow the driver to run if you are sure +you have a MST chip. + +The hub must be in ISP mode for SPI flash access to be possible, so it is usually only useful to disable ``enter_isp`` +if an earlier invocation avoided resetting it on completion. For instance, to erase the flash and rewrite it with the +contents of a file without resetting in between (which could render it nonfunctional if attempting to load firmware +from a blank flash):: + + flashrom -p realtek_mst_i2c_spi:bus=0,enter_isp=1,reset_mcu=0 -E + + flashrom -p realtek_mst_i2c_spi:bus=0,enter_isp=0,reset_mcu=1 -w new.bin + + +parade_lspcon programmer +^^^^^^^^^^^^^^^^^^^^^^^^ + +This programmer supports SPI flash programming for chips attached to Parade Technologies DisplayPort-to-HDMI level +shifter/protocol converters (LSPCONs), e.g. the PS175. Communication to the SPI flash is tunneled through the LSPCON +over I2C. + + +mediatek_i2c_spi programmer +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This programmer supports SPI flash programming for chips attached to some Mediatek display controllers, themselves +accessed through I2C (tunneling SPI flash commands through an I2C connection with the host). + +The programmer is designed to support the TSUMOP82JUQ integrated display driver and scaler as used in the Google Meet +Series One Desk 27 (which runs a version of ChromeOS and uses **flashrom** in its ``tsum-scaler-updater`` scripts that ship +with the OS). Other chips may use compatible protocols but have not been tested with this programmer, and external chip +IOs may need to be controlled through other non- **flashrom** means to configure the chip in order for it to operate as expected. + +``devpath`` and ``bus`` options select the I2C bus to use, as described previously. ``allow_brick`` defaults to ``no``, +and must explicitly be set to ``yes`` in order for the programmer to operate. This is required because there is no +mechanism in the driver to positively identify that a given I2C bus is actually connected to a supported device. + + +EXAMPLES +-------- + +To back up and update your BIOS, run:: + + flashrom -p internal -r backup.rom -o backuplog.txt + flashrom -p internal -w newbios.rom -o writelog.txt + +Please make sure to copy backup.rom to some external media before you try to write. That makes offline recovery easier. + +If writing fails and **flashrom** complains about the chip being in an unknown state, you can try to restore the backup by running:: + + flashrom -p internal -w backup.rom -o restorelog.txt + +If you encounter any problems, please contact us and supply backuplog.txt, writelog.txt and restorelog.txt. +See section **BUGS** for contact info. + + +EXIT STATUS +----------- + +**flashrom** exits with 0 on success, 1 on most failures but with 3 if a call to mmap() fails. + + +REQUIREMENTS +------------ + +**flashrom** needs different access permissions for different programmers. + +* internal + + * needs raw memory access + * PCI configuration space access + * raw I/O port access (x86) + * MSR access (x86) + +* atavia + + * needs PCI configuration space access + +* nic3com, nicrealtek, nicnatsemi + + * need PCI configuration space read access + * raw I/O port access + +* atahpt + + * needs PCI configuration space access + * raw I/O port access + +* gfxnvidia, drkaiser, it8212 + + * need PCI configuration space access + * raw memory access + +* rayer_spi + + * needs raw I/O port access + +* raiden_debug_spi + + * needs access to the respective USB device via libusb API version 1.0 + +* satasii, nicintel, nicintel_eeprom, nicintel_spi + + * need PCI configuration space read access + * raw memory access + +* satamv, atapromise + + * need PCI configuration space read access + * raw I/O port access + * raw memory access + +* serprog + + * needs TCP access to the network or userspace access to a serial port + +* buspirate_spi + + * needs userspace access to a serial port + +* ft2232_spi, usbblaster_spi, pickit2_spi + + * need access to the respective USB device via libusb API version 1.0 + +* ch341a_spi, dediprog + + * need access to the respective USB device via libusb API version 1.0 + +* dummy + + * needs no access permissions at all + +* internal, nic3com, nicrealtek, nicnatsemi, gfxnvidia, drkaiser, satasii, satamv, atahpt, atavia, atapromise, asm106x + + * have to be run as superuser/root + * need raw access permission + +* serprog, buspirate_spi, dediprog, usbblaster_spi, ft2232_spi, pickit2_spi, ch341a_spi, digilent_spi, dirtyjtag_spi + + * can be run as normal user on most operating systems if appropriate device permissions are set + +* ogp + + * needs PCI configuration space read access and raw memory access + +* realtek_mst_i2c_spi, parade_lspcon + + * need userspace access to the selected I2C bus + +On OpenBSD, you can obtain raw access permission by setting:: + + securelevel=-1 + +in **/etc/rc.securelevel** and rebooting, or rebooting into single user mode. + + +BUGS +---- + +You can report bugs, ask us questions or send success reports via our communication channels listed here: +`Contact `_ + +Also, we provide a `pastebin service `_ that is very useful to share logs without spamming +the communication channels. + + +Laptops +------- + +Using **flashrom** on older laptops is dangerous and may easily make your hardware unusable. **flashrom** will attempt to detect +if it is running on a susceptible laptop and restrict flash-chip probing for safety reasons. Please see the detailed +discussion of this topic and associated **flashrom** options in the **Laptops** paragraph in the **internal programmer** +subsection of the **PROGRAMMER-SPECIFIC INFORMATION** section and the information `in our wiki `_. + +One-time programmable (OTP) memory and unique IDs + +Some flash chips contain OTP memory often denoted as **security registers**. They usually have a capacity in the range +of some bytes to a few hundred bytes and can be used to give devices unique IDs etc. **flashrom** is not able to read +or write these memories and may therefore not be able to duplicate a chip completely. For chip types known to include +OTP memories a warning is printed when they are detected. + +Similar to OTP memories are unique, factory programmed, unforgeable IDs. They are not modifiable by the user at all. + + +LICENSE +------- + +**flashrom** is covered by the GNU General Public License (GPL), version 2. Some files are additionally available +under any later version of the GPL. + + +COPYRIGHT +--------- +Please see the individual files. + + +AUTHORS +------- + +Andrew Morgan, Anastasia Klimchuk, Carl-Daniel Hailfinger, Claus Gindhart, David Borg, David Hendricks, Dominik Geyer, +Edward O'Callaghan, Eric Biederman, Giampiero Giancipoli, Helge Wagner, Idwer Vollering, Joe Bao, Joerg Fischer, +Joshua Roys, Kyösti Mälkki, Luc Verhaegen, Li-Ta Lo, Mark Marshall, Markus Boas, Mattias Mattsson, Michael Karcher, +Nikolay Petukhov, Patrick Georgi, Peter Lemenkov, Peter Stuge, Reinder E.N. de Haan, Ronald G. Minnich, Ronald Hoogenboom, +Sean Nelson, Stefan Reinauer, Stefan Tauner, Stefan Wildemann, Stephan Guilloux, Steven James, Urja Rannikko, Uwe Hermann, +Wang Qingpei, Yinghai Lu and others, please see the **flashrom** git history for details. + +All still active authors can be reached via `the mailing list `_. + +This manual page was written by `Uwe Hermann `_, Carl-Daniel Hailfinger, Stefan Tauner and others. +It is licensed under the terms of the GNU GPL (version 2 or later). diff --git a/doc/conf.py b/doc/conf.py new file mode 100644 index 000000000..be9cc0174 --- /dev/null +++ b/doc/conf.py @@ -0,0 +1,49 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +import os + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'flashrom' +# copyright = '2023, The flashrom authors' +author = 'The flashrom authors' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +master_doc = 'index' # this is needed for old versions + +extensions = [ + 'sphinx.ext.todo' +] + +#templates_path = ['_templates'] +exclude_patterns = [] + +# -- Options for Todo extension ---------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/extensions/todo.html + +# If this is True, todo and todolist produce output, else they produce nothing. The default is False. +todo_include_todos = False + + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'alabaster' +#html_static_path = ['_static'] + +html_favicon = 'logo/flashrom_icon_color-32x32.ico' + + +# -- Options for manual page output -------------------------------------------- +man_make_section_directory = True +man_show_urls = True +man_pages = [ + ('classic_cli_manpage', project, '', [], 8), +] diff --git a/doc/contact.rst b/doc/contact.rst new file mode 100644 index 000000000..38888fbbd --- /dev/null +++ b/doc/contact.rst @@ -0,0 +1,161 @@ +Contact +======== +.. The extra = is needed to prevent git from throwing a `leftover conflict marker` + error when commiting. + +.. _mailing list: + +Mailing List +------------ +Flashrom related mails are welcome on the flashrom mailing list at `flashrom@flashrom.org `_. +Please do NOT send any BIOS images or F segment dumps to the list! + +E-mails with binary files attached will be rejected. Images for things such as scope or logic analyzer traces are acceptable +if hosted on a third-party photo sharing service that assigns a unique URL to the image, such as Google Photos. +This prevents the photo URL from being abused for malicious or inappropriate content. + +Please note that the list is moderated for non-subscribers and we recommend to subscribe first. + +Subscription +"""""""""""" +https://mail.coreboot.org/postorius/lists/flashrom.flashrom.org/ + +Archives +"""""""" +| https://mail.coreboot.org/hyperkitty/list/flashrom@flashrom.org/ +| https://mail.coreboot.org/pipermail/flashrom/ (Up to Dec. 2018) +| https://marc.info/?l=flashrom +| https://www.mail-archive.com/flashrom@flashrom.org/ + +Moderation rules +"""""""""""""""" +If your mail is too big (the current limit is 256 kB) or if you're not on the subscriber list, your mail will be held for moderation. +If your mail contains any BIOS images or F segment dumps (instead of links which are fine), the mail will be rejected for legal reasons +(we do not have the right to distribute BIOS images). + +.. _real time channels: + +Real time channels +------------------ + +Flashrom has real time channels where you have the chance to talk to people being involved or interested in the project. +Most of the discussion is about flashrom development, contributions, tech talk and user help. + +You are welcome to join and discuss current and future flashrom development, ideas and contributions. + +If you have a problem and would like to get help, don't ask for help. Instead, just explain your problem right away, +and make sure to describe the situation as much as possible, so that other people can understand you and provide meaningful answers. +Otherwise, others have to ask or guess the details of your problem, which is frustrating for both parties. + +Should you need to paste lots of text (more than three lines), please use a `paste service `_. +For flashrom logs, feel free to use `paste.flashrom.org `_. +Other good paste services are `ix.io `_, `paste.rs `_, `bpaste.net `_, +`gist.github.com `_ and `dpaste.com `_. + +Questions on `coreboot `_, `OpenBIOS `_, firmware and related topics are welcome in **#coreboot** on the same server. + +Discord +""""""" + +Flashrom Discord channel is hosted on coreboot's server. Once you join, you will be able to see all coreboot's and flashrom's channels in one place. +To join, use the `invite link `_. + +IRC +""" + +You can join `#flashrom `_ +channel on the `Libera.chat `_ `IRC `_ network. +If you don't have an IRC client, you can use the Libera.chat `webchat `_. + +**#flashrom** channel is bridged to `Matrix `_. +If you would like to join, you can use `this invite link `_. + +Do note that IRC's nature has a significant effect on conversations. People from all over the world can join this channel +with many different cultures and timezones. Most people are in the `CET timezone `_, +so the channel may be very quiet during `CET nighttime `_. + +If you receive no replies, *please be patient*. +After all, silence is better than getting replied with `"IDK" `_. +Frequently, somebody knows the answer, but hasn't checked IRC yet. In any case, please *do not leave the channel while waiting for an answer!* +Since IRC does not store messages, replying to somebody who left the channel is *impossible*. + +To have persistence on IRC, you can set up an `IRC bouncer `_ +like `ZNC `_, or use `IRCCloud `_. +Please **do not publish any logs** of this channel. + +Most of the time, people use IRC on wider-than-tall screens. Because of this, consider that pressing the return key is expensive. +Instead of sending lots of tiny messages with only about two words, prefer using longer sentences, spaces and punctuation symbols. +If reading and understanding your messages is easy, replying to them is also easy. + +*Note: the channel is not moderated or monitored by any of the current active maintainers.* + +Dev meeting +----------- +Flashrom developers community runs an online meeting every two weeks. +The main purpose of the meeting is to discuss development plans, ideas, +current ongoing projects, pending patches, and sometimes organisational questions. + +Note this meeting is NOT: + +* troubleshooting session +* tech support forum +* user training session + +For questions above, please use IRC or the mailing list. + +Time of meeting +""""""""""""""" +It runs once every two weeks. + +**IMPORTANT**: please calculate meeting time for your local timezone. + +Between November and March (inclusive) + + **Wednesday 21:00-22:00 UTC+0** + + also known as + + | Wednesday 13:00-14:00 Pacific Standard Time UTC-8 + | Wednesday 22:00-23:00 Central European Time UTC+1 + | Thursday 8:00-9:00 Australian Eastern Daylight Time UTC+11 + +Between April and September (inclusive) + + **Thursday 6:00-7:00 UTC+0** + + also known as + + | Wednesday 23:00-midnight Pacific Daylight Time UTC-7 + | Thursday 8:00-9:00 Central European Summer Time UTC+2 + | Thursday 16:00-17:00 Australian Eastern Standard Time UTC+10 + +The last week of March and 4 weeks of October there are no meetings +This is because daylight saving time changes are happening on different dates in different locations, and setting up meeting time becomes too complicated. + +FAQ +""" +**When is the next meeting?** + +Look into the meeting notes `document `_. +The top entry, on the first page, with the date in the future, and empty list of attendees - is the next meeting. + + +**How to join the meeting?** + +In the meeting notes `document `_, +on the top it says “to join, click the link”, click the link. + + +**Do I need an invitation to join the meeting?** + +No, just join. + + +**Do I need to create an account anywhere?** + +No, you can join without an account, and view/comment on the meeting doc without an account. + + +**How do I add a topic to the agenda?** + +Add comments/suggestions on the meeting doc, and they will be accepted shortly after. diff --git a/doc/contrib_howtos/how_to_add_new_chip.rst b/doc/contrib_howtos/how_to_add_new_chip.rst new file mode 100644 index 000000000..8aad3241a --- /dev/null +++ b/doc/contrib_howtos/how_to_add_new_chip.rst @@ -0,0 +1,238 @@ +===================== +How to add a new chip +===================== + +To add a new chip definition you need to send a patch to flashrom. This can be your first patch to flashrom. However if it is +your first patch please read carefully :doc:`/dev_guide/development_guide`, and set up dev environment locally. + +The expectation is that you have tested successfully at least some of the operations on the chip (not necessarily all of them). +There is an exception: when datasheet covers more than one model of the same chip, but you only have one and tested that one. +Typically, you would add all the models covered by the datasheet you have, but only mark tested the one you tested. + +To begin with, make sure you have a link to the publicly available datasheet for the chip you want to add. Publicly +available datasheet is a requirement for adding a new chip. + +Open the datasheet, ``flashchips.c`` and ``include/flashchips.h``, and then + +Model ID and vendor ID +====================== + +Find model ID and vendor ID in the datasheet. This information often can be found in the sections like "Device identification", +"Device ID", "Manufacturer ID", "Table of ID definitions" or something similar to that. +These values come in combination with commands used for probing the chip (more on probing below). Most commonly used command for +probing SPI chips is ``0x9f`` which corresponds to ``PROBE_SPI_RDID``. + +At this point you need to double-check if exact same chip is already defined. Search for the ``.name`` and ``.vendor`` of the chip +you have in ``flashchips.c`` and if found, compare values of ``.manufacture_id`` and ``.model_id``. If all 4 values match, it +seems like the chip already defined. In this case you can try using it. Possibly, only the testing status of the chip needs to be +updated, in this case see :doc:`how_to_mark_chip_tested` for instructions. + +Vendor (manufacturer) ID +------------------------ + +Search for vendor ID in ``include/flashchips.h``, IDs are defined as macros. If it exists already, use existing macro in your +chip definition. If it does not exist (which means your chip is the first ever for this vendor), define macro for this ID, +add a comment. Look at existing IDs in ``include/flashchips.h`` as examples. + +Model ID +-------- + +Search for model ID in ``include/flashchips.h``. If there is no macro defined for it, add macro for model ID in the corresponding +section for given vendor. + +Model IDs should follow the pattern. They are all uppercase; first the manufacturer name (used for the manufacturer IDs macros +on top of each paragraph in flashchips.h), followed by an underscore and then the chipname. The latter should in general equal +the ``.name``, with dots (and other disallowed characters) replaced by underscores. Shared chip IDs typically use the macro name +that happened to be added first to flashrom (which is also probably the first one manufactured) and which usually matches +the other chips of that series in ``include/flashchips.h``. + +If you added a new model ID, use it in new chip definition, skip the rest of instructions about Model ID +and continue with the next section "Properties". + +Model ID already exists +^^^^^^^^^^^^^^^^^^^^^^^ + +It is possible that model ID already exists in the header. Then find the corresponding definition in ``flashchips.c`` and inspect +it carefully. Is it the same chip that you have or a different one? + +The question you need to figure out is: whether existing definition can work for your chip or not. You figure that out by +reading the rest of instructions and comparing the values from the datasheet with existing definition. + +Existing definition matches, but it has a different chip name +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It is possible all the values from the datasheet match existing definition, but it has a different chip name. This is fine, +and in this case you need to add a comment to the macro ID definition which looks like ``Same as ...``. +Look at existing examples in ``include/flashchips.h`` file. +You should change the ``.name`` to reflect the additional chip model (see other chips of naming examples). +You don't need to add new definition. + +Existing definition does not match +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It is possible that, despite of the same model ID, existing vs new chips have significant different and they +need different definitions. Judging the significance of a difference might be not trivial and might require some understanding +of flashrom behavior, however the examples of significant differences are: different sizes of erase blocks, +or different opcodes for operations (see more on operations below), or different configuration for write-protection (if this +config is defined). + +In this case you need to do both: + +* Add a comment to existing model ID macro, ``Same as ...`` +* Add new chip definition, re-use existing ID macro + +Note that if you need to add new chip definition, it is fine to copy a similar one that already exist and correct the values. + +Make sure to keep the alphabetic ordering of chip names, and place new definition into the section with other chips +by the same vendor. + +Properties +========== + +* From the datasheet, get ``.vendor``, ``.name``, ``.bustype``, ``.total_size``. +* ``.voltage`` defines the upper and lower bounds of the supply voltage of the chip. If there are multiple chip models + with different allowed voltage ranges, the `intersection `_ + should be used and an appropriate comment added. +* ``.page_size`` is really hard. + Please read this `long explanation `_, + or ignore it for now and set it to 256. +* ``.tested`` is used to indicate if the code was tested to work with real hardware, its possible values are defined + in ``include/flash.h``. Without any tests it should be set to ``TEST_UNTESTED``. + See also another doc :doc:`how_to_mark_chip_tested`. + +Feature Bits +============ + +We encode various features of flash chips in a bitmask named ``.feature_bits``. +Available options can be found in ``include/flash.h``, look for macros defined by the pattern ``#define FEATURE_XXX``. + +Some of the feature bits have more detailed docs, see below. + +Write-Status-Register (WRSR) Handling +------------------------------------- + +The Write Status Register (WRSR) is used exclusively in SPI flash chips to configure various settings within the flash chip, +including write protection and other features. +The way WRSR is accessed varies between SPI flash chips, leading to the need for these feature bits. + +* ``FEATURE_WRSR_EWSR`` + indicates that we need an **Enable-Write-Status-Register** (EWSR) instruction which opens the status register for the + immediately-followed next WRSR instruction. Usually, the opcode is **0x50**. + +* ``FEATURE_WRSR_WREN`` + indicates that we need an **Write-Enable** (WREN) instruction to set the Write Enable Latch (WEL) bit. The WEL bit + must be set prior to every WRSR command. Usually, the opcode is **0x06**. + +* ``FEATURE_WRSR_EITHER`` + indicates that either EWSR or WREN is supported in this chip. + +Operations +========== + +Each operation is defined as a enum value from a corresponding enum. + +Probe +----- + +``.probe`` indicates which function is called to fetch IDs from the chip and to compare them with the ones in +``.manufacture_id`` and ``.model_id``. For most SPI flash chips ``PROBE_SPI_RDID`` is the most commonly used if the datasheets +mentions **0x9f** as an identification/probing opcode. + +To see the full list of available probing functions, check definition of ``enum probe_func`` in ``include/flash.h``. +You may need to inspect the source code of what a probing function is doing, check the mapping ``lookup_probe_func_ptr`` and +search for the function code. + +``.probe_timing`` is only used for non-SPI chips. It indicates the delay after "enter/exit ID mode" commands in microseconds +(see ``include/flash.h`` for special values). + +Read and write +-------------- + +``.read`` and ``.write`` indicate which functions are used for reading and writing on the chip. Currently flashrom +does only support a single function each. The one that is best supported by existing programmers should be used for now, +but others should be noted in a comment if available. + +To see the full list of available functions, check definitions of ``enum read_func`` and ``enum write_func`` in ``include/flash.h``. +To inspect the source code, check the mappings ``lookup_write_func_ptr`` and ``lookup_read_func_ptr`` and search for +the function code. + +The write granularity can be expressed by the ``.gran`` field. If you think you need something else than the default +``write_gran_256bytes`` then you should definitely ask one of the regular flashrom hackers first. +Possible values can be found in ``include/flash.h``. + +Erase +----- + +``block_erasers`` stores an array of pairs of erase functions (``.block_erase``) with their respective layout (``.eraseblocks``). + +``.block_erase`` is similar to the probing function. You should at least check that the opcode named in the function name +is matching the respective opcode in the datasheet. + +To see the full list of available functions, check definition of ``enum block_erase_func`` in ``include/flash.h``. +To inspect the source code, check the mappings ``lookup_erase_func_ptr`` and search for the function code. + +Two forms of ``.eraseblocks`` can be distinguished: symmetric and asymmetric layouts. +Symmetric means that all blocks that can be erased by an opcode are sized equal. In that case a single range can define +the whole layout (e.g. ``{4 * 1024, 256}`` means 256 blocks of 4 kB each). Asymmetric layouts on the other hand contain +differently sized blocks, ordered by their base addresses (e.g. ``{{8 * 1024, 1}, {4 * 1024, 2}, {16 * 1024, 7}}`` describes +a layout that starts with a single 8 kB block, followed by two 4 kB blocks and 7 16 kB blocks at the end). + +``.eraseblocks`` should be listed in order, from the smallest to the largest size. + +Printlock +--------- + +``.printlock`` is a `misnomer to some extent `_. + +It is used not only to print (write) protected address ranges of the chip, but also to pretty print the values +of the status register(s) - especially true for SPI chips. There are a lot of existing functions for that already +and you should reuse one if possible. Comparing the description of the status register in the datasheet of an already +supported chip with that of your chip can help to determine if you can reuse a printlock function. + +Check for definition of ``enum printlock_func`` and ``lookup_printlock_func_ptr`` for available options and source code. + +Unlock +------ + +``.unlock`` is called before flashrom wants to modify the chip's contents to disable possible write protections. +It is related to the ``.printlock`` function as it tries to change some of the bits displayed by ``.printlock``. + +Check for definition of ``enum blockprotect_func`` and ``lookup_blockprotect_func_ptr`` for available options and source code. + +Write-protection +================ + +Write-protection support is optional, and if you haven't tested it on the chip, don't add it. +If you, however, used and tested it, that would be great to add to chip definition. + +Registers bits +-------------- + +``.reg_bits`` stores information about what configuration bits the chip has and where they are found. + +For example, ``.cmp = {STATUS2, 6, RW}`` indicates that the chip has a complement bit (``CMP``) and it is the 6th bit +of the 2nd status register. See ``struct reg_bit_info`` in ``include/flash.h`` for details on each of the structure's fields. + +Note that some chips have configuration bits that function like ``TB/SEC/CMP`` but are called something else in the datasheet +(e.g. ``BP3/BP4/...``). These bits should be assigned to a field *according their function* and the datasheet name should be +noted in a comment, for example: + +:code:`.sec = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */` + +Decode range +------------ + +``.decode_range`` points to a function that determines what protection range will be selected by particular configuration +bit values. It is required for write-protect operations on the chip. + +Check for definition of ``enum decode_range_func`` and ``lookup_decode_range_func_ptr`` for available options and source code. + +Test your changes +================= + +After making changes in the code, rebuild flashrom, run unit tests, and test the chip. + +Add testing information to commit message. + +When all of the above done, follow :doc:`/dev_guide/development_guide` to push a patch and go through review process. +Dev guide has more details on the process. diff --git a/doc/contrib_howtos/how_to_add_unit_test.rst b/doc/contrib_howtos/how_to_add_unit_test.rst new file mode 100644 index 000000000..cb2aa3709 --- /dev/null +++ b/doc/contrib_howtos/how_to_add_unit_test.rst @@ -0,0 +1,101 @@ +====================== +How to add a unit test +====================== + +Unit tests help to maintain higher bar for code quality. A new unit test which adds coverage to the code is always useful, +no matter how small or large it is! Unit test is a valuable contribution, moreover it makes a good starter project, since +you don't need specific hardware (apart from you development host machine). + +For more details on how to run unit tests and measure coverage, check the dev guide: :ref:`unit tests`. + +To see the examples of existing unit tests, check the ``/tests`` directory in the source tree. If it helps, you can also look +at git history for examples of previous commits that add new tests. + +When is a good time to add a unit test? Any time is a good time. Test can go in its own separate patch, and also it can go +together in a patch which introduces a new code. + +Unit tests are using `cmocka `_ as a mocking framework, but we also have flashrom mock framework +on the top of that. + +Mocking +========= + +Unit tests mock all interactions with hardware, interactions with filesystem, syscalls, 3rd party libraries calls +(e.g. libusb, libpci) etc. You can think of a flashrom unit test as a mini-emulator. The goal is to cover as much as possible +flashrom code, but you don't need to go outside of that. + +See the list of all current mocks (which are called wraps in cmocka terminology) in ``/tests/wraps.h``. These might be enough for +your new test, or you might need to add more wraps as a part of new test. + +New wrap needs to be added to ``/tests/wraps.h``, ``/tests/tests.c``, ``/tests/meson.build``. If it's fine for new wrap to +do nothing, log invokation and return success, all good. + +If a wrap need to behave in a specific way for a test, and the behaviour can be different from one test to another, you need to +extend the wrap into ``/tests/io_mock.h`` framework. + +Add corresponding member (a function pointer) to ``struct io_mock`` +and redirect calls from a wrap function in ``/tests/tests.c`` into a member of ``io_mock``. The exact implementation +of the member function needs to be defined in your new test. At the beginning of a test scenario, define function pointers that your +test needs in your own ``struct io_mock`` and then register by calling ``io_mock_register``. At the end of a test, clean up +by calling ``io_mock_register(NULL)``. + +Note that ``io_mock`` can support state (if needed). State is a piece of custom data which is carried around for the duration +of the test scenario and is available in all functions in ``io_mock``. + +Adding a new test to a framework +================================ + +To add new test you will either add a new test function in existing .c file, or add new .c file and new function(s) there. + +If you add new file, you need to add it into the list of test source files in ``/tests/meson.build``. + +Each new test function needs to be added into ``/tests/tests.h`` and ``/tests/tests.c``. Follow existing entries as examples +how to do it. + +Types of tests +============== + +Programmers tests +----------------- + +The concept of a unit test for flashrom programmer is based on a programmer lifecycle. The options supported by the flashrom +test framework are the following (but you are very welcome to try implement new ideas). + +The smallest possible lifecycle is called basic and it does initialisation -> shutdown of a programmer (nothing else). +Another option is probing lifecycle, which does initialisation -> probing a chip -> shutdown. +These two expect successful scenarious, the whole scenario is expected to run until the end with no errors and +success return codes. + +One more option is to test expected failure for programmer initialisation. This is useful to test known invalid +(and potentially dangerous) combination of programmer parameters, when such combination should be detected at init time. +If invalid combination of parameters is detected, initialisation expected to fail early and programmer must not continue, +and not send any opcodes to the chip. + +For more details, source code is in ``/tests/lifecycle.h`` and ``/tests/lifecycle.c``. + +If you want to add new test(s) for a programmer, first you look whether that programmer has any tests already, or none at all. +Test source file has the same name as a programmer itself, for example programmer ``dummyflasher.c`` has its dedicated tests in +``/tests/dummyflasher.c`` file. Either add your tests to an existing file, or create new file for a programmer that had no tests +so far. The latter is more challenging, but it is very useful and highly appreciated. + +For programmers tests, the test scenario most likely won't be long: most likely it is one of the options to run lifecycle with +given combination of programmer params as an input. Most time and effort is typically spent on mocking (see above), and this +type of tests will indeed look like a mini-emulator. + +Chip operations tests +--------------------- + +These tests are based on dummyflasher programmer and they are running operations of a chip: read, write, erase, verify. +The test defines mock chip(s) with given properties, and all the operations of the chip are redirected to mock functions. +Mock chip has its own mock memory (an array of bytes) and all operations are performed on this array of bytes. +As all the others, these tests are completely independent of hardware, and are focused on testing core flashrom logic +for read, write, erase, verify. + +Examples of chip operation tests are: ``tests/chip.c``, ``/tests/chip_wp.c`` (focused on write-protection logic), +``/tests/erase_func_algo.c`` (focused on erasing and writing logic, especially the choice of erase blocks for given +layout regions). + +Misc +---- + +All other tests. You choose a function that you want to test, call it with given arguments, assert the results are as expected. diff --git a/doc/contrib_howtos/how_to_mark_chip_tested.rst b/doc/contrib_howtos/how_to_mark_chip_tested.rst new file mode 100644 index 000000000..5f02ffdee --- /dev/null +++ b/doc/contrib_howtos/how_to_mark_chip_tested.rst @@ -0,0 +1,46 @@ +========================== +How to mark chip as tested +========================== + +flashrom has a massive amount of flashchips definitions, not all of them are fully tested. The reason for this is: +in some situations chip definition can be introduced based on the values that the datasheet claims, +but without testing on hardware. In this case chip definition is marked as not tested, **TEST_UNTESTED**. If later +someone uses the chip for real, and it works, the chip definition can be (and should be) updated, and operations +which run successfully should be marked as tested. + +To mark the chip as tested, someone (one of the maintainers, or one of the contributors) need to send a patch to update +the list of flashchips. It can be you, and *yes it can be your first patch to flashrom!* If this is your first patch, +make sure you read the :doc:`/dev_guide/development_guide` and set up dev environment locally. If this is not possible, you +are welcome to send test results to the mailing list, see :ref:`mailing list`. + +Instructions below assume you went through Development guide, and set up environment and repository locally. + +To begin with, make sure you have full logs from all the operations that you have run successfully and want to +mark as tested. **Providing full logs which indicate successful run is required to mark chip as tested.** + +Information about tested status of the chip is stored in ``flashchips.c``, specifically in the ``.tested`` member +of ``struct flashchip``. + +Relevant definitions and available options are in ``include/flash.h``, specifically see the definition of: + +* ``enum test_state`` +* ``struct tested`` (inside ``struct flashchip``) +* pre-defined macros for ``struct tested``, all of them follow the pattern ``#define TEST_xxx_yyy`` + +Choose the correct value depending on the operations that you have tested successfully. And then: + +#. Open ``flashchips.c`` and find the definition of your chip. +#. Check the tested status of the chip. If you tested *not* on the latest HEAD (perhaps on the latest released version, + or on flashrom built a month ago, etc), it is possible that tested status has been updated already. If the status + has not been updated, +#. Update ``.tested`` value to the one which reflects current test status. Note that not all the operations have to be + tested at once: maybe you tested only probe and read, then mark just that. +#. Make sure flashrom builds successfully, and all the unit tests pass. +#. For commit title, use the string ``flashchips: Mark as tested for ``. +#. Provide the logs in commit message, you can use flashrom paste service at `paste.flashrom.org `_ + or any other paste service. As a plan B, you can post message on the :ref:`mailing list`, attach the logs to the post, + and then add the link to the post to the commit message. +#. Follow :doc:`/dev_guide/development_guide` and send your patch for review. +#. Go through review process until your patch gets approved (see Development guide for more details on this). + +To see the examples of such patches, have a look at commit history of ``flashchips.c``. diff --git a/doc/contrib_howtos/index.rst b/doc/contrib_howtos/index.rst new file mode 100644 index 000000000..cb74e1cec --- /dev/null +++ b/doc/contrib_howtos/index.rst @@ -0,0 +1,11 @@ +Contributors howtos +=================== + +.. toctree:: + :maxdepth: 1 + + how_to_add_new_chip + how_to_mark_chip_tested + how_to_add_unit_test + ../how_to_add_docs + ../how_to_support_flashrom diff --git a/doc/dev_guide/building_from_source.rst b/doc/dev_guide/building_from_source.rst new file mode 100644 index 000000000..b360b6033 --- /dev/null +++ b/doc/dev_guide/building_from_source.rst @@ -0,0 +1,314 @@ +Building from source +==================== + +You're going to need the following tools to get started: + +* gcc or clang +* meson +* ninja +* pkg-config +* sphinx-build* + +| \* optional, to build man-pages and html documentation + +And the following dependencies: + +* cmocka [#b1]_ +* linux-headers [#b2]_ +* libpci [#b2]_ +* libusb1 [#b2]_ +* libftdi1 [#b2]_ +* libjaylink [#b2]_ +* NI-845x driver & library package [#b3]_ + +.. [#b1] | optional, for building unit testing +.. [#b2] | optional, depending on the selected programmer +.. [#b3] | optional, proprietary and Windows only. (See Windows build instructions) + +If you are cross compiling, install the dependencies for your target. + +TL;DR +----- +:: + + meson setup builddir + meson compile -C builddir + meson test -C builddir + meson install -C builddir + + +.. _installing-dependencies: + +Installing dependencies +----------------------- + +.. todo:: Move the bullet points to `tabs `_ + + * No external dependencies (documentation should be build without fetching all of pypi) + * No Javascript? + +Linux +""""" + +* Debian / Ubuntu + + :: + + apt-get install -y \ + gcc meson ninja-build pkg-config python3-sphinx \ + libcmocka-dev libpci-dev libusb-1.0-0-dev libftdi1-dev libjaylink-dev + +* ArchLinux / Manjaro + + :: + + pacman -S --noconfirm \ + gcc meson ninja pkg-config python-sphinx cmocka \ + pciutils libusb libftdi libjaylink + +* openSUSE / SUSE + + :: + + zypper install -y \ + gcc meson ninja pkg-config python3-Sphinx \ + libcmocka-devel pciutils-devel libusb-1_0-devel libftdi1-devel libjaylink-devel + +* NixOS / nixpkgs + + * There is a ``shell.nix`` under ``scripts/`` + + :: + + nix-shell -p \ + gcc meson ninja pkg-config sphinx \ + cmocka pciutils libusb1 libftdi1 libjaylink + +* Alpine Linux + + :: + + apk add \ + build-base meson ninja pkgconf py3-sphinx \ + cmocka-dev pciutils-dev libusb-dev libjaylink-dev + +Windows +""""""" + +* MSYS2 + + Install `MSYS2 `_ and ensure it is `fully updated `_. + + * ``libpci`` is not available through the package manager and pci based programmer are not supported on Windows. + * ``ni845x_spi`` is only available with the proprietary library from National Instruments. Download and install the driver + from `ni.com `_ and build flashrom + for **32-bit**. Add ``-Dprogrammer=ni845x_spi`` to your meson configuration. + + In the MINGW64 shell run:: + + pacman -Sy \ + mingw-w64-x86_64-gcc mingw-w64-x86_64-meson mingw-w64-x86_64-ninja mingw-w64-x86_64-pkg-config mingw-w64-x86_64-python-sphinx \ + mingw-w64-x86_64-cmocka mingw-w64-x86_64-libusb mingw-w64-x86_64-libftdi mingw-w64-x86_64-libjaylink-git + + For building flashrom as 32-bit application, use the MSYS2 MINGW32 shell and run:: + + pacman -Sy \ + mingw-w64-i686-gcc mingw-w64-i686-meson mingw-w64-i686-ninja mingw-w64-i686-pkg-config mingw-w64-i686-python-sphinx \ + mingw-w64-i686-cmocka mingw-w64-i686-libusb mingw-w64-i686-libftdi mingw-w64-i686-libjaylink-git + +MacOS +""""" + +* Homebrew + + * ``libpci`` is not available through the package manager + * ``libjaylink`` is not available through the package manager + + :: + + brew install \ + meson ninja pkg-config sphinx-doc \ + libusb libftdi + +BSD +""" + +* FreeBSD / DragonFlyBSD + + * ``libusb1`` is part of the system + * ``libjaylink`` is not available through the package manager + + :: + + pkg install \ + meson ninja pkgconf py39-sphinx \ + cmocka libpci libftdi1 + +* OpenBSD + + * ``libjaylink`` is not available through the package manager + + :: + + pkg_add \ + meson ninja pkg-config py39-sphinx\ + cmocka pciutils libusb1 libftdi1 + +* NetBSD + + * ``libjaylink`` is not available through the package manager + * note: https://www.cambus.net/installing-ca-certificates-on-netbsd/ + + :: + + pkgin install \ + meson ninja pkg-config py39-sphinx \ + cmocka pciutils libusb1 libftdi1 + +OpenIndiana (Illumos, Solaris, SunOS) +""""""""""""""""""""""""""""""""""""" + +* ``libpci`` missing, pciutils is build without it +* ``libftdi1`` & ``libjaylink`` are not available through the package manager +* TODO: replace ``build-essential`` with the default compiler + +:: + + pkg install build-essential meson ninja cmocka libusb-1 + +DJGPP-DOS +""""""""" + +* Get `DJGPP `_ +* A great build script can be found `here `_ +* Download the `pciutils `_ sources + +| Run the following commands in the the pciutils directory to build libpci for DOS. +| Replace ```` with your cross-compile install root. + +:: + + make install-lib \ + ZLIB=no \ + DNS=no \ + HOST=i386-djgpp-djgpp \ + CROSS_COMPILE=i586-pc-msdosdjgpp- \ + STRIP="--strip-program=i586-pc-msdosdjgpp-strip -s" \ + PREFIX= + +Point pkg-config to the ```` :: + + export PKG_CONFIG_SYSROOT= + +* To compile flashrom use the ``meson_cross/i586_djgpp_dos.txt`` cross-file +* You will need `CWSDPMI.EXE `_ to run flashrom + +libpayload +"""""""""" + + .. todo:: Add building instructions for libpayload + + +Configuration +------------- +In the flashrom repository run:: + + meson setup [builtin options] [flashrom options] + +Mesons ``[builtin options]`` can be displayed with ``meson setup --help``. +The flashrom specific options can be found in ``meson_options.txt`` in the top-level +directory of flashrom and are used like in cmake with ``-Doption=value`` +Run ``meson configure`` to display all configuration options. + +.. todo:: Write a sphinx extension to render ``meson_options.txt`` here + + +Configuration for Crossbuilds +----------------------------- +Flashrom specific cross-files can be found in the ``meson_cross`` folder. +To use them run:: + + meson setup --cross-file [builtin options] [flashrom options] + +The options are the same as the normal configuration options. For more information see +https://mesonbuild.com/Cross-compilation.html + + +Compiling +--------- +Run:: + + meson compile -C + + +Update configuration +-------------------- +If you want to change your initial configuration for some reason +(for example you discovered that a programmer is missing), run:: + + meson configure [updated builtin options] [updated flashrom options] + +.. _unit tests: + +Unit Tests +---------- +To execute the unit tests run:: + + meson test -C + +You will get a summary of the unit test results at the end. + + +Code coverage +""""""""""""" +gcov + Due to a bug in lcov, the html file will only be correct if lcov is not + installed and gcovr is installed. See + https://github.com/linux-test-project/lcov/issues/168 and + https://github.com/mesonbuild/meson/issues/6747 + + To create the coverage target add ``-Db_coverage=true`` to your build configuration. + After executing the tests, you can run :: + + ninja -C coverage + + to generate the coverage report. + +lcov / llvm + https://clang.llvm.org/docs/SourceBasedCodeCoverage.html + Make sure that you are using `clang` as compiler, e.g. by setting `CC=clang` during configuration. + Beside that you need to add ``-Dllvm_cov=enabled`` to your build configuration :: + + CC=clang meson setup -Dllvm_cov=enable + meson test -C + ninja -C llvm-cov-tests + +For additional information see `the meson documentation `_ + + +Installing +---------- +To install flashrom and documentation, run:: + + meson install -C + +This will install flashrom under the PREFIX selected in the configuration phase. Default is ``/usr/local``. + +To install into a different directory use DESTDIR, like this:: + + DESTDIR=/your/destination/directory meson install -C + +You can also set the prefix during configuration with:: + + meson setup --prefix + +Create distribution package +--------------------------- +To create a distribution tarball from your ``builddir``, run:: + + meson dist -C + +This will collect all git tracked files and pack them into an archive. + +Current flashrom version is in the VERSION file. To release a new flashrom +version you need to change VERSION file and tag the changing commit. diff --git a/doc/dev_guide/development_guide.rst b/doc/dev_guide/development_guide.rst new file mode 100644 index 000000000..aac3a6cb4 --- /dev/null +++ b/doc/dev_guide/development_guide.rst @@ -0,0 +1,361 @@ +================= +Development Guide +================= + +We welcome contributions from every human being, corporate entity or club. + +This document describes the rules and recommendations about the development, contribution and review processes. + +If you introduce new features (not flash chips, but stuff like partial +programming, support for new external programmers, voltage handling, etc) +please **discuss your plans** on the :ref:`mailing list` first. That way, we +can avoid duplicated work and know about how flashrom internals need to be +adjusted and you avoid frustration if there is some disagreement about the +design. + +You can `look at the latest flashrom development efforts in Gerrit `_. + +Set up the git repository and dev environment +============================================= + +#. Clone git repository + + * If using https: :code:`git clone "https://review.coreboot.org/flashrom"` + * If using ssh: :code:`git clone "ssh://@review.coreboot.org:29418/flashrom"` + +#. Follow the build guidelines to install dependencies :doc:`building_from_source` + +#. Install Git hooks: :code:`./util/git-hooks/install.sh` + +#. Add upstream as a remote: + + * If using https: :code:`git remote add -f upstream https://review.coreboot.org/flashrom` + * If using ssh: :code:`git remote add -f upstream ssh://@review.coreboot.org:29418/flashrom` + +#. Check out a new local branch that tracks :code:`upstream/main`: :code:`git checkout -b upstream/main` + +#. Every patch is required to be signed-off (see also :ref:`sign-off`). + Set up your ``user.name`` and ``user.email`` in git config, and don't forget + to ``-s`` when creating a commit. + +#. See also build guidelines :doc:`building_from_source` and `git docs `_ + +Creating your patch +=================== + +In short, commit your changes with a descriptive message and remember to sign off +on the commit (``git commit -s``). + +.. _commit-message: + +Commit message +-------------- + +Commit messages shall have the following format:: + + : Short description (up to 72 characters) + + This is a long description. Max width of each line in the description + is 72 characters. It is separated from the summary by a blank line. You + may skip the long description if the short description is sufficient, + for example "flashchips: Add FOO25Q128" to add FOO25Q128 chip support. + + You may have multiple paragraphs in the long description, but please + do not write a novel here. For non-trivial changes you must explain + what your patch does, why, and how it was tested. + + Finally, follow the sign-off procedure to add your sign-off! + + Signed-off-by: Your Name + +Commit message should include: + +* Commit title +* Commit description: explain what the patch is doing, or what it is fixing. +* Testing information: how did you test the patch. +* Signed-off-by line (see below :ref:`sign-off`) +* If applicable, link to the ticket in the bugtracker ``_ +* Change-Id for Gerrit. If commit message doesn't have Change-Id, you forgot to install git hooks. + +.. _sign-off: + +Sign-off procedure +^^^^^^^^^^^^^^^^^^ + +We employ a similar sign-off procedure as the `Linux kernel developers +`_ +do. Add a note such as + +:code:`Signed-off-by: Random J Developer ` + +to your email/patch if you agree with the Developer's Certificate of Origin 1.1 +printed below. Read `this post on the LKML +`_ for rationale (spoiler: SCO). + +You must use your known identity in the ``Signed-off-by`` line and in any +copyright notices you add. Anonymous patches lack provenance and cannot be +committed! + +Developer's Certificate of Origin 1.1 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + By making a contribution to this project, I certify that: + + (a) The contribution was created in whole or in part by me and I have + the right to submit it under the open source license indicated in the file; or + + (b) The contribution is based upon previous work that, to the best of my + knowledge, is covered under an appropriate open source license and I have the + right under that license to submit that work with modifications, whether created + in whole or in part by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated in the file; or + + (c) The contribution was provided directly to me by some other person who + certified (a), (b) or (c) and I have not modified it; and + + (d) In the case of each of (a), (b), or (c), I understand and agree that + this project and the contribution are public and that a record of the contribution + (including all personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with this project or the + open source license indicated in the file. + +.. note:: + + The `Developer's Certificate of Origin 1.1 + `_ + is licensed under the terms of the `Creative Commons Attribution-ShareAlike + 2.5 License `_. + +Coding style +------------ + +Flashrom generally follows Linux kernel style: +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/coding-style.rst + +The notable exception is line length limit. Our guidelines are: + +* 80-columns soft limit for most code and comments. This is to encourage simple design and concise naming. +* 112-columns hard limit. Use this to reduce line breaks in cases where they + harm grep-ability or overall readability, such as print statements and + function signatures. Don't abuse this for long variable/function names or + deep nesting. +* Tables are the only exception to the hard limit and may be as long as needed + for practical purposes. + +Our guidelines borrow heavily from `coreboot coding style +`_ and `coreboot Gerrit +guidelines `_, +and most of them apply to flashrom as well. The really important part is about +the :ref:`sign-off procedure `. + +We try to **reuse as much code as possible** and create new files only if +absolutely needed, so if you find a function somewhere in the tree which +already does what you want, please use it. + +Testing a patch +--------------- + +We expect the patch to be appropriately tested by the patch owner. +Please add the testing information in commit message, for example that could be some of these: +programmer you were using, programmer params, chip, OS, operations you were running +(read/write/erase/verify), and anything else that is relevant. + +.. _working-with-gerrit: + +Working with Gerrit +=================== + +All of the patches and code reviews need to go via +`Gerrit on review.coreboot.org `_. +While it is technically possible to send a patch to the mailing list, that patch +still needs to be pushed to Gerrit by someone. We treat patches on the mailing list as a very +exceptional situation. Normal process is to push a patch to Gerrit. +Please read below for instructions and check `official Gerrit documentation `_. + +Creating an account +--------------------- + +#. Go to https://review.coreboot.org/login and sign in using the credentials of + your choice. +#. Edit your settings by clicking on the gear icon in the upper right corner. +#. Set your Gerrit username (this may be the different from the username of an + external account you log in with). +#. Add an e-mail address so that Gerrit can send notifications to you about + your patch. +#. Upload an SSH public key, or click the button to generate an HTTPS password. +#. After account created, set either "Full name" or "Display name", it is used by Gerrit + for code review emails. + +.. _pushing-a-patch: + +Pushing a patch +--------------- + +Before pushing a patch, make sure it builds on your environment and all unit tests pass (see :doc:`building_from_source`). + +To push patch to Gerrit, use the follow command: :code:`git push upstream HEAD:refs/for/main`. + +* If using HTTPS you will be prompted for the username and password you + set in the Gerrit UI. +* If successful, the Gerrit URL for your patch will be shown in the output. + +There is an option to add a topic to the patch. For one-off standalone patches this +is not necessary. However if your patch is a part of a larger effort, especially if the +work involves multiple contributors, it can be useful to mark that the patch belongs +to a certain topic. + +Adding a topic makes it easy to search "all the patches by the topic", even if the patches +have been authored by multiple people. + +To add a topic, push with the command: :code:`git push upstream HEAD:refs/for/main%topic=example_topic`. +Alternatively, you can add a topic from a Gerrit UI after the patch in pushed +(on the top-left section) of patch UI. + +Checking the CI +--------------- + +Every patch needs to get a ``Verified +1`` label, typically from Jenkins. Once the patch is pushed +to Gerrit, Jenkins is added automatically and runs its build script. The script builds the patch with +various config options, and runs unit tests (for more details see source code of ``test_build.sh``). +Then, Jenkins gives the patch ``+1`` or ``-1`` vote, indicating success or fail. + +In case of failure, follow Jenkins link (which it adds as a comment to the patch), open Console output, +find the error and try to fix it. + +In addition to building and running unit tests, Jenkins also runs a scan-build over the patch. Ideally +you should check that your patch does not introduce new warnings. To see scan-build report, follow +Jenkins link -> Build artifacts -> scan build link for the given run. + +Adding reviewers to the patch +----------------------------- + +After pushing the patch, ideally try to make sure there are some reviewers added to your patch. + +flashrom has MAINTAINERS file with people registered for some areas of the code. People who +are in MAINTAINERS file will be automatically added as reviewers if the patch touches that +area. However, not all areas are covered in the file, and it is possible that for the patch you +sent no one is added automatically. + +If you know someone in the dev community who can help with patch review, add the person(s) you know. + +In general, it's a good idea to add someone who has a knowledge of whatever the patch is doing, +even if the person has not been added automatically. + +If you are new, and don't know anyone, and no one has been added automatically: you can add +Anastasia Klimchuk (aklm) as a reviewer. + +Going through code reviews +-------------------------- + +You will likely get some comments on your patch, and you will need to fix the comments. +After doing the work locally, amend your commit ``git commit --amend -s`` and push to Gerrit again. +Check that Change-Id in commit message stays the same. This way Gerrit knows your change belongs +to the same patch, and will upload new change as new patchset for the same patch. + +After uploading the work, go through comments and respond to them. Mark as Done the ones you done +and mark them as resolved. If there is something that is impossible to do, or maybe you have more questions, +or maybe you are not sure what you are asked about: respond to a comment **without marking it as resolved**. + +It is completely fine to ask a clarifying questions if you don't understand what the comment is asking you to do. +If is also fine to explain why a comment can't be done, if you think it can't be done. + +The patch reviews may take some time, but please don't get discouraged. +We have quite high standards regarding code quality. + +Initial review should include a broad indication of acceptance or rejection of +the idea/rationale/motivation or the implementation + +In general, reviews should focus on the architectural changes and things that +affect flashrom as a whole. This includes (but is by no means limited to) +changes in APIs and types, safety, portability, extensibility, and +maintainability. The purpose of reviews is not to create perfect patches, but +to steer development in the right direction and produce consensus within the +community. The goal of each patch should be to improve the state of the project +- it does not need to fix all problems of the respective field perfectly. + + New contributors may need more detailed advices and should be told about + minor issues like formatting problems more precisely. The result of a review + should either be an accepted patch or a guideline how the existing code + should be changed to be eventually accepted. + +To get an idea whether the patch is ready or not, please check :ref:`merge-checklist`. + +If you sent a patch and later lost interest or no longer have time to follow up on code review, +please add a comment saying so. Then, if any of our maintainers are interested in finishing the work, +they can take over the patch. + +Downloading patch from Gerrit +----------------------------- + +Sometimes you may need to download a patch into your local repository. This can be needed for example: + +* if you want to test someone else's patch, +* if multiple developers are collaborating on a patch, +* if you are continuing someone else's work, when original author left or unable to continue. + +First prepare local repository: sync to head or to desired tag / commit. + +Open patch in Gerrit, open "three dot" menu on top-right, open Download patch. Copy Cherry-pick command (pick +the relevant tab for you: anonymous http / http / ssh) and run the copied command in your local repo. + +Now you have the commit locally and can do the testing or futher developing. To upload your local changes, +push patch to Gerrit again (see :ref:`pushing-a-patch`). + +Make sure people involved in the patch agree that you are pushing new version of someone else's patch, +so this does not come at a surprise for an original author. + +Merging patches +--------------- + +Merging to branches is limited to the "flashrom developers" group on Gerrit (see also :doc:`/about_flashrom/team`). + +The list of requirements for the patch to be ready for merging is below, see :ref:`merge-checklist`. +Some of the requirements are enforced by Gerrit, but not all of them. In general, a person who clicks +Submit button is responsible to go through Merge checklist. Code reviewers should be aware of the checklist +as well. + +Patch owners can use the checklist to detect whether the patch is ready for merging or not. + +.. _merge-checklist: + +Merge checklist +^^^^^^^^^^^^^^^ + +#. Every patch has to be reviewed and needs at least one +2 that was not given by the commit's author. + Ideally, people who were actively reviewing the patch and adding comments, would be the ones approving it. +#. If a patch is authored by more than one person (Co-developed-by), each author may +2 the other author's changes. +#. Patch needs to get Verified +1 vote, typically from Jenkins build bot. This means the patch builds successfully + and all unit tests pass. +#. Commit message should have Signed-off-by line, see :ref:`sign-off` and align with the rest + of the rules for :ref:`commit-message` +#. All the comments need to be addressed, especially if there was a negative vote in the process of review (-1 or -2). +#. flashrom developers are people from literally all around the planet, and various timezones. We usually wait + for 3 days (3 * 24hours) after the patch is fully approved just in case of last minute concerns from all timezones. +#. In the case of emergency, merging should not take place within less than 24 hours after the review + started (i.e. the first message by a reviewer on Gerrit). + +To help search for patches which are potential candidates for merging, you can try using this search in Gerrit:: + + status:open project:flashrom -is:wip -label:Verified-1 label:Verified+1 -label:Code-Review<0 age:3d is:mergeable is:submittable -has:unresolved + +Note the search is not a replacement for Merge checklist, but it can help find candidates for merging. + +.. _bugtracker: + +Bugtracker +========== + +We have a bugtracker on ``_. +Anyone can view tickets, but to be able to create/update/assign tickets you need an account. + +Mirrors +======== + +The only official repository is https://review.coreboot.org/flashrom ; GitHub and GitLab are just mirrors. +**Reviewers do not look at pull requests** on mirrors. +Even if pull requests were automatically transferred to Gerrit, +requirements such as :ref:`sign-off` still present a problem. + +The quickest and best way to get your patch reviewed and merged is by sending +it to review.coreboot.org (see :ref:`working-with-Gerrit`). Conveniently, you can use your GitHub, GitLab or +Google account as an OAuth2 `login method `_. diff --git a/doc/dev_guide/index.rst b/doc/dev_guide/index.rst new file mode 100644 index 000000000..dcd7bd287 --- /dev/null +++ b/doc/dev_guide/index.rst @@ -0,0 +1,9 @@ +Developers documentation +======================== + +.. toctree:: + :maxdepth: 1 + + building_from_source + development_guide + release_process diff --git a/doc/dev_guide/release_process.rst b/doc/dev_guide/release_process.rst new file mode 100644 index 000000000..749779e78 --- /dev/null +++ b/doc/dev_guide/release_process.rst @@ -0,0 +1,100 @@ +=============== +Release process +=============== + +The document describes the technical aspect of making a flashrom release, +and it assumes that the team of active core maintainers is in agreement to commence the process. + +To go through the process, at least two maintainers are needed to be closely involved, +because it includes sending and approving patches in Gerrit. + +Set up the timeline and announce on the mailing list +==================================================== + +Decide on the bug-fixing and testing window (3-4 weeks), decide exact dates of start and end of the window, +and announce it on the mailing list. Ideally make an announcement a few weeks in advance. + +During the testing and bug-fixing window only bug fixes are merged, and no new features are added. +Typically it's fine to push new features for review, and reviews are fine too, +but merging new features will be delayed until the release is done. +*This should be very clearly explained in the announcement.* + +Start testing and bug-fixing window +=================================== + +* Double-check and merge all the patches that are fully ready (see also :ref:`merge-checklist`) + +* Update VERSION file to first release candidate. Check the git history of VERSION file for a version name pattern. + + * As an example at the time of writing, the version name of the first release candidate was ``1.4.0-rc1``. + * To update the VERSION file, push a patch to Gerrit, and another maintainer should review and approve. + +* After submitting the change to the VERSION file, tag this commit. + You can check `flashrom tags in Gerrit `_ + for tag name pattern. As an example at the time of writing, the tag name was ``v1.4.0-rc1``. + +* Write an announcement on the mailing list. Be very clear about: + + * start and end date of the window, and what does it mean + * any help with :ref:`building-and-testing` is very much appreciated + +**From this moment and until the release cut, the highest priority is for building and testing on various environments, and bug-fixing.** + +Release candidates +================== + +If any bugs are found and fixed (or reverted), then the second, or third release candidate will be needed. +The process is the same as with the first candidate: + +* Update the VERSION file, and submit this +* Tag the commit which updates the VERSION file +* Post an announcement on mailing list + +Release notes +============= + +During the time in-between releases, ideally most updates are accumulated in the doc :doc:`/release_notes/devel`. +While this doc is helpful, it is not a replacement for a human to go through all development history +since the previous release and prepare release notes. One maintainer is preparing the release notes +and sending them for review, and at least one other maintainer needs to review that (it can be more than one reviewer). + +Ideally the patch with release notes should be prepared, reviewed and approved before the release cut, +so that it can be published by the time of final release announcement. + +For inspiration to write release notes, have a look at prior art :doc:`/release_notes/index`. + +There is one section in release notes, Download, which is not possible to complete before the actual release cut. +Leave it as TODO, but complete the rest. + +Cut the release +=============== + +Wait for at least a week (or two) since the last release candidate. if everything is alright: + +* Submit the release notes, and in the same patch restart :doc:`/release_notes/devel` document. + This way everyone who is syncing the repository by the release tag will have release notes in the tree. + +* Update VERSION file to release version (for example, at the time of writing ``1.4.0``), and submit this + +* Tag the commit which updates the VERSION file. You can check + `flashrom tags in Gerrit `_ for tag name pattern. + As an example at the time of writing, the tag name was ``v1.4.0``. + +* Create the tarball, sign it, and upload to the server together with the signature. + +* Update release notes with the link to download tarball, signature, and fingerprint. Submit this and check that final release notes are published on the website. + +* Write the release announcement, don't forget to: + + * Link to download the tarball, signature and fingerprint. + * Say thank you to everyone who is helping and supporting flashrom + * Add link to published release notes on the website + +Start the next cycle of development +=================================== + +* Update the VERSION file to the development version. For example, at the time of writing ``1.5.0-devel``, and submit this. + +* Submit all the patches that have been ready and waiting. + +* Celebrate :) diff --git a/doc/documentation_license.rst b/doc/documentation_license.rst new file mode 100644 index 000000000..ebadeb77d --- /dev/null +++ b/doc/documentation_license.rst @@ -0,0 +1,296 @@ +===================== +Documentation license +===================== + +Files under doc/ are licensed under CC-BY 4.0 terms, printed below. + +Attribution 4.0 International +============================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and does not provide +legal services or legal advice. Distribution of Creative Commons public licenses does +not create a lawyer-client or other relationship. Creative Commons makes its licenses +and related information available on an "as-is" basis. Creative Commons gives no warranties +regarding its licenses, any material licensed under their terms and conditions, or any +related information. Creative Commons disclaims all liability for damages resulting from +their use to the fullest extent possible. + +Using Creative Commons Public Licenses +-------------------------------------- + +Creative Commons public licenses provide a standard set of terms and conditions that +creators and other rights holders may use to share original works of authorship and other +material subject to copyright and certain other rights specified in the public license below. +The following considerations are for informational purposes only, are not exhaustive, and do +not form part of our licenses. + +* **Considerations for licensors:** Our public licenses are intended for use by those + authorized to give the public permission to use material in ways otherwise restricted + by copyright and certain other rights. Our licenses are irrevocable. Licensors should + read and understand the terms and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before applying our licenses so that the + public can reuse the material as expected. Licensors should clearly mark any material not + subject to the license. This includes other CC-licensed material, or material used under an + exception or limitation to copyright. `More considerations for licensors `_ + +* **Considerations for the public:** By using one of our public licenses, a licensor grants + the public permission to use the licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason - for example, because of any + applicable exception or limitation to copyright - then that use is not regulated by the + license. Our licenses grant only permissions under copyright and certain other rights that a + licensor has authority to grant. Use of the licensed material may still be restricted for + other reasons, including because others have copyright or other rights in the material. + A licensor may make special requests, such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to respect those requests where + reasonable. `More considerations for the public `_ + +Creative Commons Attribution 4.0 International Public License +============================================================= + +By exercising the Licensed Rights (defined below), You accept and agree to be bound by the +terms and conditions of this Creative Commons Attribution 4.0 International Public License +("Public License"). To the extent this Public License may be interpreted as a contract, You +are granted the Licensed Rights in consideration of Your acceptance of these terms and +conditions, and the Licensor grants You such rights in consideration of benefits the Licensor +receives from making the Licensed Material available under these terms and conditions. + +Section 1 - Definitions. +------------------------ + +\a. **Adapted Material** means material subject to Copyright and Similar Rights that is +derived from or based upon the Licensed Material and in which the Licensed Material is +translated, altered, arranged, transformed, or otherwise modified in a manner requiring +permission under the Copyright and Similar Rights held by the Licensor. For purposes of +this Public License, where the Licensed Material is a musical work, performance, or sound +recording, Adapted Material is always produced where the Licensed Material is synched in +timed relation with a moving image. + +\b. **Adapter's License** means the license You apply to Your Copyright and Similar Rights +in Your contributions to Adapted Material in accordance with the terms and conditions of +this Public License. + +\c. **Copyright and Similar Rights** means copyright and/or similar rights closely related +to copyright including, without limitation, performance, broadcast, sound recording, and +Sui Generis Database Rights, without regard to how the rights are labeled or categorized. +For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not +Copyright and Similar Rights. + +\d. **Effective Technological Measures** means those measures that, in the absence of proper +authority, may not be circumvented under laws fulfilling obligations under Article 11 of +the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. + +\e. **Exceptions and Limitations** means fair use, fair dealing, and/or any other exception or +limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. + +\f. **Licensed Material** means the artistic or literary work, database, or other material to +which the Licensor applied this Public License. + +\g. **Licensed Rights** means the rights granted to You subject to the terms and conditions of +this Public License, which are limited to all Copyright and Similar Rights that apply to Your +use of the Licensed Material and that the Licensor has authority to license. + +\h. **Licensor** means the individual(s) or entity(ies) granting rights under this Public License. + +\i. **Share** means to provide material to the public by any means or process that requires +permission under the Licensed Rights, such as reproduction, public display, public performance, +distribution, dissemination, communication, or importation, and to make material available to +the public including in ways that members of the public may access the material from a place +and at a time individually chosen by them. + +\j. **Sui Generis Database Rights** means rights other than copyright resulting from Directive 96/9/EC +of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, +as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. + +\k. **You** means the individual or entity exercising the Licensed Rights under this Public License. +Your has a corresponding meaning. + +Section 2 - Scope. +------------------ + +\a. **License grant.** + + 1) Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, + royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in + the Licensed Material to: + + \A. reproduce and Share the Licensed Material, in whole or in part; and + + \B. produce, reproduce, and Share Adapted Material. + + 2) **Exceptions and Limitations.** For the avoidance of doubt, where Exceptions and Limitations apply + to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. + + 3) **Term.** The term of this Public License is specified in Section 6(a). + + 4) **Media and formats; technical modifications allowed.** The Licensor authorizes You to exercise + the Licensed Rights in all media and formats whether now known or hereafter created, and to make + technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right + or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, + including technical modifications necessary to circumvent Effective Technological Measures. For purposes + of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. + + 5) **Downstream recipients.** + + \A. **Offer from the Licensor - Licensed Material.** Every recipient of the Licensed Material + automatically receives an offer from the Licensor to exercise the Licensed Rights under the + terms and conditions of this Public License. + + \B. **No downstream restrictions.** You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological Measures to, the Licensed Material if + doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. + + 6) **No endorsement.** Nothing in this Public License constitutes or may be construed as permission + to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or + sponsored, endorsed, or granted official status by, the Licensor or others designated to receive + attribution as provided in Section 3(a)(1)(A)(i). + +\b. **Other rights.** + + 1) Moral rights, such as the right of integrity, are not licensed under this Public License, nor are + publicity, privacy, and/or other similar personality rights; however, to the extent possible, the + Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent + necessary to allow You to exercise the Licensed Rights, but not otherwise. + + 2) Patent and trademark rights are not licensed under this Public License. + + 3) To the extent possible, the Licensor waives any right to collect royalties from You for the exercise + of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable + statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right + to collect such royalties. + +Section 3 - License Conditions. +------------------------------- + +Your exercise of the Licensed Rights is expressly made subject to the following conditions. + +\a. **Attribution.** + + 1) If You Share the Licensed Material (including in modified form), You must: + + \A. retain the following if it is supplied by the Licensor with the Licensed Material: + + \i. identification of the creator(s) of the Licensed Material and any others designated to receive + attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); + + \ii. a copyright notice; + + \iii. a notice that refers to this Public License; + + \iv. a notice that refers to the disclaimer of warranties; + + \v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; + + \B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and + + \C. indicate the Licensed Material is licensed under this Public License, and include the text of, + or the URI or hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, + and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the + conditions by providing a URI or hyperlink to a resource that includes the required information. + + 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to + the extent reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients + of the Adapted Material from complying with this Public License. + +Section 4 - Sui Generis Database Rights. +---------------------------------------- + +Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: + +\a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share +all or a substantial portion of the contents of the database; + +\b. if You include all or a substantial portion of the database contents in a database in which You have +Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its +individual contents) is Adapted Material; and + +\c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the +contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this +Public License where the Licensed Rights include other Copyright and Similar Rights. + +Section 5 - Disclaimer of Warranties and Limitation of Liability. +----------------------------------------------------------------- + +\a. **Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers +the Licensed Material as-is and as-available, and makes no representations or warranties of any kind +oncerning the Licensed Material, whether express, implied, statutory, or other. This includes, without +limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, +absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known +or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may +not apply to You.** + +\b. **To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, +without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, +punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use +of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, +expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation +may not apply to You.** + +\c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, +to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. + +Section 6 - Term and Termination. +--------------------------------- + +\a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You +fail to comply with this Public License, then Your rights under this Public License terminate automatically. + +\b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: + + 1) automatically as of the date the violation is cured, provided it is cured within 30 days of Your + discovery of the violation; or + + 2) upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek + remedies for Your violations of this Public License. + +\c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or +conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. + +\d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. + +Section 7 - Other Terms and Conditions. +--------------------------------------- + +\a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You +unless expressly agreed. + +\b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are +separate from and independent of the terms and conditions of this Public License. + +Section 8 - Interpretation. +--------------------------- + +\a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, +restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without +permission under this Public License. + +\b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be +automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot +be reformed, it shall be severed from this Public License without affecting the enforceability of the +remaining terms and conditions. + +\c. No term or condition of this Public License will be waived and no failure to comply consented to unless +expressly agreed to by the Licensor. + +\d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any +privileges and immunities that apply to the Licensor or You, including from the legal processes of any +jurisdiction or authority. + + Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect + to apply one of its public licenses to material it publishes and in those instances will be considered + the "Licensor". Except for the limited purpose of indicating that material is shared under a + Creative Commons public license or as otherwise permitted by the Creative Commons policies published at + `creativecommons.org/policies `_, Creative Commons does not authorize + the use of the trademark "Creative Commons" or any other trademark or logo of Creative Commons without + its prior written consent including, without limitation, in connection with any unauthorized modifications + to any of its public licenses or any other arrangements, understandings, or agreements concerning use of + licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. + + Creative Commons may be contacted at creativecommons.org diff --git a/doc/how_to_add_docs.rst b/doc/how_to_add_docs.rst new file mode 100644 index 000000000..ee99ce71c --- /dev/null +++ b/doc/how_to_add_docs.rst @@ -0,0 +1,40 @@ +How to add or update docs +========================= + +Documentation files live in ``/doc`` directory in the source tree, so +adding or updating documentation follows the same process as changing +the code. If you've never done it before, start by carefully +reading the :doc:`/dev_guide/development_guide`. + +To add or update a documentation page, you need to create or modify +an ``.rst`` file in the ``/doc`` directory and send a patch for +review. + +People who are registered in MAINTAINERS file for doc/ directory will +be automatically added to the patch as reviewers. However, you are +very welcome to add more reviewers who know the subject. In fact, it +is always a good idea to add someone who has knowledge of the specific +area you are documenting. + +We are using Sphinx doc engine for documentation (see +https://www.sphinx-doc.org/) and reStructured Text format for content. +reStructuredText Primer page has more details +https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#restructuredtext-primer + +Brand new page needs to be added to the appropriate ``index.rst`` file +under ``/doc`` directory (that could be a root index file or nested one). + +To test your changes, build flashrom with documentation and open +generated ``.html`` file in the browser. Generated ``.html`` files are +in meson ``builddir/doc/html`` directory. + +Misc questions +-------------- + +* We use CC-BY-4.0 license for documentation. +* Writing style can be formal or informal, it's mostly up to you, the + important thing is to make the text clear, readable and unambiguous. You + can insert images if this really helps the readers to understand the + instructions. +* Documentation should be relevant to either flashrom usage or flashrom + development diff --git a/doc/how_to_support_flashrom.rst b/doc/how_to_support_flashrom.rst new file mode 100644 index 000000000..7fdfdf84d --- /dev/null +++ b/doc/how_to_support_flashrom.rst @@ -0,0 +1,171 @@ +======================= +How to support flashrom +======================= + +Intro +========= + +This document is for people and companies who want to help flashrom, and it explains +various ways how to do this. + +There are lots of ways to help (as you can see below), whether you have little time or a lot, +whether you are a developer, a user or a company. +flashrom is a free open source software project, and all the contributions are publicly visible - +which means you get all the glory for your work, and you help the whole open source ecosystem. +Thank you! + +flashrom supports a huge variety of environments, platforms and hardware, and there is +no one person or one company on earth which has setup to test and maintain all of these +(and realistically, never will be). The only way we can maintain all of these, +is together as a community. + +To be aware of what's going on, subscribe to our :ref:`mailing list` and/or join our :ref:`real time channels`. + +Development +=========== + +Development, or in other words, sending patches to flashrom, is what probably comes to mind first +when you think about helping and contributing. And indeed, this is a great help, +and patches are always welcome. + +If your idea fits into one patch, you can just send it. If you have bigger plans in mind, +a large amount of work over a longer time frame, the best way is to start a topic on the mailing list. +This helps with planning, and also people in the community, whoever is interested, +will be able to support your effort. + +If you are new to flashrom development process, please start by reading :doc:`/dev_guide/development_guide`. +It's also useful to check `existing patches `_ +for examples on how the dev process works. + +For some types of contributions we have more detailed guidelines, check the list :doc:`/contrib_howtos/index`. + +Code reviews +============ + +Did you know: code reviews are equally important as writing the code! + +For each patch, we need at least one reviewer, and often more than one. +Doing code reviews is highly appreciated and highly respected! +All reviewers' names are immortalised in git history together with authors names, +as "Reviewed-by" and "Signed-off-by" tags in a commit message (see `example `_). + +Code review involves carefully inspecting the patch in Gerrit, and adding comments if anything +is unclear/potential errors/issues/something missing etc. If you think the patch is ready, +you can vote on the patch. Every Gerrit user with a registered account can add comments to patches +and vote +1/-1. Note that if you vote -1, you need to add a comment explaining why you gave a negative vote, +and what specific big issues that you see with the patch. Negative vote is a stronger opinion, +and in most cases just adding comments is enough. + +The group of people who can fully approve the patch (i.e. vote +2, see :doc:`/about_flashrom/team`) +is limited, however every Gerrit user can do code reviews. This increases overall confidence +in the reviewed patch. Approving the patch is much easier when the code reviews are done well. + +You can check pending patches under review `in Gerrit `_ +and help with code review if a patch looks useful, you understand what it is about, and want to have it submitted. + +.. _building-and-testing: + +Building and testing +==================== + +Given the large variety of environments and hardware that flashrom supports, +the question of building and testing flashrom is always relevant. +Try to build flashrom at head on your environment and if it doesn't build, +send a patch to fix (see :doc:`/dev_guide/development_guide`) or file a ticket in :ref:`bugtracker` +with as many details as possible. + +A special case of this is, the time when flashrom team is preparing the release. +The release candidate tag is announced on the mailing list, and it is a great help to try and build and test +a release candidate in whatever your environment is. Both positive and negative results are important, +and you are welcome to share the results, just don't forget to include environment details. +In case of issues, as always: patches are very very welcome. + +Documentation +============= + +You don't have to be a flashrom developer to add, update or review documentation. In fact, +lots of users' docs can greatly benefit from reviews by the users, who are supposed to read and use the docs. +Doc how to update the docs is here: :doc:`/how_to_add_docs` + +As for specific ideas: + +#. If there is an announcement on the mailing list about new doc under review, + have a look and you can join the review + +#. Help migrate information from `old website `_ to `new website `_. + The rule is, all useful docs need to be migrated but they should be reviewed. Concrete example, + there are docs for programmers, written a while ago. If you are using the programmer regularly + you can review the existing doc and help update it (if needed) and then the updated doc will + go to the new website. + +#. New documentation welcome. + +Mailing list +============ + +If you are not subscribed: please subscribe (see :ref:`mailing list`) so you can see what's going on. + +Oftentimes, mailing list has questions from flashrom users. If it so happens +that you maybe know what they are asking, or have ideas about it - you are welcome to respond! +This will be very helpful. + +Similarly, if there is a development discussion that makes sense to you and is relevant: please join the discussion. + +Mailing list is archived, and archives are public and searchable. Which means, +when you respond to the post you not only help that one person who is asking, +but you also help one hundred people in future, who have the same question and can search the answer on the list archives. + +Joining the team +================ + +If you have experience of flashrom development, good knowledge of some of the areas of flashrom code, +some time and motivation, you can consider joining the team, more info here (:doc:`/about_flashrom/team`). +Unlike the previous ideas, this means some *regular* time commitment (the amount of time +can be small or large, but it is regular). + +If you are not at this stage yet, but are considering this as a potential goal for the future, +check the :doc:`/about_flashrom/team` page for what it means. + +Special appeal for companies +============================ + +There are lots of companies that have their own forks of flashrom, and it would be a great help +if you could contribute back to the upstream project! + +Try to keep your fork as close as possible to upstream, do not diverge without a strong reason. +This makes it easier for you to downstream patches, and also makes it easier to contribute patches +from your fork upstream. As an end result, you will be exchanging code and knowledge with a large ecosystem +rather than hiding in your own corner. Working together we can achieve a higher quality bar, +which is better for the upstream project, and better for your fork. + +Consider the following ideas: + +#. Send upstream the bug fixes you found + +#. Add unit tests for the areas you are using actively + +#. Add new features or add support for new platforms/hardware, especially if you have that in your lab + and can reliably test and maintain + +#. Help with releases: if you have an automated test suite, run it on release candidates. + Build and test flashrom for the devices you have in the lab. + +#. If possible, allocate an engineer(s) to contribute to upstream project (and all their work + you can downstream straight away). Upstream early, upstream often: anything you can upstream sooner + will make your life easier in the future. + +#. Have someone subscribed to the mailing list and respond when the topic is relevant to you, + and you have a knowledge of questions or ideas how to help. + +#. On a long term, consider joining the :doc:`/about_flashrom/team`, pick something to maintain: + for example a programmer you are using often + +Outro +======== + +If you read all of the above and still unsure what to do, but actually want to help, +please don't be afraid to ask flashrom project lead directly (Anastasia Klimchuk, +and you can find email in `Gerrit `_ +or tag aklm on Discord (see :ref:`real time channels`). + +**Every bit of help matters and you can help make flashrom a better place. Thank you!** diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 000000000..f32f18298 --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,27 @@ +.. flashrom documentation master file, created by + sphinx-quickstart on Mon Jan 30 17:34:19 2023. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +.. image:: logo/flashrom_logo.png + :alt: flashrom logo + +.. toctree:: + :hidden: + + dev_guide/index + user_docs/index + contrib_howtos/index + supported_hw/index + classic_cli_manpage + contact + release_notes/index + about_flashrom/index + how_to_support_flashrom + how_to_add_docs + documentation_license + Old wiki website + +.. include:: intro.rst + +.. include:: ../README.rst diff --git a/doc/intro.rst b/doc/intro.rst new file mode 100644 index 000000000..92bcac533 --- /dev/null +++ b/doc/intro.rst @@ -0,0 +1,44 @@ +**flashrom** is a utility for identifying, reading, writing, verifying and erasing flash +chips. It is designed to flash BIOS/EFI/coreboot/firmware/optionROM images on mainboards, +network/graphics/storage controller cards, and various other programmer devices. + +* Supports more than 627 flash chips, 407 chipsets, 539 mainboards, 94 PCI devices, + 30 USB devices and various parallel/serial port-based programmers. + For more information, see the pages under :doc:`/supported_hw/index`. + +* Supports parallel, LPC, FWH and SPI flash interfaces and various chip packages (DIP32, + PLCC32, DIP8, SO8/SOIC8, TSOP32, TSOP40, TSOP48, BGA and more), see :doc:`user_docs/overview`. + +* No physical access needed, root access is sufficient (not needed for some programmers). + +* No bootable floppy disk, bootable CD-ROM or other media needed. + +* No keyboard or monitor needed. Simply reflash remotely via SSH. + +* No instant reboot needed. Reflash your chip in a running system, verify it, be happy. + The new firmware will be present next time you boot. + +* Crossflashing and hotflashing is possible as long as the flash chips are electrically + and logically compatible (same protocol). Great for recovery. + +* Scriptability. Reflash a whole pool of identical machines at the same time from the + command line. It is recommended to check flashrom output and error codes. + +* Speed. flashrom is often much faster than most vendor flash tools. + +* Portability. Supports DOS, Linux, FreeBSD (including Debian/kFreeBSD), NetBSD, OpenBSD, + DragonFlyBSD, anything Solaris-like, Mac OS X, and other Unix-like OSes as well as GNU Hurd. + Partial Windows support is available (no internal programmer support at the moment, hence + no "BIOS flashing"). + +.. todo:: Convert Technology page and add links here + +.. container:: danger, admonition + + **Emergency help** + + IMPORTANT: If something went wrong during flashing, do NOT turn off/reboot your computer. + Instead, let us help you recover. We can be contacted via `IRC `_ + (#flashrom on `libera.chat `_, `webchat `_), + `Discord `_, or `email `_. + Please allow some time until someone responds, we're all volunteers. diff --git a/doc/logo/COPYING b/doc/logo/COPYING new file mode 100644 index 000000000..3a7d190ce --- /dev/null +++ b/doc/logo/COPYING @@ -0,0 +1,12 @@ +The flashrom logo and icons in this directory were originally designed by Stefan Tauner in 2015. +The lettering is based on the "Free Mono" font of the GNU FreeFont family. +The SOIC chip seen in the lettering is based on the SOIC08 narrow STL CAD file from +https://grabcad.com/library/soic-package-narrow-8-10-14-and-16-pins-1 +It was rendered by Blender with the Freestyle SVG plugin from +https://github.com/hvfrancesco/freestylesvg + +All source image files within this directory (i.e. all with names ending with ".svg" or ."xcf") +are licensed under the Creative Commons Attribution-NoDerivatives 4.0 license (CC BY-ND 4.0): +http://creativecommons.org/licenses/by-nd/4.0/ +All image files produced from the source image files mentioned above and included in this +directory are in the public domain. diff --git a/doc/logo/flashrom_icon_bw.svg b/doc/logo/flashrom_icon_bw.svg new file mode 100644 index 000000000..e19996e41 --- /dev/null +++ b/doc/logo/flashrom_icon_bw.svg @@ -0,0 +1,184 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/logo/flashrom_icon_color-128x128.png b/doc/logo/flashrom_icon_color-128x128.png new file mode 100644 index 000000000..0c1f50caf Binary files /dev/null and b/doc/logo/flashrom_icon_color-128x128.png differ diff --git a/doc/logo/flashrom_icon_color-16x16.ico b/doc/logo/flashrom_icon_color-16x16.ico new file mode 100644 index 000000000..6c8c777db Binary files /dev/null and b/doc/logo/flashrom_icon_color-16x16.ico differ diff --git a/doc/logo/flashrom_icon_color-16x16.png b/doc/logo/flashrom_icon_color-16x16.png new file mode 100644 index 000000000..fd977bb64 Binary files /dev/null and b/doc/logo/flashrom_icon_color-16x16.png differ diff --git a/doc/logo/flashrom_icon_color-16x16.xcf b/doc/logo/flashrom_icon_color-16x16.xcf new file mode 100644 index 000000000..5a2785b9d Binary files /dev/null and b/doc/logo/flashrom_icon_color-16x16.xcf differ diff --git a/doc/logo/flashrom_icon_color-256x256.png b/doc/logo/flashrom_icon_color-256x256.png new file mode 100644 index 000000000..62d0b080b Binary files /dev/null and b/doc/logo/flashrom_icon_color-256x256.png differ diff --git a/doc/logo/flashrom_icon_color-32x32.ico b/doc/logo/flashrom_icon_color-32x32.ico new file mode 100644 index 000000000..d070e70a1 Binary files /dev/null and b/doc/logo/flashrom_icon_color-32x32.ico differ diff --git a/doc/logo/flashrom_icon_color-32x32.png b/doc/logo/flashrom_icon_color-32x32.png new file mode 100644 index 000000000..d400d9a02 Binary files /dev/null and b/doc/logo/flashrom_icon_color-32x32.png differ diff --git a/doc/logo/flashrom_icon_color-32x32.xcf b/doc/logo/flashrom_icon_color-32x32.xcf new file mode 100644 index 000000000..16c5e3907 Binary files /dev/null and b/doc/logo/flashrom_icon_color-32x32.xcf differ diff --git a/doc/logo/flashrom_icon_color-64x64.png b/doc/logo/flashrom_icon_color-64x64.png new file mode 100644 index 000000000..1ee7d55c0 Binary files /dev/null and b/doc/logo/flashrom_icon_color-64x64.png differ diff --git a/doc/logo/flashrom_icon_color-64x64.xcf b/doc/logo/flashrom_icon_color-64x64.xcf new file mode 100644 index 000000000..7c1d7503e Binary files /dev/null and b/doc/logo/flashrom_icon_color-64x64.xcf differ diff --git a/doc/logo/flashrom_icon_color.svg b/doc/logo/flashrom_icon_color.svg new file mode 100644 index 000000000..07f0fc683 --- /dev/null +++ b/doc/logo/flashrom_icon_color.svg @@ -0,0 +1,186 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/logo/flashrom_icon_gray.svg b/doc/logo/flashrom_icon_gray.svg new file mode 100644 index 000000000..f334b4455 --- /dev/null +++ b/doc/logo/flashrom_icon_gray.svg @@ -0,0 +1,183 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/logo/flashrom_logo.png b/doc/logo/flashrom_logo.png new file mode 100644 index 000000000..6f201a868 Binary files /dev/null and b/doc/logo/flashrom_logo.png differ diff --git a/doc/logo/flashrom_logo.svg b/doc/logo/flashrom_logo.svg new file mode 100644 index 000000000..b4ee6b75f --- /dev/null +++ b/doc/logo/flashrom_logo.svg @@ -0,0 +1,199 @@ + + + + + + + + + + image/svg+xml + + + + + + + + fla hrom + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/meson.build b/doc/meson.build new file mode 100644 index 000000000..5bc57b995 --- /dev/null +++ b/doc/meson.build @@ -0,0 +1,37 @@ + +sphinx = find_program('sphinx-build', native : true, required : get_option('man-pages').enabled() or get_option('documentation').enabled()) +sphinx_wrapper = meson.current_source_dir() / 'sphinx-wrapper.sh' + +man_pages = [ + 'flashrom.8' +] + +if sphinx.found() + if get_option('man-pages').auto() or get_option('man-pages').enabled() + man_outputs = [] + foreach page : man_pages + man_outputs += 'man' + page.substring(-1) + endforeach + + custom_target( + 'man-pages', + command : [sphinx_wrapper, '@OUTDIR@', ' '.join(man_outputs), sphinx, '-b', 'man', '-q', '-d', '@PRIVATE_DIR@', '-Drelease=' + flashrom_version, '@CURRENT_SOURCE_DIR@', '@OUTDIR@'], + build_always_stale : true, # sphinx handles rebuilds + output : man_outputs, + install : true, + install_dir : get_option('mandir'), + ) + endif + + if get_option('documentation').auto() or get_option('documentation').enabled() + custom_target( + 'documentation', + command : [sphinx, '-b', 'html', '-q', '-d', '@PRIVATE_DIR@', '-Drelease=' + flashrom_version,'@CURRENT_SOURCE_DIR@', '@OUTDIR@/html'], + build_always_stale : true, # sphinx handles rebuilds + output : 'html', + install : true, + install_dir : get_option('datadir') + '/doc/flashrom' + ) + endif + +endif diff --git a/doc/release_notes/devel.rst b/doc/release_notes/devel.rst new file mode 100644 index 000000000..919d36401 --- /dev/null +++ b/doc/release_notes/devel.rst @@ -0,0 +1,37 @@ +=============================== +Recent development (unreleased) +=============================== + +This document describes the major changes that are expected to be included in +the next release of flashrom and which are currently only available by source +code checkout (see :doc:`../dev_guide/building_from_source`). These changes +may be further revised before the next release. + +Known issues +============ + +AMD-based PCs with FCH are unable to read flash contents for internal (BIOS +flash) chips larger than 16 MB, and attempting to do so may crash the system. +Systems with AMD "Promontory" IO extenders (mostly "Zen" desktop platforms) are +not currently supported. + +https://ticket.coreboot.org/issues/370 + +Build only supported with Meson +=============================== + +As documented in the :doc:`v1.4 release notes `, support for building +flashrom with make has been removed; all Makefiles have been deleted. Meson is +now the only supported tool for building flashrom from source. + +New Feature +=========== +Libpci 3.13.0 and onwards support ECAM to access pci registers. Flashrom will +be moved to ECAM from IO port 0xcf8/0xcfc if the libpci version is >= 3.13.0. +The ECAM has been supported for a very long time, most platforms should support +it. For those platforms don't support ECAM, libpci will terminate the process by +exit. + +Chipset support +=============== +Added Raptor Point PCH support. diff --git a/doc/release_notes/index.rst b/doc/release_notes/index.rst new file mode 100644 index 000000000..fe12d346b --- /dev/null +++ b/doc/release_notes/index.rst @@ -0,0 +1,9 @@ +Release notes +============= + +.. toctree:: + :maxdepth: 1 + + devel + v_1_4 + v_1_3 diff --git a/doc/release_notes/v_1_3.rst b/doc/release_notes/v_1_3.rst new file mode 100644 index 000000000..d72256653 --- /dev/null +++ b/doc/release_notes/v_1_3.rst @@ -0,0 +1,214 @@ +=============== +v1.3 (Feb 2023) +=============== + +It has been almost three years since our last release. All this time we have been working +on enhancing the flashrom code base. This new release comes with a lot of new features, programmers, +improvements, and bug fixes. A detailed but not exhaustive change log is presented below. + +New major user-visible features +=============================== + +* Support for the Linux I2C subsystem +* Option to read/write only region to/from ROM is renamed to :code:`--include` (:code:`--image` option + is deprecated and exist only for back compatibility). An optional sub-parameter + (:code:`--include [:]`) to allow building the image to be written from multiple files is added +* Support different SPI modes (Dual IO, Quad IO, Normal, Fast Read) for AMD’s chipsets (>= Bolton) +* Support for Write Protection configuration (:code:`--wp-disable`, :code:`--wp-enable`, :code:`--wp-list`, + :code:`--wp-status`, :code:`--wp-range`, :code:`--wp-region`) +* Add SPI SR2/SR3 read/write support +* The Intel chipset detection has been improved +* Bus Pirate SPI + + * New parameter to control the external Vcc state (:code:`psus=`) + +* Dediprog + + * Add 4BA support on SF600 protocol version 3 + +* Dummyflasher + + * New parameter to allows emulating a bus/chip frequency (:code:`freq`) + * New parameter to emulate flash erase with either 0x00 or 0xff (:code:`erase_to_zero`) + * Add emulation for S25FL128L chip + * SR2, SR3 and WP is emulated for W25Q128FV + * Emulate variable-size SPI flash chip (4-byte address format is supported) + +* FT2232 SPI dongles + + * New parameter to search FTDI by description, i.e. product string (:code:`description`) + +* SEGGER J-Link and compatible devices + + * New parameter to active the 5V power supply during a flash operation (:code:`power`) + +* Drop "Promontory" architecture (AMD) support +* End Of Life (EOL) for ITE IT85* specific code +* README and man page updated with additional information + +The greatest increase in the speed of operations can be seen on the following programmers: +SPI on Intel NICs, FT2232 SPI dongles + +Libflashrom +=========== + +* Add Write Protect functions to the API +* Add rust Foreign Function Interface bindings for the libflashrom API +* Move documentation from source file to header +* Drop :code:`flashrom_system_info()` +* Drop :code:`flashrom_supported_programmers()` +* Add :code:`flashrom_layout_get_region_range()` +* Declaration change from :code:`flashrom_layout_read_fmap_from_rom(struct flashrom_layout **const, struct flashctx *const, off_t, size_t)` + to :code:`flashrom_layout_read_fmap_from_rom(struct flashrom_layout **const, struct flashctx *const, size_t, size_t)` +* Allow NULL-pointer argument in :code:`flashrom_flash_release()` + +Infrastructure expansion +======================== + +* Add blackbox test uber-script +* Add E2E tester for a specific chip/chipset combo +* Build script for Jenkins was upgraded and move to repository - :code:`test_build.sh` +* Add a set of Dockerfiles for build testing - :code:`util/manibuilder` +* Add a Nix shell file which is able to compile flashrom - :code:`util/shell.nix` +* Add CMocka unit-test infrastructure into the meson build system (test for drivers available only + if its driver is built). The following tests are included: + + * Core logic tests + * Basic lifecycle for :code:`dediprog`, :code:`nicrealtek`, :code:`raiden_debug_spi`, :code:`parade_lspcon`, + :code:`mediatek_i2c_spi`, :code:`realtek_mst_i2c_spi` + * Basic lifecycle + chip probe for :code:`dummyflasher`, :code:`linux_mtd`, :code:`linux_spi` + * Layout tests (overlapping, sanity checks, invalid range/address) + * Erasing/reading/writing/verifying chip tests + * Write Protect tests + * And others! + +* Introduce :code:`MAINTAINERS` file +* Rename :code:`z60_flashrom.rules` to :code:`flashrom_udev.rules` +* Introduce linter for git sign-off-by line +* Move all header files to the new :code:`include` directory. + +Meson +----- + +The minimum version has been increased. Requires at least :code:`0.53.0`. + +* Added build instructions - :code:`Documentation/building.md` +* Allow libflashrom to be built as a static or shared library. +* Add new options: :code:`print_wiki`, :code:`ich_descriptors_tool`, :code:`classic_cli` +* Rename :code:`print_wiki` to :code:`classic_cli_print_wiki` option +* Install the man file +* Fix compilation under uClibc-ng +* Add missing config option for J-Link SPI +* Treat warnings as errors and use the same warning options as in Makefile. + +Makefile +-------- + +* Add support for Elbrus (e2k) architecture +* Make pkg-config mandatory to find :code:`libftdi1`, :code:`libjaylink`, + :code:`libusb1`, :code:`libpci` + (you still can override detection and set cflags and ldflags manually) +* Merge :code:`compiler`, :code:`hwlibs`, :code:`features` targets into :code:`config` target +* Drop :code:`distclean` target +* Drop STANDALONE mode +* Summarize systems with the same CPPFLAGS and LDFLAGS +* Only enable I2C programmers on Linux (linux-specific code) +* Revise C compiler check, utsname and clock_gettime test, detection of Linux specific headers +* Since the NI-845x is a Windows only proprietary library, disable it by default. +* Enable the internal programmer on x86 or linux. +* Fix building on AArch64 NixOS + +Various broken and missing dependencies have been fixed for these two build systems. + +New programmers +=============== + +* Chrome EC based debug tools - SuzyQable, Servo V4, C2D2 & uServo +* Realtek RTD2142 MST +* Parade lspcon USB-C to HDMI protocol translator +* DirtyJTAG (a USB-JTAG firmware for STM32 MCUs) +* MediaTek LCD controller +* Programmers based on FT4233H FTDI +* Kristech KT-LINK +* Variants of STLINK-V3: STLINK-V3E, STLINK-V3S, STLINK-V3 With dual VCP, STLINK-V3 Without MSD +* Intel Gemini Lake PCH +* Intel Meteor Lake PCH +* Intel Elkhart Lake PCH +* Intel Emmitsburg PCH +* Intel Comet Lake-U/400-series PCH +* Intel Tiger Point/500-series PCH +* Intel Jasper Lake PCH +* Intel Alder Lake/600-series PCH +* Intel PCH7 Desktop/Mobile/SFF Sample +* More Intel PCHs variants (Apollo Lake, Cannon Point, Union Point, Lewisburg) + +At some point, flashrom supported ENE LPC interface keyboard controller and Microchip MEC1308 embedded controller. +But they were dropped before the release because the code was no longer maintained by anyone. If you're interested, +take a look at git history. + +New Boards +========== + +* ASUS P3B-F +* Jetway P4MDPT +* ASUS P5W DH Deluxe + +New chips +========= + +* AT25SF128A +* B.25D16A +* BY25Q128AS +* FM25F01 +* FM25F02(A) +* FM25F04(A) +* FM25F005 +* FM25Q08 +* FM25Q16 +* FM25Q32 +* F29C51001B +* GD25LQ128E +* GD25Q256E +* GD25WQ80E +* MX25L12833F +* MX25L12873F +* MX25L3233F +* MX25L5121E +* MX25R3235F +* MX66L1G45G +* S25FL128L +* S25FL128S +* S25FL129P +* S25FL256L +* S25FL256S +* S25FS128S +* S29C51001B +* V29C51001B +* W25Q32JW...M +* W25Q64JV +* W25Q64JW...M +* W25Q256JW +* W25Q256JW_DTR +* W25Q512JV +* W25Q512NW-IM +* W25X05(CL) +* XM25QU64C +* XM25QU128C +* XM25QU256C +* XM25QH64C +* XM25QH128C +* XM25QH256C + +Download +======== + +flashrom 1.3 can be downloaded in various ways: + +Anonymous checkout from the git repository at ``_ (tag v1.3.0) + +A tarball is available for download at + +``_ (GPG signature), +fingerprint: :code:`6E6E F9A0 BA47 8006 E277 6E4C C037 BB41 3134 D111` + +and more in the "Tags" section of CGit at ``_ diff --git a/doc/release_notes/v_1_4.rst b/doc/release_notes/v_1_4.rst new file mode 100644 index 000000000..d05420526 --- /dev/null +++ b/doc/release_notes/v_1_4.rst @@ -0,0 +1,329 @@ +================ +v1.4 (July 2024) +================ + +This document describes the major changes in flashrom version 1.4.0, +from more than 400 patches contributed by more than 70 authors (thank you!) +in the 18 months since version 1.3.0 was branched. + +Download +======== + +flashrom 1.4 can be downloaded in various ways: + +Anonymous checkout from the git repository at https://review.coreboot.org/flashrom.git +(tag v1.4.0) + +A tarball is available for download at +https://download.flashrom.org/releases/flashrom-1.4.0.tar.xz +(signature https://download.flashrom.org/releases/flashrom-1.4.0.tar.xz.asc) + +fingerprint: 6E6E F9A0 BA47 8006 E277 6E4C C037 BB41 3134 D111 + +Known issue +=========== + +AMD-based PCs with FCH are unable to read flash contents for internal (BIOS flash) +chips larger than 16 MB, and attempting to do so may crash the system. +Systems with AMD "Promontory" IO extenders (mostly "Zen" desktop platforms) are not currently +supported. + +https://ticket.coreboot.org/issues/370 + +Major updates +============= + +Optimised erase and write logic +------------------------------- + +Significant performance improvements with new logic which is based on: +the optimal selection of erase blocks for the given logical layout, +available erase functions, and size of memory area to erase/write. + +**Legacy code path still exists in the source tree, but it will be deleted by the next release.** + +Optimised delays logic +---------------------- + +Optimised logic and refactorings of delays functionality, in particular for SPI chips. + +* Flashrom now sleeps more aggressively when a delay is required, rather than + polling in a loop. This should reduce power consumption significantly, but + may require more time to complete operations on systems experiencing high + CPU load. +* An unconditional 1-second delay was removed for SPI flashes. This is not + believed to be needed for any SPI flashes, but may be needed for some old + parallel flashes (where it remains in use). +* Cycle-counting busy loops are now only used on DOS builds of flashrom. All + other platforms use OS timers for timed delays, which are expected to be + more accurate. +* Tree-wide refactorings around programmer_delay and internal_delay + +Documentation is in the git tree +-------------------------------- + +Docs are available in the same repository as the code, in ``doc/`` directory. + +Website content is automatically generated from docs in the git tree. + +**Patches with code changes and new features can (and should) update documentation +in the same patch, which makes it a lot easier to maintain up-to-date docs.** + +Note: the migration process for documents from flashrom wiki to the git tree is half way. +Wiki is deprecated now, and will go away once the migration process complete. + +Makefile scheduled for removal +------------------------------ + +**Future versions of flashrom will drop support for building via Makefile**: +Meson will become the only supported build system. + +The Makefile and meson build systems are currently at feature parity, +except automated testing is supported only with meson. +To reduce the maintenance burden, we plan to remove the Makefile after this release. + +Write-protect updates +--------------------- + +* Support reading security register +* Support reading/writing configuration register +* More range functions (with different block sizes and handling of CMP bit) + +Protected regions support +------------------------- + +* Support to allow programmers to handle protected regions on the flash. +* get_region() function is added so that programmers can expose access permissions + for multiple regions within the flash. +* A get_region() implementation is added for the ichspi driver + +Chipset support added +===================== + +* Tiger Lake +* Emmitsburg Chipset SKU +* Meteor Lake-P/M +* Panther Lake-U/H 12Xe +* Panther Lake-H 4Xe + +Chip models support added or updated +==================================== + +New models support +------------------ + +* AT25DF011 + +* B.25D80A +* B25Q64AS + +* GD25LB128E/GD25LR128E +* GD25LB256E +* GD25LF128E +* GD25Q127C/GD25Q128E +* GD25LQ255E +* GD25LR256E +* GD251R512ME + +* IS25LP016 +* IS25LQ016 +* IS25WP016 +* IS25WP020 +* IS25WP040 +* IS25WP080 +* IS25WQ040 + +* MX25L1633E +* MX25L1636E +* MX25L3239E +* MX25L3255E +* MX25L3273F +* MX25L6473F +* MX25L6436E/MX25L6445E/MX25L6465E +* MX25L6473E +* MX25L12850F +* MX77L25650F +* MX25R2035F +* MX25R4035F +* MX25R8035F +* MX25U25643G +* MX25V16066 + +* P25Q06H +* P25Q11H +* P25Q21H + +* W25Q16JV_M + +* XM25QH128A +* XM25QH80B +* XM25QH16C/XM25QH16D +* XM25QU80B +* XM25RU256C + +* XT25F02E +* XT25F64B +* XT25F128B + +* ZD25D20 + +Added write-protect support +--------------------------- + +* EN25QH32 +* EN25QH64 + +* MX25L3206E/MX25L3208E +* MX25L6405 +* MX25L6405D +* MX25L6406E/MX25L6408E +* MX25L12833F +* MT25QL512 +* MX25R1635F +* MX25R1635F +* MX25U25643G +* MX25V1635F +* MX25V4035F +* MX25V8035F + +* N25Q032..1E +* N25Q032..3E +* N25Q064..1E +* N25Q064..3E + +* W25Q16.V +* W25Q32BV/W25Q32CV/W25Q32DV +* W25Q32FV +* W25Q32JV +* W25Q32BW/W25Q32CW/W25Q32DW +* W25Q32FW +* W25Q32JW...Q +* W25Q32JW...M +* W25Q64JW...M +* W25Q256JW_DTR +* W25Q512NW-IM +* W25X05 +* W25X10 +* W25X16 +* W25X20 +* W25X32 +* W25X40 +* W25X64 +* W25X80 + +Marked as tested +---------------- + +* AM29LV040B + +* AT29C010A + +* FM25F01 +* FM25Q16 + +* MT25QL128 + +* S25FL128L + +* W25Q128.V + +* XM25QH64C +* XM25QH256C +* XM25QU256C + +Programmers support added or updated +==================================== + +* New programmer for ASM106x SATA controllers +* New programmer for WCH CH347, supports CH347T and CH347F packaging. + +* buspirate: Add option for setting the aux pin +* jlink_spi: add cs=tms option to jlink_spi programmer +* raiden: Support target index with generic REQ_ENABLE +* buspirate_spi: add support for hiz output with pullups=off +* serprog: Add support for multiple SPI chip selects + +Utilities +========= + +* Bash completion (enabled by default with command line interface) + +* CI checks for Signed-off-by line in commit message + +* CI builds documentation + +Unit tests +========== + +Added coverage for erase and write logic +---------------------------------------- + +20 test cases for each operation, with various logical layouts and chip memory states, +and additional 6 for each, with protected regions configured. +The test for erase and write is set up so that new test cases can be added whenever needed. + +selfcheck +--------- + +selfcheck is now also implemented as a unit test. + +selfcheck provides critical sanity checks for the programmer table, board matches table, +and array of flashchip definitions. + +Note that selfcheck currently, by default, still runs on flashrom init, +because at the moment we can't run unit tests on all supported platforms, +and we don't have continuous integration for all platforms. + +This gives an opportunity for performance improvement for developers or companies +who build their own flashrom binary and, importantly, +can run unit tests with the build (Linux, BSD). +For their own binary, it is possible to disable selfcheck on init and save some time +(**under their own responsibility to run unit tests**). + +Coverage report +--------------- + +Unit tests coverage report can be generated with gcov or lcov / llvm. + +ch341a_spi test +--------------- + +Unit test which covers initialization-probing-shutdown of ch341a_spi. + +Reduces the risk of breakage for the very popular programmer. + +Write-protect +------------- + +Added coverage for write-protect operation + +Some of the other misc fixes and improvements +============================================= + +* bitbang_spi.c: Fix unchecked heap allocation +* writeprotect.c: skip unnecessary writes +* writeprotect.c: refuse to work with chip if OTP WPS == 1 +* flashrom.c: Drop redundant chip read validation in verify_range() +* ichspi: Clear Fast SPI HSFC register before HW seq operation +* ichspi: Fix number of bytes for HW seq operations +* writeprotect,ichspi,spi25: handle register access constraints +* tree/: Make heap alloc checks err msg consistent +* flashrom.c: Replace 'exit(1)' leaks with return codes on err paths +* flashrom: Check for flash access restricitons in read_flash() +* flashrom: Check for flash access restricitons in verify_range() +* flashrom: Check for flash access restricitons in write_flash() +* flashrom: Check for flash access restrictions in erase path +* flashrom: Use WP-based unlocking on opaque masters +* ni845x_spi: Fix signed - unsigned comparisons +* flashrom: only perform WP unlock for write/erase operations +* tree: Rename master branch to main +* serial: Fix sp_flush_incoming for serprog TCP connections +* Makefile,meson.build: Add support for Sphinx versions prior to 4.x +* Makefile: Fix cleanup for Sphinx versions prior to 4.x +* Makefile: Fix version string for non-Git builds +* serprog protocol: Add SPI Mode and CS Mode commands +* util/list_yet_unsupported_chips.h: Fix path +* flashrom_udev.rules: Add rule for CH347 +* Add documentation for pico-serprog +* cli_classic: Defer flashrom_init calibration until after options parsing +* hwaccess_x86_io: Fix Android compilation with bionic libc diff --git a/doc/sphinx-wrapper.sh b/doc/sphinx-wrapper.sh new file mode 100755 index 000000000..5569638a5 --- /dev/null +++ b/doc/sphinx-wrapper.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +OUTPUT_HOME="$1" +MAN_OUTPUTS="$2" +SPHINXBUILD="$3" +shift 3 + +"${SPHINXBUILD}" "$@" || exit $? + +SPHINXBUILD_MAJOR="$("${SPHINXBUILD}" --version | cut -d' ' -f2 | cut -d'.' -f1)" +if [ "${SPHINXBUILD_MAJOR}" -ge 4 ]; then + exit 0 +fi + +# sphinx-build 3.x outputs man pages to "8" directory instead of expected "man8". +# The following block checks for "man8" (and other output paths in ${MAN_OUTPUTS}) +# and, if that is missing, but "8" dir exists instead, it renames "8" to "man8" +# and creates a symlink named "8" that points to "man8", so that anyone is happy +# during the rest of current build and subsequent builds as well. + +for MAN_OUTPUT in ${MAN_OUTPUTS}; do + PATH_TARGET="${OUTPUT_HOME}/${MAN_OUTPUT}" + PATH_ACTUAL="${OUTPUT_HOME}/${MAN_OUTPUT#man}" + if [ -d "${PATH_ACTUAL}" -a ! -L "${PATH_ACTUAL}" ]; then + rm -rf "${PATH_TARGET}" + mv "${PATH_ACTUAL}" "${PATH_TARGET}" + ln -s "${MAN_OUTPUT}" "${PATH_ACTUAL}" + fi +done diff --git a/doc/supported_hw/index.rst b/doc/supported_hw/index.rst new file mode 100644 index 000000000..eebf39406 --- /dev/null +++ b/doc/supported_hw/index.rst @@ -0,0 +1,11 @@ +================== +Supported hardware +================== + +.. toctree:: + :maxdepth: 1 + + supported_flashchips + supported_prog/index + supported_chipsets + supported_boards diff --git a/doc/supported_hw/supported_boards.rst b/doc/supported_hw/supported_boards.rst new file mode 100644 index 000000000..91b2899df --- /dev/null +++ b/doc/supported_hw/supported_boards.rst @@ -0,0 +1,19 @@ +======================== +Supported boards/laptops +======================== + +To see the list of all supported boards or laptops, check either ``struct board_info boards_known[]`` or ``struct board_info laptops_known[]`` +in the ``known_boards.c`` file in the source tree. + +If you have a flashrom repo cloned locally, you can look at the file in your repo, alternatively inspect the file +`on the web UI of our GitHub mirror `_. + +If you can run flashrom locally, the command ``flashrom -L`` prints the list of all supported boards and laptops +(see :doc:`/classic_cli_manpage` for more details on command line options). The output of this command is long, so you might +want to save it to file or grep. + +Each board entry is described by the ``struct board_info`` in ``include/programmer.h`` which you can inspect in the same way, either in the local source tree or +`in the GitHub web UI `_. + +Note the ``enum test_state status`` of the board. ``OK`` means board is tested, ``NT`` means not tested, to see all possible +test states check the ``enum test_state`` definition in ``include/flash.h``. diff --git a/doc/supported_hw/supported_chipsets.rst b/doc/supported_hw/supported_chipsets.rst new file mode 100644 index 000000000..ca7dc8fab --- /dev/null +++ b/doc/supported_hw/supported_chipsets.rst @@ -0,0 +1,21 @@ +================== +Supported chipsets +================== + +To see the list of all supported chipsets, check the ``const struct penable chipset_enables[]`` in ``chipset_enable.c`` file in the source tree. +If you have a flashrom repo cloned locally, you can look at the file in your repo. + +Alternatively inspect the file `on the web UI of our GitHub mirror `_. + +If you can run flashrom locally, the command ``flashrom -L`` prints the list of all supported chipsets +(see :doc:`/classic_cli_manpage` for more details on command line options). The output of this command is long, so you might +want to save it to file or grep. + +Each chipset entry is described by ``struct penable`` in ``include/programmer.h`` which you can inspect in the same way, either in the local source tree or +`in the GitHub web UI `_. + +Note the ``enum test_state status`` of the chipset. ``OK`` means chipset is tested, ``NT`` means not tested, to see all possible +test states check the ``enum test_state`` definition in ``include/flash.h``. + +Also note that macros for supported buses are defined in ``chipset_enable.c`` right before ``chipset_enables[]`` array. +For example ``B_S`` means ``BUS_SPI``, check the ``chipset_enable.c`` source code for the rest of macro definitions. diff --git a/doc/supported_hw/supported_flashchips.rst b/doc/supported_hw/supported_flashchips.rst new file mode 100644 index 000000000..8e881d2ea --- /dev/null +++ b/doc/supported_hw/supported_flashchips.rst @@ -0,0 +1,26 @@ +===================== +Supported flash chips +===================== + +The list of all supported flash chips is in ``flashchips.c`` file in the source tree. +If you have a flashrom repo cloned locally, you can look at the file in your repo. + +Alternatively inspect the file on the `web UI of our GitHub mirror `_. + +If you can run flashrom locally, the command ``flashrom -L`` prints the list of all supported flash chips +(see :doc:`/classic_cli_manpage` for more details on command line options). The output of this command is long, so you might +want to save it to file or grep. + +If you want to check whether a flash chip is supported in the given release, you can rebase your local +repo at the release tag, alternatively select a tag/branch in GitHub web UI (dropdown on the top-left). + +Each chip definition is described by a ``struct flashchip`` in ``include/flash.h``, which you can inspect in the same way, +either in local source tree or on GitHub web UI. + +Note the ``.tested`` status of the chip. If the status is ``TEST_UNTESTED`` this means chip definition has been added purely based on +datasheet, but without testing on real hardware. + +Related documents: + + * :doc:`/contrib_howtos/how_to_mark_chip_tested`. + * :doc:`/contrib_howtos/how_to_add_new_chip`. diff --git a/doc/supported_hw/supported_prog/ARM-USB-TINY_pinout.png b/doc/supported_hw/supported_prog/ARM-USB-TINY_pinout.png new file mode 100644 index 000000000..aa95a59b8 Binary files /dev/null and b/doc/supported_hw/supported_prog/ARM-USB-TINY_pinout.png differ diff --git a/doc/supported_hw/supported_prog/Buspirate_v3_back.jpg b/doc/supported_hw/supported_prog/Buspirate_v3_back.jpg new file mode 100644 index 000000000..3afb97458 Binary files /dev/null and b/doc/supported_hw/supported_prog/Buspirate_v3_back.jpg differ diff --git a/doc/supported_hw/supported_prog/Buspirate_v3_front.jpg b/doc/supported_hw/supported_prog/Buspirate_v3_front.jpg new file mode 100644 index 000000000..3c4fa9c22 Binary files /dev/null and b/doc/supported_hw/supported_prog/Buspirate_v3_front.jpg differ diff --git a/doc/supported_hw/supported_prog/Dlp_usb1232h_bottom.jpg b/doc/supported_hw/supported_prog/Dlp_usb1232h_bottom.jpg new file mode 100644 index 000000000..5ebf9b72c Binary files /dev/null and b/doc/supported_hw/supported_prog/Dlp_usb1232h_bottom.jpg differ diff --git a/doc/supported_hw/supported_prog/Dlp_usb1232h_side.jpg b/doc/supported_hw/supported_prog/Dlp_usb1232h_side.jpg new file mode 100644 index 000000000..0a17f6e03 Binary files /dev/null and b/doc/supported_hw/supported_prog/Dlp_usb1232h_side.jpg differ diff --git a/doc/supported_hw/supported_prog/Dlp_usb1232h_spi_programmer.jpg b/doc/supported_hw/supported_prog/Dlp_usb1232h_spi_programmer.jpg new file mode 100644 index 000000000..94eecb1ff Binary files /dev/null and b/doc/supported_hw/supported_prog/Dlp_usb1232h_spi_programmer.jpg differ diff --git a/doc/supported_hw/supported_prog/Dlp_usb1232h_spi_programmer_breadboard_1.jpg b/doc/supported_hw/supported_prog/Dlp_usb1232h_spi_programmer_breadboard_1.jpg new file mode 100644 index 000000000..61a7a18f5 Binary files /dev/null and b/doc/supported_hw/supported_prog/Dlp_usb1232h_spi_programmer_breadboard_1.jpg differ diff --git a/doc/supported_hw/supported_prog/Dlp_usb1232h_spi_programmer_breadboard_2.jpg b/doc/supported_hw/supported_prog/Dlp_usb1232h_spi_programmer_breadboard_2.jpg new file mode 100644 index 000000000..92e143a65 Binary files /dev/null and b/doc/supported_hw/supported_prog/Dlp_usb1232h_spi_programmer_breadboard_2.jpg differ diff --git a/doc/supported_hw/supported_prog/Ft2232spi_programer.jpg b/doc/supported_hw/supported_prog/Ft2232spi_programer.jpg new file mode 100644 index 000000000..84f618c80 Binary files /dev/null and b/doc/supported_hw/supported_prog/Ft2232spi_programer.jpg differ diff --git a/doc/supported_hw/supported_prog/Lycom-pe115-flashrom-buspirate-2.jpg b/doc/supported_hw/supported_prog/Lycom-pe115-flashrom-buspirate-2.jpg new file mode 100644 index 000000000..5962fa9a3 Binary files /dev/null and b/doc/supported_hw/supported_prog/Lycom-pe115-flashrom-buspirate-2.jpg differ diff --git a/doc/supported_hw/supported_prog/Openmoko_0001.jpeg b/doc/supported_hw/supported_prog/Openmoko_0001.jpeg new file mode 100644 index 000000000..7ea796856 Binary files /dev/null and b/doc/supported_hw/supported_prog/Openmoko_0001.jpeg differ diff --git a/doc/supported_hw/supported_prog/Openmoko_0002.jpeg b/doc/supported_hw/supported_prog/Openmoko_0002.jpeg new file mode 100644 index 000000000..be60d565c Binary files /dev/null and b/doc/supported_hw/supported_prog/Openmoko_0002.jpeg differ diff --git a/doc/supported_hw/supported_prog/Openmoko_0003.jpeg b/doc/supported_hw/supported_prog/Openmoko_0003.jpeg new file mode 100644 index 000000000..74109de52 Binary files /dev/null and b/doc/supported_hw/supported_prog/Openmoko_0003.jpeg differ diff --git a/doc/supported_hw/supported_prog/Via_epia_m700_bios.jpg b/doc/supported_hw/supported_prog/Via_epia_m700_bios.jpg new file mode 100644 index 000000000..6103838ea Binary files /dev/null and b/doc/supported_hw/supported_prog/Via_epia_m700_bios.jpg differ diff --git a/doc/supported_hw/supported_prog/Via_epia_m700_programer.jpg b/doc/supported_hw/supported_prog/Via_epia_m700_programer.jpg new file mode 100644 index 000000000..bc69bcb90 Binary files /dev/null and b/doc/supported_hw/supported_prog/Via_epia_m700_programer.jpg differ diff --git a/doc/supported_hw/supported_prog/buspirate.rst b/doc/supported_hw/supported_prog/buspirate.rst new file mode 100644 index 000000000..3d064701f --- /dev/null +++ b/doc/supported_hw/supported_prog/buspirate.rst @@ -0,0 +1,78 @@ +========== +Bus Pirate +========== + +The `Bus Pirate `_ is an open source design +for a multi-purpose chip-level serial protocol transceiver and debugger. +flashrom supports the Bus Pirate for `SPI programming `_. +It also has `SPI sniffing `_ +functionality, which may come in useful for analysing chip or programmer behaviour. + +They are available for around US$30 from various sources. + +Connections +=========== + +The table below shows how a typical SPI flash chip (sitting in the center of the table) +needs to be connected (NB: not all flash chips feature all of the pins below, but in general +you should always connect all input pins of ICs to some defined potential (usually GND or VCC), +ideally with a pull-up/down resistor in between). Most SPI flash chips require a 3.3V supply voltage, +but there exist some models that use e.g. 1.8V. Make sure the device in question is compatible +before connecting any wires. + +*NB: Some rather rare SPI flash chips (e.g. Atmel AT45DB series) have a completely different layout, please beware.* + ++----------------------+------------+------+---------------------------------+------+------------+-----------------------------+ +| Description | Bus Pirate | Dir. | Flash chip | Dir. | Bus Pirate | Description | ++======================+============+======+===+===========+=============+===+======+============+=============================+ +| (not) Chip Select | CS | → | 1 | /CS | VCC | 8 | ← | +3.3v | Supply | ++----------------------+------------+------+---+-----------+-------------+---+------+------------+-----------------------------+ +| Master In, Slave Out | MISO | ← | 2 | DO (IO1) | /HOLD (IO3) | 7 | ← | +3.3v | (not) hold (see datasheets) | ++----------------------+------------+------+---+-----------+-------------+---+------+------------+-----------------------------+ +| (not) Write Protect | +3.3v | → | 3 | /WP (IO2) | CLK | 6 | ← | CLK | The SPI clock | ++----------------------+------------+------+---+-----------+-------------+---+------+------------+-----------------------------+ +| Ground | GND | → | 4 | GND | DI (IO0) | 5 | ← | MOSI | Master Out, Slave In | ++----------------------+------------+------+---+-----------+-------------+---+------+------------+-----------------------------+ + +Usage +========= + +:: + + $ flashrom -p buspirate_spi:dev=/dev/device,spispeed=frequency + +Example:: + + $ flashrom -p buspirate_spi:dev=/dev/ttyUSB0,spispeed=1M + +Troubleshooting +=============== + +In case of problems probing the chip with flashrom - especially when connecting chips +still soldered in a system - please take a look at the doc :doc:`/user_docs/in_system`. In-system programming is often possible +**only as long as no other devices on the SPI bus are trying to access the device**. + +Speedup +========= + +A beta firmware build exists, to speed up the buspirate. +`See this post on dangerousprototypes.com `_ + +See also: http://dangerousprototypes.com/docs/Bus_Pirate#Firmware_upgrades + +Images +========== + +Bus Pirate v3, front. + +.. image:: Buspirate_v3_front.jpg + +Bus Pirate v3, back. + +.. image:: Buspirate_v3_back.jpg + +Recovering a bricked Lycom PE-115 88SE8123 PCIe to SATA adapter using flashrom and a Bus Pirate - power to the +PE-115 is supplied by a PC. The test probes of the bus pirate are attached directly to the SOIC Atmel AT26F004 SPI flash chip. +The other test clip is connected to GND on another device for convenience (easier than getting yet another clip onto a SOIC device). + +.. image:: Lycom-pe115-flashrom-buspirate-2.jpg diff --git a/doc/supported_hw/supported_prog/dummyflasher.rst b/doc/supported_hw/supported_prog/dummyflasher.rst new file mode 100644 index 000000000..d11f59c50 --- /dev/null +++ b/doc/supported_hw/supported_prog/dummyflasher.rst @@ -0,0 +1,14 @@ +============ +Dummyflasher +============ + +Dummyflasher programmer is software-only implementation of a flashrom programmer. In other words, +it is an emulator which operates on in-memory arrays of bytes instead of a real chip. Dummyflasher does not interact with any hardware. + +This programmer is actively used in unit tests. + +Also, since dummyflasher implements all of the programmers APIs, it can be used as an example or as a starting point for implementing a new programmer. + +Related documents: + +* :doc:`/contrib_howtos/how_to_add_unit_test` diff --git a/doc/supported_hw/supported_prog/ft2232_spi.rst b/doc/supported_hw/supported_prog/ft2232_spi.rst new file mode 100644 index 000000000..8f87117f9 --- /dev/null +++ b/doc/supported_hw/supported_prog/ft2232_spi.rst @@ -0,0 +1,308 @@ +========== +FT2232 SPI +========== + +flashrom supports the ``-p ft2232_spi`` (or ``-p ft2232spi`` in very old flashrom revisions) option +which allows you to use an FTDI FT2232/FT4232H/FT232H based device as external SPI programmer. + +This is made possible by using `libftdi `_. +flashrom autodetects the presence of libftdi headers and enables FT2232/FT4232H/FT232H support if they are available. + +Currently known FT2232/FT4232H/FT232H based devices which can be used as SPI programmer +together with flashrom are described below. + +DLP Design DLP-USB1232H +======================= + +The `DLP Design DLP-USB1232H `_ +(`datasheet DLP-USB1232H `_) can be used with flashrom +for programming SPI chips. + +Where to buy: `Digikey `_, +`Mouser `_, +`Saelig `_ + +Setup +----- + +DLP-USB1232H based SPI programmer schematics + +.. image:: Dlp_usb1232h_spi_programmer.jpg + +In order to use the DLP-USB1232H device as SPI programmer you have to setup a small circuit +(e.g. on a breadboard). See the schematics for details (you can also +`download the schematics as PDF `_ +for easier printing). + +What you will need +------------------ + +=============== ======================= ============= ====== =============================================== +Quantity Device Footprint Value Comments +=============== ======================= ============= ====== =============================================== +1 DLP Design DLP-USB1232H — — ... +1 Breadboard — — ... +many Jumper wires — — ... +1 DIP-8 SPI chip — — This is the chip you want to program/read/erase +1 3.3V voltage regulator TO-220 3.3V E.g. **LD33V** or **LD1117xx** +1 Electrolytic capacitor single ended 100nF ... +1 Electrolytic capacitor single ended 10uF ... +=============== ======================= ============= ====== =============================================== + +Instructions and hints +---------------------- + +* You must connect/shorten pins 8 and 9, which configures the device to be powered by USB. + Without this connection it will not be powered, and thus not be detected by your OS + (e.g. it will not appear in the ``lsusb`` output). + +* You need a 3.3V voltage regulator to convert the 5V from USB to 3.3V, + so you can power the 3.3V SPI BIOS chip. + + * You can probably use pretty much any 3.3V voltage regulator, e.g. **LD33V** or **LD1117xx**. + For usage on a breadboard the TO-220 packaging is probably most useful. + * You have to connect two capacitors (e.g. 100nF and 10uF as per datasheets, + but using two 10uF capacitors, or even two 47uF capacitors also works in practice) as shown in the schematics, + otherwise the voltage regulator will not work correctly and reliably. + +* Connect the following pins from the DLP-USB1232H to the SPI BIOS chip: + + * **18 (SK)** to **SCLK** + * **16 (DO)** to **SI** + * **2 (DI)** to **SO** + * **5 (CS)** to **CS#** + * The **WP# and HOLD#** pins should be tied to **VCC**! If you leave them unconnected + you'll likely experience strange issues. + * All **GND** pins should be connected together (**pins 1i and 10** on the DLP-USB1232H, + **pin 8** on the SPI chip, **pin 1** on the voltage regulator). + +You have to invoke flashrom with the following parameters:: + + $ flashrom -p ft2232_spi:type=2232H,port=A + +Photos +------ + +Module, top + +.. image:: Dlp_usb1232h_side.jpg + + +Module, bottom + +.. image:: Dlp_usb1232h_bottom.jpg + + +SPI header on a mainboard + +.. image:: Via_epia_m700_bios.jpg + + +Module on a breadboard, connected to the mainboard's SPI header + +.. image:: Via_epia_m700_programer.jpg + + +Breadboard setup + +.. image:: Ft2232spi_programer.jpg + + +Another breadboard setup + +.. image:: Dlp_usb1232h_spi_programmer_breadboard_1.jpg + + +Module and parts + +.. image:: Dlp_usb1232h_spi_programmer_breadboard_2.jpg + +FTDI FT2232H Mini-Module +======================== + +The `FTDI FT2232H Mini-Module Evaluation Kit `_ +(`the datasheet `_) +can be used with flashrom for programming SPI chips. + +Pinout +------ + +=============== ======= ======= =============== =========================== +Module Pin FTDI MPSSE SPI SPI Flash (vendor specific) +=============== ======= ======= =============== =========================== +CN2-7 AD0 TCK/SK (S)CLK (S)CLK +CN2-10 AD1 TDI/DO MOSI SI / DI +CN2-9 AD2 TDO/DI MISO SO / DO +CN2-12 AD3 TMS/CS /CS / /SS /CS +CN3-26 BD0 TCK/SK (S)CLK (S)CLK +CN3-25 BD1 TDI/DO MOSI SI / DI +CN3-24 BD2 TDO/DI MISO SO / DO +CN3-23 BD3 TMS/CS /CS / /SS /CS +=============== ======= ======= =============== =========================== + +FTDI FT4232H Mini-Module +======================== + +The `FTDI FT4232H Mini-Module Evaluation Kit `_ +(`datasheet `_) +can be used with flashrom for programming SPI chips. + +Olimex ARM-USB-TINY/-H and ARM-USB-OCD/-H +========================================= + +The `Olimex `_ `ARM-USB-TINY `_ +(VID:PID 15BA:0004) and `ARM-USB-OCD `_ (15BA:0003) +can be used with flashrom for programming SPI chips. +The `ARM-USB-TINY-H `_ (15BA:002A) +and `ARM-USB-OCD-H `_ (15BA:002B) should also work, +though the tested status is unconfirmed. + +The following setup can then be used to flash a BIOS chip through SPI. + +Pinout: + + .. image:: ARM-USB-TINY_pinout.png + +=============== ========================= +Pin (JTAG Name) SPI/Voltage Source +=============== ========================= +1 (VREF) VCC (from Voltage Source) +2 (VTARGET) VCC (to SPI target) +4 (GND) GND (from Voltage Source) +5 (TDI) SI +6 (GND) GND (to SPI target) +7 (TMS) CE# +9 (TCK) SCK +13 (TDO) SO +=============== ========================= + +On the ARM-USB-TINY, VREF, and VTARGET are internally connected, and all the GND lines +(even numbered pins, from 4 to 20) share the same line as well, so they can be used +to split VCC/GND between the voltage source and the target. + +The voltage source should provide 3.0V to 3.3V DC but doesn't have to come from USB: +it can be as simple as two AA or AAA batteries placed in serial (2 x 1.5V). + +Invoking flashrom +----------------- + +You first need to add the ``-p ft2232_spi`` option, and then specify one of ``arm-usb-tiny``, +``arm-usb-tiny-h``, ``arm-usb-ocd`` or ``arm-usb-ocd-f`` for the type. +For instance, to use an ARM-USB-TINY, you would use:: + + $ flashrom -p ft2232_spi:type=arm-usb-tiny + +Openmoko +======== + +The openmoko debug board (which can also do serial+jtag for the openmoko phones, or for other phones) +has `its shematics available here `_. + +Informations +------------ + +The openmoko debug board can act as an SPI programmer bitbanging the FTDI +(no need of an openmoko phone), you just need: + +* a breadboard +* some wires +* The openmoko debug board(v2 and after,but only tested with v3) + +The voltage is provided by the board itself. The connector to use is the JTAG one +(very similar to what's documented in the previous section(Olimex ARM-USB-TINY/-H and ARM-USB-OCD/-H ) + +Building +-------- + +**WARNING: This was tested with 3.3v chips only.** + +Here's the pinout of the JTAG connector of the openmoko debug board +(copied from ARM-USB-tiny because it's the same pinout): + + .. image:: ARM-USB-TINY_pinout.png + +=============== =============================== ======================== +Pin (JTAG Name) SPI/Voltage Source BIOS Chip connector name +=============== =============================== ======================== +1 (VREF) VCC (from Voltage Source) VCC (3.3v only) +2 (VTARGET) VCC (to SPI target) Not connected +4 (GND) GND (from Voltage Source) Ground +5 (TDI) SI DIO (Data Input) +6 (GND) GND (to SPI target) Not connected +7 (TMS) CE# CS (Chip select) +9 (TCK) SCK CLK (Clock) +13 (TDO) SO DO (Data output) +=============== =============================== ======================== + +* Also connect the BIOS chip's write protect(WP) to VCC + +* Also connect the BIOS chips's HOLD to VCC + +Pictures +-------- + +.. image:: Openmoko_0001.jpeg + +.. image:: Openmoko_0002.jpeg + +.. image:: Openmoko_0003.jpeg + +Performances +------------ + +:: + + $ time ./flashrom/flashrom -p ft2232_spi:type=openmoko -r coreboot.rom + flashrom v0.9.5.2-r1545 on Linux 3.0.0-20-generic (x86_64) + flashrom is free software, get the source code at http://www.flashrom.org + + Calibrating delay loop... OK. + Found Winbond flash chip "W25X80" (1024 kB, SPI) on ft2232_spi. + Reading flash... done. + + real 0m19.459s + user 0m1.244s + sys 0m0.000s + +:: + + $ time ./flashrom/flashrom -p ft2232_spi:type=openmoko -w coreboot.rom + flashrom v0.9.5.2-r1545 on Linux 3.0.0-20-generic (x86_64) + flashrom is free software, get the source code at http://www.flashrom.org + + Calibrating delay loop... OK. + Found Winbond flash chip "W25X80" (1024 kB, SPI) on ft2232_spi. + Reading old flash chip contents... done. + Erasing and writing flash chip... Erase/write done. + Verifying flash... VERIFIED. + + real 1m1.366s + user 0m7.692s + sys 0m0.044s + +Advantages/disadvantages +------------------------ + +* fast(see above) + +* easily available (many people in the free software world have openmoko debug board + and they don't know what to do with them), can still be bought + +* stable + +* SPI only + +Generic Pinout +============== + +There are many more simple modules that feature the FT*232H. +Actual pinouts depend on each module, the FTDI names map to SPI as follows: + +=============== ======= =============== =========================== +Pin Name MPSSE SPI SPI Flash (vendor specific) +=============== ======= =============== =========================== +DBUS0 TCK/SK (S)CLK (S)CLK +DBUS1 TDI/DO MOSI SI / DI +DBUS2 TDO/DI MISO SO / DO +DBUS3 TMS/CS /CS / /SS /CS +=============== ======= =============== =========================== diff --git a/doc/supported_hw/supported_prog/index.rst b/doc/supported_hw/supported_prog/index.rst new file mode 100644 index 000000000..7912f348f --- /dev/null +++ b/doc/supported_hw/supported_prog/index.rst @@ -0,0 +1,21 @@ +Supported programmers +===================== + +flashrom supports many different programmers, for the full list you can look into `programmer_table.c `_ +in the source tree. Some of the programmers have their own documentation pages, see below. + +Please check the :ref:`programmer-specific information` section of the :doc:`/classic_cli_manpage` for more details about programmers and their usage. + +If you can run flashrom locally, the command ``flashrom -L`` prints all devices supported per programmer +(see :doc:`/classic_cli_manpage` for more details on command line options). The output of this command is long, so you might +want to save it to file or grep. + +Patches to add/update documentation, or migrate docs from `old wiki website `_ are very much appreciated. + +.. toctree:: + :maxdepth: 1 + + buspirate + dummyflasher + ft2232_spi + serprog/index diff --git a/doc/supported_hw/supported_prog/serprog/166px-Serprogduino_v2.jpeg b/doc/supported_hw/supported_prog/serprog/166px-Serprogduino_v2.jpeg new file mode 100644 index 000000000..ffe85588f Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/166px-Serprogduino_v2.jpeg differ diff --git a/doc/supported_hw/supported_prog/serprog/250px-Arduino_5V_lpc_spi_shield.jpg b/doc/supported_hw/supported_prog/serprog/250px-Arduino_5V_lpc_spi_shield.jpg new file mode 100644 index 000000000..1886e260b Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/250px-Arduino_5V_lpc_spi_shield.jpg differ diff --git a/doc/supported_hw/supported_prog/serprog/250px-Arduino_lpcspi_shield_render.png b/doc/supported_hw/supported_prog/serprog/250px-Arduino_lpcspi_shield_render.png new file mode 100644 index 000000000..02b139e5e Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/250px-Arduino_lpcspi_shield_render.png differ diff --git a/doc/supported_hw/supported_prog/serprog/300px-AtmegaXXu2-flasher.jpg b/doc/supported_hw/supported_prog/serprog/300px-AtmegaXXu2-flasher.jpg new file mode 100644 index 000000000..1a78faa90 Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/300px-AtmegaXXu2-flasher.jpg differ diff --git a/doc/supported_hw/supported_prog/serprog/300px-Avr_rs232_programmer.jpg b/doc/supported_hw/supported_prog/serprog/300px-Avr_rs232_programmer.jpg new file mode 100644 index 000000000..618037b59 Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/300px-Avr_rs232_programmer.jpg differ diff --git a/doc/supported_hw/supported_prog/serprog/300px-HydraFW_Default_PinAssignment.png b/doc/supported_hw/supported_prog/serprog/300px-HydraFW_Default_PinAssignment.png new file mode 100644 index 000000000..a9fd931c8 Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/300px-HydraFW_Default_PinAssignment.png differ diff --git a/doc/supported_hw/supported_prog/serprog/300px-Serprog_0001.jpeg b/doc/supported_hw/supported_prog/serprog/300px-Serprog_0001.jpeg new file mode 100644 index 000000000..af1bcafca Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/300px-Serprog_0001.jpeg differ diff --git a/doc/supported_hw/supported_prog/serprog/300px-Teensy31_lpcspi_flasher.jpg b/doc/supported_hw/supported_prog/serprog/300px-Teensy31_lpcspi_flasher.jpg new file mode 100644 index 000000000..9289aaeac Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/300px-Teensy31_lpcspi_flasher.jpg differ diff --git a/doc/supported_hw/supported_prog/serprog/P1v1_arduino328.png b/doc/supported_hw/supported_prog/serprog/P1v1_arduino328.png new file mode 100644 index 000000000..0fd808bf0 Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/P1v1_arduino328.png differ diff --git a/doc/supported_hw/supported_prog/serprog/P1v2_arduino1280.png b/doc/supported_hw/supported_prog/serprog/P1v2_arduino1280.png new file mode 100644 index 000000000..7cd6cb9cf Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/P1v2_arduino1280.png differ diff --git a/doc/supported_hw/supported_prog/serprog/P2v1_resdivider.png b/doc/supported_hw/supported_prog/serprog/P2v1_resdivider.png new file mode 100644 index 000000000..16d5dae19 Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/P2v1_resdivider.png differ diff --git a/doc/supported_hw/supported_prog/serprog/P2v2_oc_cs.png b/doc/supported_hw/supported_prog/serprog/P2v2_oc_cs.png new file mode 100644 index 000000000..45ebe2d41 Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/P2v2_oc_cs.png differ diff --git a/doc/supported_hw/supported_prog/serprog/P2v3_buffer4050.png b/doc/supported_hw/supported_prog/serprog/P2v3_buffer4050.png new file mode 100644 index 000000000..d2ebd8c9d Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/P2v3_buffer4050.png differ diff --git a/doc/supported_hw/supported_prog/serprog/P3v1_dil8_so8_spi.png b/doc/supported_hw/supported_prog/serprog/P3v1_dil8_so8_spi.png new file mode 100644 index 000000000..3a2f1342e Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/P3v1_dil8_so8_spi.png differ diff --git a/doc/supported_hw/supported_prog/serprog/P3v2_so16_spi.png b/doc/supported_hw/supported_prog/serprog/P3v2_so16_spi.png new file mode 100644 index 000000000..7ae13796e Binary files /dev/null and b/doc/supported_hw/supported_prog/serprog/P3v2_so16_spi.png differ diff --git a/doc/supported_hw/supported_prog/serprog/arduino_flasher.rst b/doc/supported_hw/supported_prog/serprog/arduino_flasher.rst new file mode 100644 index 000000000..ada05195d --- /dev/null +++ b/doc/supported_hw/supported_prog/serprog/arduino_flasher.rst @@ -0,0 +1,227 @@ +=============== +Arduino flasher +=============== + +.. container:: danger, admonition + + **WARNING** + + Make sure that the Arduino SPI voltages and the flash chip voltages matches: Without any extra resistors or level shifter, + the Arduino Uno and Duemillanove SPI pins are at 5V, while most chips operate at 3.3v. + +Hardware basics +=============== + +You'll need to have: + +* a supported Arduino, these are + + * any based on the ATmega328 (/168/88 will work with small changes too), like the Arduino Uno R3. + * Arduino Mega or Mega2560, but notice that the software has a different branch for them. + +* a way to convert the 5V logic levels to 3.3V (except if 3.3V arduino, these are rarer) +* a 3.3V SPI flash chip that is supported by flashrom + +Notes: + +* The FTDI based usb-serial converters are the fastest. +* 1.8V conversion isnt covered here, yet. + +There are some simple schematics included here (`source `_). +The idea is that you pick one version from each part 1 through 3, and connect the pin/net names. + +Part 1: The Arduino +------------------- + +ATmega328 based ones: + +.. image:: P1v1_arduino328.png + +For the Arduino Megas: + +.. image:: P1v2_arduino1280.png + +Part 2: Level translation +------------------------- + +There are a few options here, ranging from the simple resistors (v1) to a buffer chip (v3). + +One thing to remember about the resistor dividers is that they're not strong enough to do ISP. + +Here's the simple resistors: + +.. image:: P2v1_resdivider.png + +The part count for the resistor divider is 6 resistors of 2 types or 9 of one type. + +Here's one with 5 resistors, the downside is that you'll need to modify the firmware a little: + +.. image:: P2v2_oc_cs.png + +The 3rd version is using the DIP16 HEF4050 buffer chip: + +.. image:: P2v3_buffer4050.png + +Part 3: The SPI Flash chip +-------------------------- + +The DIL-8 and SOIC-8 versions connect like this: + +.. image:: P3v1_dil8_so8_spi.png + +For the SMD SOIC-16 chips the pinout is: + +.. image:: P3v2_so16_spi.png + +Gallery of some flashers +======================== + +.. image:: 166px-Serprogduino_v2.jpeg + +.. _arduino shield: + +Alternative: Shield with SPI and LPC/FWH for 5V Arduinos +======================================================== + +.. image:: 250px-Arduino_5V_lpc_spi_shield.jpg + +.. image:: 250px-Arduino_lpcspi_shield_render.png + +`Firmware and hardware sources `_ + +`Shield PCB shared at oshpark `_ + +* This shield and firmware was built for 5V ATMega328s with FTDI, variations to that will need adaptations in building the shield and/or in the firmware. + The Uno R3 will work with the fast-usbserial U2 firmware. +* This shield uses a different pin for SPI CS than the other circuits on this page, and has LPC/FWH capability, thus different firmware. + Frser-duino does have the code for using the CS like in this shield, but you need to modify spihw.h. +* Note: do check for any incompatibilities between your arduino and the shield, eg. the PD7 used as LPC CLK clashes with BT reset in BT arduinos. +* For LPC/FWH, current (16/02/01) flashrom trunk will be really slow, please use this branch instead. + +Software and setup +================== + +The Arduino Uno R3 and other arduinos with an ATmega8U2/16U2 as an usb-serial converter have lots of bugs in their usb-serial firmware +that prevent it from operating at more than a limited 115200 baud. The frser-duino firmware works around this by default if you use the appropriate make target, +but there exists a firmware that allows these to be used like the FTDI at 2Mbaud: `fast-usbserial `_. + +Setup +----- + +Required software +^^^^^^^^^^^^^^^^^ + +To make it work you need: + +* A recent flashrom with the serprog protocol compiled in (most packaged versions do) +* `frser-duino which runs on the arduino `_ + + * This page used to link to `serprog-duino `_, + frser-duino should build in a similar fashion and has better serial buffering and some other features (spi speed setting). + +* The avr toolchain(avr-gcc, avr-libc,make etc...) + +Building the software +^^^^^^^^^^^^^^^^^^^^^ + +First get the firmware source:: + + $ git clone --recursive git://github.com/urjaman/frser-duino + $ cd frser-duino + +Then build it: + +For a board with a 8u2 or a 16u2:: + + $ make u2 && make flash-u2 + +For a board with an ftdi:: + + $ make ftdi && make flash-ftdi + +Building for the Mega1280 or 2560 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +As above, except use the branch for the 1280:: + + $ git clone --recursive git://github.com/urjaman/frser-duino -b arduino-mega-1280 + +For the Mega2560, change the Makefile to target the correct MCU (replace 1280 with 2560). Please also verify that the avrdude command is as expected for your device. + +Running flashrom +^^^^^^^^^^^^^^^^ + +The right flashrom arguments are explained in the :doc:`/classic_cli_manpage`, or here. + +Available targets: + +* ftdi, flash-ftdi: + For the Arduinos with an FTDI + compatible flashrom arguments:: + + flashrom -p serprog:dev=/dev/ttyUSB0:2000000 + + Other boards using an hardware USB<->Serial converter might work too. + +* u2, flash-u2: + For the Arduino with a 8u2 or a 16u2 + compatible flashrom arguments:: + + flashrom -p serprog:dev=/dev/ttyACM0:115200 + +So for a board that has an ftdi that would give:: + + flashrom -p serprog:dev=/dev/ttyUSB0:2000000 + +Speed +^^^^^ + +The speed is very dependant on the flash chip used: + +* Its capacity impacts the speed a lot, as you would expect. +* The chip model as also a huge impact. + +Duemillanove +^^^^^^^^^^^^ + +With the duemillanove:: + + # time flashrom -p serprog:dev=/dev/ttyUSB0:2000000 -r duemillanove.rom + flashrom v0.9.7-r1711 on Linux 3.18.3-gnu-1 (i686) + flashrom is free software, get the source code at http://www.flashrom.org + + Calibrating delay loop... delay loop is unreliable, trying to continue OK. + serprog: Programmer name is "serprog-duino" + Found Winbond flash chip "W25Q32.V" (4096 kB, SPI) on serprog. + Reading flash... done. + flashrom -p serprog:dev=/dev/ttyUSB0:2000000 -r duemillanove.rom + +we have:: + + 4.23s user 0.29s system 8% cpu 56.010 total + +Uno +^^^ + +With the Arduino uno:: + + # flashrom -p serprog:dev=/dev/ttyACM0:115200 -r uno.rom + flashrom v0.9.7-r1711 on Linux 3.18.3-gnu-1 (i686) + flashrom is free software, get the source code at http://www.flashrom.org + + Calibrating delay loop... delay loop is unreliable, trying to continue OK. + serprog: Programmer name is "serprog-duino" + Found Winbond flash chip "W25Q32.V" (4096 kB, SPI) on serprog. + Reading flash... done. + flashrom -p serprog:dev=/dev/ttyACM0:115200 -r uno.rom + +we have:: + + 4.77s user 0.65s system 1% cpu 6:02.43 total + +Tested chips +^^^^^^^^^^^^ + +* SST25VF016B => huge issues, not recognized by the 3.3v version, had to use the 5v version which is over maximum allowed voltage, + also had to lower the serial speed to 115200, ultra slow to write(seem related to the chip itself, since that with the openmoko programmer it's even slower...)... +* W25X80 works well in 3.3v mode(5v works also but it's highly not advised to use 5v) diff --git a/doc/supported_hw/supported_prog/serprog/arduino_flasher_3.3v.rst b/doc/supported_hw/supported_prog/serprog/arduino_flasher_3.3v.rst new file mode 100644 index 000000000..0f4b76cbc --- /dev/null +++ b/doc/supported_hw/supported_prog/serprog/arduino_flasher_3.3v.rst @@ -0,0 +1,237 @@ +==================== +Arduino flasher 3.3v +==================== + +Introduction +============ + +This explains how to: + +* Easily lower the voltage of an arduino +* Use that arduino to flash a coreboot image on a GM45 Thinkpad with a SOIC16 chip + +It requires: + +* An AVR Arduino at 5v +* An USB<->Serial adapter capable of providing enough current to power up: + + * The arduino + * The flash chip + * The circuits around the flash chip + +It was tested with: + +* An Arduino.org "nano version 3.3" +* A Sparkfun "FTDI Basic 3v3" (Uses an FTDI FT232R) + +Caveats and warnings: + +* It requires you to to never connect an USB cable between the Arduino USB port and the computer while the flasher is connected to a flash chip. + This would result in the I/O voltage being 5V instead of 3.3V. If you think you may accidentally connect it this way, this flasher isn't the right solution for you. +* You need to read the tutorial, if you don't understand it, it's probably not for you. In doubt you could ask for some help in flashrom real-time channels + or on the mailing list, see :doc:`/contact`. +* For now it requires to patch frser-duino + +Theory +======== + +In the `Atmega328/P datasheet `_, +the "32.3. Speed Grades" chapter describes (pages 368 and 369) the link between maximum frequency of the microcontroller and the voltage. At 3.3v, the maximum frequency is 12Mhz. + +HOWTO +======== + +Build the code installing it on the arduino +------------------------------------------- + +Building frser-duino +^^^^^^^^^^^^^^^^^^^^ + +First download frser-duino:: + + $ git clone --recursive https://github.com/urjaman/frser-duino.git + $ cd frser-duino + +Then modify the ``F_CPU`` value in ``main.h`` to be 12Mhz instead of 16Mhz. ``F_CPU`` will look like that:: + + #define F_CPU 16000000UL + +Change it to:: + + #define F_CPU 12000000UL + +You can then build the code:: + + $ make ftdi + +Installing the code on the arduino +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Before installing the code on arduino we want to make sure that we are talking to the right device. +To do that make sure that the arduino is not connected to your computer and run:: + + $ ls -l /dev/ttyUSB0 + +If everything went fine it will output something like that:: + + ls: cannot access '/dev/ttyUSB0': No such file or directory + +If instead it looks like that:: + + crw-rw---- 1 root uucp 188, 0 27 févr. 14:30 /dev/ttyUSB0 + +then something else is connected to your computer at ``/dev/ttyUSB0``. If you can't figure what's going on by yourself, +it's better to try get help on the flashrom channels to fix the issue, see :doc:`/contact`. + +Then connect your arduino to the computer and run the same command:: + + $ ls -l /dev/ttyUSB0 + +This time it's supposed to output a line that looks more or less like that:: + + crw-rw---- 1 root uucp 188, 0 27 févr. 14:30 /dev/ttyUSB0 + +At this point we're pretty confident that ``/dev/ttyUSB0`` corresponds to the arduino, so we can install the code with:: + + $ make flash-ftdi + +Once it is installed we can now test that everything went fine with:: + + $ flashrom -p serprog:dev=/dev/ttyUSB0:2000000 + +This will make flashrom talk to the arduino to verify if everything is fine up to this point. + +If everything went fine it will look more or less like that:: + + $ flashrom -p serprog:dev=/dev/ttyUSB0:2000000 + /sys/firmware/dmi/tables/smbios_entry_point: Permission denied + /dev/mem: Permission denied + /sys/firmware/dmi/tables/smbios_entry_point: Permission denied + /dev/mem: Permission denied + flashrom v1.0 on Linux 4.15.2-gnu-1 (i686) + flashrom is free software, get the source code at https://flashrom.org + + Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns). + serprog: Programmer name is "frser-duino" + serprog: requested mapping AT45CS1282 is incompatible: 0x1080000 bytes at 0xfef80000. + No EEPROM/flash device found. + Note: flashrom can never write if the flash chip isn't found automatically. + +This is the important line:: + + serprog: Programmer name is "frser-duino" + +It means that flashrom is able to talk to the flasher, which reports itself as "frser-duino" We also have the following line:: + + No EEPROM/flash device found. + +which tells that it didn't find any flash. This is what's supposed to happen since we didn't connect any yet. + +Build the programmer +-------------------- + +Connect the programmer to the USB<->Serial adapter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To do that: + +* Connect the FTDI adapter RX to the TX of the arduino +* Connect the FTDI adapter TX to the RX of the arduino +* Connect the 3V3 of the FTDI adapter to the 5V pin of the Arduino +* Connect the GND of the FTDI adapter to the GDN of the arduino. + +Here's a summary of the above: + +======== ========================= +Arduino USB<->Serial port adapter +======== ========================= +RX TX +TX RX +5v 3.3v +GND GND +======== ========================= + +You can now check that the programmer is responding with:: + + flashrom -p serprog:dev=/dev/ttyUSB0:2000000 + +Since you didn't connect yet a flash chip, it will says it found no flash chips:: + + $ flashrom -p serprog:dev=/dev/ttyUSB0:2000000 + /sys/firmware/dmi/tables/smbios_entry_point: Permission denied + /dev/mem: Permission denied + /sys/firmware/dmi/tables/smbios_entry_point: Permission denied + /dev/mem: Permission denied + flashrom v1.0 on Linux 4.15.2-gnu-1 (i686) + flashrom is free software, get the source code at https://flashrom.org + + Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns). + serprog: Programmer name is "frser-duino" + serprog: requested mapping AT45CS1282 is incompatible: 0x1080000 bytes at 0xfef80000. + No EEPROM/flash device found. + Note: flashrom can never write if the flash chip isn't found automatically. + +Again like before the important parts are:: + + serprog: Programmer name is "frser-duino" + +And:: + + No EEPROM/flash device found. + +If you made it up to this point, you successfully built the flasher. + +Using the programmer +-------------------- + +Connect the programmer to a flash chip +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Since the flasher has been built, you probably want to use it. + +If you use a clip (Like a SOIC-8 or SOIC16 Pomona clip), connect it to the Arduino +Connect the chip to the clip, or if you don't use a clip, the chip to the Arduino +Here's how to connect the flash chips to the programmer: + +=========== ========================== =================== ===================== +Arduino pin Function Flash chip pin name SOIC16 Flash chip pin +=========== ========================== =================== ===================== +D13 CLK (Clock) CLK 16 +D12 MISO (Master In Slave Out) MISO or SO 8 +D11 MOSI (Master Out Slave In) MOSI or SI 15 +D10 CS# (Chip Select) CS# or CS OR SS 7 +GND GND (Ground) GND 10 +5V 3.3V VCC 2 +5V 3.3V WP# (Write Protect) 9 +5V 3.3V HOLD# 1 +=========== ========================== =================== ===================== + +Then connect an USB cable between the USB<->Serial adapter and the computer. +Never connect the cable between the Arduino USB port and the computer while the flasher is connected to a flash chip. +That would result in the I/O voltage being 5V instead of 3.3V. + +Flashing +^^^^^^^^ + +Run flashrom like that:: + + flashrom -p serprog:dev=/dev/ttyUSB0:2000000 + +With some models of Macronix flash chip (that are present in the Thinkpad X200) you might need to add ``spispeed=100k`` like that:: + + flashrom -p serprog:dev=/dev/ttyUSB0:2000000,spispeed=100k + +Thanks +======== + +Thanks a lot to SwiftGeek on IRC (#libreboot on Libera) for finding the first workaround to make it detect flash chips at lower voltage. +Thanks also for telling me about the Macronix issues on the Thinkpad X200. This project would not have been possible without that. + +Page license +============ + +This page is available under the following licenses: + +* `CC-BY-SA 3.0 `_ +* `CC-BY-SA 4.0 `_ or later +* `GFDL 1.3 `_ or later diff --git a/doc/supported_hw/supported_prog/serprog/index.rst b/doc/supported_hw/supported_prog/serprog/index.rst new file mode 100644 index 000000000..c1c2d73ea --- /dev/null +++ b/doc/supported_hw/supported_prog/serprog/index.rst @@ -0,0 +1,11 @@ +Serprog +======== + +.. toctree:: + :maxdepth: 1 + + overview + serprog-protocol + arduino_flasher_3.3v + arduino_flasher + teensy_3_1 diff --git a/doc/supported_hw/supported_prog/serprog/overview.rst b/doc/supported_hw/supported_prog/serprog/overview.rst new file mode 100644 index 000000000..ba01b024c --- /dev/null +++ b/doc/supported_hw/supported_prog/serprog/overview.rst @@ -0,0 +1,95 @@ +================== +Serprog (overview) +================== + +This page collects information about the serprog protocol and the programmers implementing it. + +Protocol +======== + +See :doc:`/supported_hw/supported_prog/serprog/serprog-protocol`. It is designed to be compact and allow efficient storage in limited memory of programmer devices. + +AVR flasher by Urja Rannikko +============================ + +.. image:: 300px-Avr_rs232_programmer.jpg + +The Prototype RS232 AVR parallel flash programmer of Urja Rannikko was the first implementation of the serprog protocol. + +The source code can be found `here `_. + +InSystemFlasher by Juhana Helovuo +================================= + +This was the first one that talks to SPI devices via serial over USB. +Details can be found in the `coreboot wiki `_ and in this +`coreboot mailing list thread `_. + +atmegaXXu2-flasher by Stefan Tauner +=================================== + +Like the InSystemFlasher this one uses LUFA on an AVR microcontroller to tunnel the serial data over USB. + +.. image:: 300px-AtmegaXXu2-flasher.jpg + +Various Arduino based flashers +============================== + +Frser-duino +----------- + +This project contains `source code `_ to install on Arduino devices. + +This developer also have various ports on `github repo `_ for several microcontroller boards, such as: + +* `frser-teensyflash `_: A port for the teensy microcontroller board + +There also various other interesting projects such as: + +* `fast-usbserial `_: A software to make arduino with 8u2 or 16u2 flashing faster and more reliable] +* :ref:`arduino shield` + +Using a 5v Arduino at 3.3V +-------------------------- + +Information on it can be found in this doc: :doc:`/supported_hw/supported_prog/serprog/arduino_flasher_3.3v` + +5V arduino with level shifter +----------------------------- + +For detailed instructions on how to use different Arduino models to access SPI flash chips see :doc:`/supported_hw/supported_prog/serprog/arduino_flasher` + +.. image:: 300px-Serprog_0001.jpeg + +Teensy 3.1 SPI + LPC/FWH Flasher +-------------------------------- + +A Teensy 3.1 based small flasher by Urja Rannikko documented here: :doc:`/supported_hw/supported_prog/serprog/teensy_3_1` + +HydraBus multi-tool +------------------- + +HydraBus (hardware) with HydraFW (firmware) is an open source multi-tool for learning, developing, debugging, hacking and penetration testing +of embedded hardware. It is built upon an ARM Cortex-M4 (STM32F405). The source code for HydraFW is available +`on GitHub `_. Refer to `their GitHub Wiki `_ +for more details on how to use HydraBus with flashrom. + +.. image:: 300px-HydraFW_Default_PinAssignment.png + +stm32-vserprog by Chi Zhang +----------------------------- + +A powerful option is `stm32-vserprog `_, a firmware for various STM32-based boards +that turns them into serprog-based programmers with SPI clock speeds up to 36 MHz. + +pico-serprog +------------ + +`pico-serprog `_ by stacksmashing is a firmware for +`Raspberry Pi Picos `_ and other RP2040 based boards which turns them +into a serprog programmer. + +Notable forks are: + +`Riku_V's fork `_ which uses the hardware SPI implementation instead of SPI over PIO (programmable IO) which +sacrifices arbitrary pinouts. The fork also implements custom USB descriptors which allow for custom udev-rules. diff --git a/Documentation/serprog-protocol.txt b/doc/supported_hw/supported_prog/serprog/serprog-protocol.rst similarity index 51% rename from Documentation/serprog-protocol.txt rename to doc/supported_hw/supported_prog/serprog/serprog-protocol.rst index 6b7e7e330..35574facc 100644 --- a/Documentation/serprog-protocol.txt +++ b/doc/supported_hw/supported_prog/serprog/serprog-protocol.rst @@ -1,80 +1,103 @@ -Serial Flasher Protocol Specification - version 1 (0x01 return value == 1) +===================================== +Serial Flasher Protocol Specification +===================================== + +Version 1 (0x01 return value == 1) +================================== Command And Answer Sequence - all commands give an answer. + PC: COMMAND(8bit) + DEV: ACK/NAK(8bit) / nothing + Command 0x10 (SYNCNOP) has a special return of NAK+ACK for synchronization. ACK = 0x06 + NAK = 0x15 All multibyte values are little-endian. Addresses and lengths are 24-bit. -COMMAND Description Parameters Return Value -0x00 NOP none ACK -0x01 Query programmer iface version none ACK + 16bit version (nonzero) -0x02 Query supported commands bitmap none ACK + 32 bytes (256 bits) of supported cmds flags -0x03 Query programmer name none ACK + 16 bytes string (null padding) / NAK -0x04 Query serial buffer size none ACK + 16bit size / NAK -0x05 Query supported bustypes none ACK + 8-bit flags (as per flashrom) / NAK -0x06 Query connected address lines none ACK + 8bit line count / NAK -0x07 Query operation buffer size none ACK + 16bit size / NAK -0x08 Query maximum write-n length none ACK + 24bit length (0==2^24) / NAK -0x09 Read byte 24-bit addr ACK + BYTE / NAK -0x0A Read n bytes 24-bit addr + 24-bit length ACK + length bytes / NAK -0x0B Initialize operation buffer none ACK / NAK -0x0C Write to opbuf: Write byte 24-bit addr + 8-bit byte ACK / NAK (NOTE: takes 5 bytes in opbuf) -0x0D Write to opbuf: Write n 24-bit length + 24-bit addr + ACK / NAK (NOTE: takes 7+n bytes in opbuf) - + length bytes of data -0x0E Write to opbuf: delay 32-bit usecs ACK / NAK (NOTE: takes 5 bytes in opbuf) -0x0F Execute operation buffer none ACK / NAK -0x10 Sync NOP none NAK + ACK (for synchronization) -0x11 Query maximum read-n length none ACK + 24-bit length (0==2^24) / NAK -0x12 Set used bustype 8-bit flags (as with 0x05) ACK / NAK -0x13 Perform SPI operation 24-bit slen + 24-bit rlen ACK + rlen bytes of data / NAK - + slen bytes of data -0x14 Set SPI clock frequency in Hz 32-bit requested frequency ACK + 32-bit set frequency / NAK -0x15 Toggle flash chip pin drivers 8-bit (0 disable, else enable) ACK / NAK -0x?? unimplemented command - invalid. - +======== =============================== ================================================== ================================================= +COMMAND Description Parameters Return Value +======== =============================== ================================================== ================================================= +0x00 NOP none ACK +0x01 Query programmer iface version none ACK + 16bit version (nonzero) +0x02 Query supported commands bitmap none ACK + 32 bytes (256 bits) of supported cmds flags +0x03 Query programmer name none ACK + 16 bytes string (null padding) / NAK +0x04 Query serial buffer size none ACK + 16bit size / NAK +0x05 Query supported bustypes none ACK + 8-bit flags (as per flashrom) / NAK +0x06 Query connected address lines none ACK + 8bit line count / NAK +0x07 Query operation buffer size none ACK + 16bit size / NAK +0x08 Query maximum write-n length none ACK + 24bit length (0==2^24) / NAK +0x09 Read byte 24-bit addr ACK + BYTE / NAK +0x0A Read n bytes 24-bit addr + 24-bit length ACK + length bytes / NAK +0x0B Initialize operation buffer none ACK / NAK +0x0C Write to opbuf: Write byte 24-bit addr + 8-bit byte ACK / NAK (NOTE: takes 5 bytes in opbuf) +0x0D Write to opbuf: Write n 24-bit length + 24-bit addr + length bytes of data ACK / NAK (NOTE: takes 7+n bytes in opbuf) +0x0E Write to opbuf: delay 32-bit usecs ACK / NAK (NOTE: takes 5 bytes in opbuf) +0x0F Execute operation buffer none ACK / NAK +0x10 Sync NOP none NAK + ACK (for synchronization) +0x11 Query maximum read-n length none ACK + 24-bit length (0==2^24) / NAK +0x12 Set used bustype 8-bit flags (as with 0x05) ACK / NAK +0x13 Perform SPI operation 24-bit slen + 24-bit rlen + slen bytes of data ACK + rlen bytes of data / NAK +0x14 Set SPI clock frequency in Hz 32-bit requested frequency ACK + 32-bit set frequency / NAK +0x15 Toggle flash chip pin drivers 8-bit (0 disable, else enable) ACK / NAK +0x16 Set SPI Chip Select 8-bit ACK / NAK +0x17 Set SPI Mode 8-bit ACK / NAK +0x18 Set CS Mode 8-bit ACK / NAK +0x?? unimplemented command - invalid +======== =============================== ================================================== ================================================= Additional information of the above commands: + About unimplemented commands / startup sequence: Only commands allowed to be used without checking anything are 0x00,0x10 and 0x01 (NOP,SYNCNOP,Q_IFACE). If 0x01 doesn't return 1, dont do anything if you dont support a newer protocol. Then, check support for any other opcode (except 0x02) by using 0x02 (Q_CMDMAP). + 0x02 (Q_CMDMAP): The map's bits are mapped as follows: cmd 0 support: byte 0 bit 0 cmd 1 support: byte 0 bit 1 cmd 7 support: byte 0 bit 7 cmd 8 support: byte 1 bit 0, and so on. + 0x04 (Q_SERBUF): If the programmer has a guaranteed working flow control, it should return a big bogus value - eg 0xFFFF. + 0x05 (Q_BUSTYPE): The bit's are defined as follows: bit 0: PARALLEL, bit 1: LPC, bit 2: FWH, bit 3: SPI. + 0x06 (Q_CHIPSIZE): Only applicable to parallel programmers. An LPC/FWH/SPI-programmer can report this as not supported in the command bitmap. + 0x08 (Q_WRNMAXLEN): If a programmer reports a bigger maximum write-n length than the serial buffer size, it is assumed that the programmer can process the data fast enough to take in the reported maximum write-n without problems. + 0x0F (O_EXEC): Execute operation buffer will also clear it, regardless of the return value. + 0x11 (Q_RDNMAXLEN): If this command is not supported, assume return of 0 (2^24). + 0x12 (S_BUSTYPE): Set's the used bustype if the programmer can support more than one flash protocol. Sending a byte with more than 1 bit set will make the programmer decide among them on it's own. Bit values as with Q_BUSTYPE. + 0x13 (O_SPIOP): Send and receive bytes via SPI. Maximum slen is Q_WRNMAXLEN in case Q_BUSTYPE returns SPI only or S_BUSTYPE was used to set SPI exclusively before. Same for rlen and Q_RDNMAXLEN. This operation is immediate, meaning it doesn't use the operation buffer. + 0x14 (S_SPI_FREQ): Set the SPI clock frequency. The 32-bit value indicates the requested frequency in Hertz. Value 0 is reserved and should @@ -83,12 +106,37 @@ Additional information of the above commands: lower than the one requested. If there is no lower frequency available the lowest possible should be used. The value chosen is sent back in the reply with an ACK. - 0x15 (S_CMD_S_PIN_STATE): + + 0x15 (S_PIN_STATE): Sets the state of the pin drivers connected to the flash chip. Disabling them allows other devices (e.g. a mainboard's chipset) to access the chip. This way the serprog controller can remain attached to the flash chip even when the board is running. The user is responsible to NOT connect VCC and other permanently externally driven signals to the programmer as needed. If the value is 0, then the drivers should be disabled, otherwise they should be enabled. + + 0x16 (S_SPI_CS): + Set which SPI Chip Select pin to use. This operation is immediate, + meaning it doesn't use the operation buffer. + + 0x17 (S_SPI_MODE): + Set which SPI Mode to use for 0x13 O_SPIOP commands. + This operation is immediate, meaning it doesn't use the operation buffer. + The current defined modes are: + + * 0x00: SPI Half Duplex (default) + * 0x01: SPI Full Duplex + + 0x18 (S_CS_MODE): + Set which CS Mode to use. The CS Mode determines the CS behaviour. + This allows manual control over the CS. + This operation is immediate, meaning it doesn't use the operation buffer. + The current defined modes are: + + * 0x00: CS Auto Mode. The CS gets selected before 0x13 O_SPIOP commands and + deselected afterwards. (default) + * 0x01: CS Selected. The CS will be selected until another mode is set. + * 0x02: CS Deselected. The CS will be deselected until another mode is set. + About mandatory commands: The only truly mandatory commands for any device are 0x00, 0x01, 0x02 and 0x10, but one can't really do anything with these commands. @@ -99,4 +147,4 @@ Additional information of the above commands: In addition, support for these commands is recommended: S_CMD_Q_PGMNAME, S_CMD_Q_BUSTYPE, S_CMD_Q_CHIPSIZE (if parallel). -See also serprog.h. +See also ``serprog.c`` diff --git a/doc/supported_hw/supported_prog/serprog/teensy_3_1.rst b/doc/supported_hw/supported_prog/serprog/teensy_3_1.rst new file mode 100644 index 000000000..2336387c5 --- /dev/null +++ b/doc/supported_hw/supported_prog/serprog/teensy_3_1.rst @@ -0,0 +1,81 @@ +================================ +Teensy 3.1 SPI + LPC/FWH Flasher +================================ + +Note: this was made for the Teensy 3.1, but 3.2 should be compatible too. + +Hardware +======== + +.. image:: 300px-Teensy31_lpcspi_flasher.jpg + +The hardware is made of a `Teensy 3.1 `_ and a shield-like PCB over it. +Schematic and board files for the PCB can be found `in the github `_. +The PCB is also shared `at OshPark `_. + +Other components required: + +* pin headers (total 28, but get more) +* a DIL8 socket (if you want to use SPI DIL8) +* a PLCC32 SMD socket (if you want to use LPC/FWH) +* optional: small SMD capacitor - pad exists under the shield PCB + +Assembly +-------- + +* start by installing the SMD cap (if available) and the DIL8 socket on the shield PCB +* split appropriate strips of pin headers for the teensy and solder them on the teensy, you can use the shield pcb to align them + + * my arrangement was as pictured in order to have more ground clearance under the teensy for the prog button + +* push the shield pcb only a little bit on the pin headers, just so the headers dont come over the top of the PCB +* solder two corner pins to keep the shield PCB in place, these can be done from above +* solder the rest of headers from the underside while watching that you dont flood the topside with too much solder, especially for the ones close to the PLCC socket +* in order to solder the SMD PLCC32 socket, you'll need to break out the middle plastic bit, but keep it safe + + * to protect from solder bridges forming between the pin headers and PLCC socket, i placed a very thin tape over the pin header holes on the pcb during the soldering + * notice that the PLCC footprint isnt centered on the PCB, meaning dont try to align the PLCC socket exactly on the PCB + +* after soldering the PLCC socket, i installed the plastic bit back with a little bit of glue + +Software +======== + +Firmware for the Teensy is available at https://github.com/urjaman/frser-teensyflash + +Also see the README in that directory, both it or this document might be outdated ;) + +As of writing the setup would be: + +* download arduino, extract it somewhere where you have write access +* download the `Teensyduino thingy `_ +* run it on that arduino tree +* install the udev rules provided in the above url +* compile and install the `teensy_loader_cli `_ in your path + + :: + + git clone --recursive https://github.com/urjaman/frser-teensyflash.git + cd frser-teensyflash + nano Makefile # Edit the TEENSYDIR path to include your arduino directory + make + make program-cli # If this waits you need to press the PROG button on the teensy + +After this you should be able to use it with flashrom serprog, for speedups and enhancements to serprog before they're upstreamed +I'd suggest to use this flashrom tree: https://github.com/urjaman/flashrom/tree/sp-upstream3 + +Device should be something like /dev/ttyACM0 and the baudrate doesnt matter:: + + flashrom -p serprog:dev=/dev/ttyACM0:2000000 + +ISP Usage +--------- + +The same software could be used on a bare teensy 3.1 for ISP SPI programming - this is untested and also the 3.3V supply in the teensy is not strong, so beware, but the SPI pins used would be: + +* CS: "Pin 2", PD0 +* SCK: "Pin 14", PD1 +* MOSI: "Pin 7", PD2 +* MISO: "Pin 8", PD3 + +See https://forum.pjrc.com/threads/25643-Combined-Pin-Assignments-card for a good Teensy pinmap picture. diff --git a/doc/user_docs/1200px-DIP_socket_as_SOIC_clip.jpg b/doc/user_docs/1200px-DIP_socket_as_SOIC_clip.jpg new file mode 100644 index 000000000..c3db69231 Binary files /dev/null and b/doc/user_docs/1200px-DIP_socket_as_SOIC_clip.jpg differ diff --git a/doc/user_docs/Amd_am29f010_tsop32.jpg b/doc/user_docs/Amd_am29f010_tsop32.jpg new file mode 100644 index 000000000..faf0982d2 Binary files /dev/null and b/doc/user_docs/Amd_am29f010_tsop32.jpg differ diff --git a/doc/user_docs/Bios_savior.jpg b/doc/user_docs/Bios_savior.jpg new file mode 100644 index 000000000..91d5557b2 Binary files /dev/null and b/doc/user_docs/Bios_savior.jpg differ diff --git a/doc/user_docs/Dip32_chip.jpg b/doc/user_docs/Dip32_chip.jpg new file mode 100644 index 000000000..5eede283c Binary files /dev/null and b/doc/user_docs/Dip32_chip.jpg differ diff --git a/doc/user_docs/Dip32_chip_back.jpg b/doc/user_docs/Dip32_chip_back.jpg new file mode 100644 index 000000000..f564505ee Binary files /dev/null and b/doc/user_docs/Dip32_chip_back.jpg differ diff --git a/doc/user_docs/Dip32_in_socket.jpg b/doc/user_docs/Dip32_in_socket.jpg new file mode 100644 index 000000000..38467a328 Binary files /dev/null and b/doc/user_docs/Dip32_in_socket.jpg differ diff --git a/doc/user_docs/Dip8_chip.jpg b/doc/user_docs/Dip8_chip.jpg new file mode 100644 index 000000000..b1afb4193 Binary files /dev/null and b/doc/user_docs/Dip8_chip.jpg differ diff --git a/doc/user_docs/Dip8_chip_back.jpg b/doc/user_docs/Dip8_chip_back.jpg new file mode 100644 index 000000000..768e17a97 Binary files /dev/null and b/doc/user_docs/Dip8_chip_back.jpg differ diff --git a/doc/user_docs/Dip8_in_socket.jpg b/doc/user_docs/Dip8_in_socket.jpg new file mode 100644 index 000000000..0450cbcd5 Binary files /dev/null and b/doc/user_docs/Dip8_in_socket.jpg differ diff --git a/doc/user_docs/Dip_tool.jpg b/doc/user_docs/Dip_tool.jpg new file mode 100644 index 000000000..60633339d Binary files /dev/null and b/doc/user_docs/Dip_tool.jpg differ diff --git a/doc/user_docs/Dual_plcc32_soldered.jpg b/doc/user_docs/Dual_plcc32_soldered.jpg new file mode 100644 index 000000000..7d742511a Binary files /dev/null and b/doc/user_docs/Dual_plcc32_soldered.jpg differ diff --git a/doc/user_docs/Empty_dip32_socket.jpg b/doc/user_docs/Empty_dip32_socket.jpg new file mode 100644 index 000000000..0c44c3aaa Binary files /dev/null and b/doc/user_docs/Empty_dip32_socket.jpg differ diff --git a/doc/user_docs/Empty_dip8_socket.jpg b/doc/user_docs/Empty_dip8_socket.jpg new file mode 100644 index 000000000..22e843bb2 Binary files /dev/null and b/doc/user_docs/Empty_dip8_socket.jpg differ diff --git a/doc/user_docs/Empty_plcc32_socket.jpg b/doc/user_docs/Empty_plcc32_socket.jpg new file mode 100644 index 000000000..acd20b1d8 Binary files /dev/null and b/doc/user_docs/Empty_plcc32_socket.jpg differ diff --git a/doc/user_docs/Flash-BGA.jpg b/doc/user_docs/Flash-BGA.jpg new file mode 100644 index 000000000..2eb059bc4 Binary files /dev/null and b/doc/user_docs/Flash-BGA.jpg differ diff --git a/doc/user_docs/Plcc32_chip.jpg b/doc/user_docs/Plcc32_chip.jpg new file mode 100644 index 000000000..3a0193a50 Binary files /dev/null and b/doc/user_docs/Plcc32_chip.jpg differ diff --git a/doc/user_docs/Plcc32_chip_back.jpg b/doc/user_docs/Plcc32_chip_back.jpg new file mode 100644 index 000000000..f01690095 Binary files /dev/null and b/doc/user_docs/Plcc32_chip_back.jpg differ diff --git a/doc/user_docs/Plcc32_in_socket.jpg b/doc/user_docs/Plcc32_in_socket.jpg new file mode 100644 index 000000000..241794cc7 Binary files /dev/null and b/doc/user_docs/Plcc32_in_socket.jpg differ diff --git a/doc/user_docs/Plcc_tool.jpg b/doc/user_docs/Plcc_tool.jpg new file mode 100644 index 000000000..3d3b80154 Binary files /dev/null and b/doc/user_docs/Plcc_tool.jpg differ diff --git a/doc/user_docs/Pomona_5250_soic8.jpg b/doc/user_docs/Pomona_5250_soic8.jpg new file mode 100644 index 000000000..83f8c3e23 Binary files /dev/null and b/doc/user_docs/Pomona_5250_soic8.jpg differ diff --git a/doc/user_docs/Pushpin_roms_2.jpg b/doc/user_docs/Pushpin_roms_2.jpg new file mode 100644 index 000000000..c4ce5aef3 Binary files /dev/null and b/doc/user_docs/Pushpin_roms_2.jpg differ diff --git a/doc/user_docs/Soic8_chip.jpg b/doc/user_docs/Soic8_chip.jpg new file mode 100644 index 000000000..d103c7d23 Binary files /dev/null and b/doc/user_docs/Soic8_chip.jpg differ diff --git a/doc/user_docs/Soic8_socket_back.jpg b/doc/user_docs/Soic8_socket_back.jpg new file mode 100644 index 000000000..49504e2c6 Binary files /dev/null and b/doc/user_docs/Soic8_socket_back.jpg differ diff --git a/doc/user_docs/Soic8_socket_front_closed.jpg b/doc/user_docs/Soic8_socket_front_closed.jpg new file mode 100644 index 000000000..f6aebd5b4 Binary files /dev/null and b/doc/user_docs/Soic8_socket_front_closed.jpg differ diff --git a/doc/user_docs/Soic8_socket_half_opened.jpg b/doc/user_docs/Soic8_socket_half_opened.jpg new file mode 100644 index 000000000..f4d5730d6 Binary files /dev/null and b/doc/user_docs/Soic8_socket_half_opened.jpg differ diff --git a/doc/user_docs/Soic8_socket_open.jpg b/doc/user_docs/Soic8_socket_open.jpg new file mode 100644 index 000000000..69b4e744e Binary files /dev/null and b/doc/user_docs/Soic8_socket_open.jpg differ diff --git a/doc/user_docs/Soic8_socket_with_chip.jpg b/doc/user_docs/Soic8_socket_with_chip.jpg new file mode 100644 index 000000000..322f6383c Binary files /dev/null and b/doc/user_docs/Soic8_socket_with_chip.jpg differ diff --git a/doc/user_docs/Soic8_socket_with_chip_inserted.jpg b/doc/user_docs/Soic8_socket_with_chip_inserted.jpg new file mode 100644 index 000000000..37af90d75 Binary files /dev/null and b/doc/user_docs/Soic8_socket_with_chip_inserted.jpg differ diff --git a/doc/user_docs/Soldered_plcc32.jpg b/doc/user_docs/Soldered_plcc32.jpg new file mode 100644 index 000000000..8a3a6cdc5 Binary files /dev/null and b/doc/user_docs/Soldered_plcc32.jpg differ diff --git a/doc/user_docs/Soldered_tsop40.jpg b/doc/user_docs/Soldered_tsop40.jpg new file mode 100644 index 000000000..1fcf2efb1 Binary files /dev/null and b/doc/user_docs/Soldered_tsop40.jpg differ diff --git a/doc/user_docs/Soldered_tsop48.jpg b/doc/user_docs/Soldered_tsop48.jpg new file mode 100644 index 000000000..3df63eef8 Binary files /dev/null and b/doc/user_docs/Soldered_tsop48.jpg differ diff --git a/doc/user_docs/Spi-socket-dscn2913-1024x768.jpg b/doc/user_docs/Spi-socket-dscn2913-1024x768.jpg new file mode 100644 index 000000000..3b20ae09b Binary files /dev/null and b/doc/user_docs/Spi-socket-dscn2913-1024x768.jpg differ diff --git a/doc/user_docs/Sst_39vf040_tsop32.jpg b/doc/user_docs/Sst_39vf040_tsop32.jpg new file mode 100644 index 000000000..beefeba98 Binary files /dev/null and b/doc/user_docs/Sst_39vf040_tsop32.jpg differ diff --git a/doc/user_docs/Top_hat_flash.jpeg b/doc/user_docs/Top_hat_flash.jpeg new file mode 100644 index 000000000..8edd27e8d Binary files /dev/null and b/doc/user_docs/Top_hat_flash.jpeg differ diff --git a/doc/user_docs/chromebooks.rst b/doc/user_docs/chromebooks.rst new file mode 100644 index 000000000..feb333b3f --- /dev/null +++ b/doc/user_docs/chromebooks.rst @@ -0,0 +1,8 @@ +============================= +Documentation for Chromebooks +============================= + +Below is the list of documents and pages that can be useful if you use flashrom on ChromeOS. +Note these documents are external to flashrom and maintained outside of upstream flashrom tree. + +* `Write protection `_ diff --git a/doc/user_docs/example_partial_wp.rst b/doc/user_docs/example_partial_wp.rst new file mode 100644 index 000000000..811c772fc --- /dev/null +++ b/doc/user_docs/example_partial_wp.rst @@ -0,0 +1,191 @@ +=================================== +Example of partial write-protection +=================================== + +This document provides demonstration of how one can protect part of a flash chip +from writing using :code:`flashrom` and its support for manipulating SPI write protection (WP). +This kind of protection requires changing connection of WP pin of the chip to prevent +any attempt of disabling the protection by software alone. + +Not to be confused with protection by flash controller of your motherboard (PCH protection). + +Version of flashrom +=================== + +Write-protect manipulation functionality is included in flashrom since release v1.3.0. +If for any reasons you need the latest code from head, you might need to build :code:`flashrom` +from scratch. The following doc describe how to do this: :doc:`/dev_guide/building_from_source`. +See also :doc:`/dev_guide/development_guide`. + +Alternatively, your operating system might provide development version of :code:`flashrom` as a package. + +Programmer support of WP +======================== + +Not all programmers support manipulating WP configuration. A suitable programmer must either +provide a dedicated API for working with WP or give sufficiently comprehensive access to the +interface of the flash chip. + +In particular, *internal* programmer on Intel platforms might allow only limited access to WP +feature of chips or effectively deny it. Read "Intel chipsets" section of flashrom's manpage +for details on how you can try choosing sequencing type to possibly make WP work for you. + +In some cases external flashing might be the only option and you need to unscrew your device, +find the chip, connect it to another device through a suitable adapter and finally be able +to configure it as you wish. + +Chip support in flashrom +======================== + +There is a great variety of chips with some not supporting write protection at all and others +doing it in their own peculiar way of which :code:`flashrom` has no idea. So the first thing to do is +to make sure that :code:`flashrom` knows how WP works for your chip and chipset doesn't get in the way. +Run a command like (adjust this and similar commands below if you're not using *internal* programmer +or need to specify other options):: + + flashrom --programmer internal --wp-status: + +Seeing this output line would mean that :code:`flashrom` doesn't know how to use WP feature of the chip you have:: + + Failed to get WP status: WP operations are not implemented for this chip + +Otherwise the output might contain something similar to this:: + + Protection range: start=0x00000000 length=0x00000000 (none) + Protection mode: disabled + +If so, you can continue with the rest of the instructions. + +Collecting information about the range +====================================== + +You need to know where the area you want to protect starts and ends. The example below assumes +you're trying to protect bootblock stored in CBFS at the end of some :code:`coreboot` firmware. In other cases +it might be a separate file which is put at the beginning of a chip. You need to have an idea of what +you're doing here or have some reliable instructions to follow. + +In this case :code:`cbfstool` can be used to list information about bootblock like this:: + + $ cbfstool rom print | sed -n '2p; /bootblock/p' + Name Offset Type Size Comp + bootblock 0x3ef100 bootblock 36544 none + +However, the offset is relative to the start of CBFS region, so we also need to find out offset of CBFS:: + + $ cbfstool rom layout | grep CBFS + 'COREBOOT' (CBFS, size 4161536, offset 12615680) + +Now we can calculate: + +* start offset (CBFS offset + 64 + bootblock offset):: + + 12615680 + 64 + 0x3ef100 = 0xff7140 + (printf "%#x\n" $(( 12615680 + 64 + 0x3ef100 ))) + +* end offset (start offset + bootblock size - 1):: + + 0xff7140 + 36544 - 1 = 0xffffff + (printf "%#x\n" $(( 0xff7140 + 36544 - 1 ))) + +Thus we need to write-protect the smallest area that covers the range from :code:`0xff7140` to :code:`0xffffff` +(both bounds are inclusive). + +“64” in the computation of start offset is offset of booblock data. Unfortunately, current tooling +doesn't provide a reliable way of determining actual offset, but 64 is the typical “extra offset” one needs +to add to account for file metadata of CBFS (otherwise it can be its multiple 128 or bigger). Bootblock +should normally end at the last byte of ROM on x86 systems, giving you a way to test the result of computations. + +Finding a matching range +======================== + +In most chips the list of supported ranges is fixed and you can't specify an arbitrary one. Some others +allow more fine-grained control (sector/block-based), but that feature is not supported even by development +version of flashrom at the time of writing (September 2023). + +Obtain list of supported ranges from which we'll pick the best match:: + + $ flashrom --programmer internal --wp-list + ... + Available protection ranges: + start=0x00000000 length=0x00000000 (none) + start=0x00000000 length=0x00001000 (lower 1/4096) + start=0x00fff000 length=0x00001000 (upper 1/4096) + start=0x00000000 length=0x00002000 (lower 1/2048) + start=0x00ffe000 length=0x00002000 (upper 1/2048) + start=0x00000000 length=0x00004000 (lower 1/1024) + start=0x00ffc000 length=0x00004000 (upper 1/1024) + start=0x00000000 length=0x00008000 (lower 1/512) + start=0x00ff8000 length=0x00008000 (upper 1/512) + start=0x00000000 length=0x00040000 (lower 1/64) + start=0x00fc0000 length=0x00040000 (upper 1/64) + start=0x00000000 length=0x00080000 (lower 1/32) + start=0x00f80000 length=0x00080000 (upper 1/32) + start=0x00000000 length=0x00100000 (lower 1/16) + start=0x00f00000 length=0x00100000 (upper 1/16) + start=0x00000000 length=0x00200000 (lower 1/8) + start=0x00e00000 length=0x00200000 (upper 1/8) + start=0x00000000 length=0x00400000 (lower 1/4) + start=0x00c00000 length=0x00400000 (upper 1/4) + start=0x00000000 length=0x00800000 (lower 1/2) + start=0x00800000 length=0x00800000 (upper 1/2) + start=0x00000000 length=0x00c00000 (lower 3/4) + start=0x00400000 length=0x00c00000 (upper 3/4) + start=0x00000000 length=0x00e00000 (lower 7/8) + start=0x00200000 length=0x00e00000 (upper 7/8) + start=0x00000000 length=0x00f00000 (lower 15/16) + start=0x00100000 length=0x00f00000 (upper 15/16) + start=0x00000000 length=0x00f80000 (lower 31/32) + start=0x00080000 length=0x00f80000 (upper 31/32) + start=0x00000000 length=0x00fc0000 (lower 63/64) + start=0x00040000 length=0x00fc0000 (upper 63/64) + start=0x00000000 length=0x00ff8000 (lower 511/512) + start=0x00008000 length=0x00ff8000 (upper 511/512) + start=0x00000000 length=0x00ffc000 (lower 1023/1024) + start=0x00004000 length=0x00ffc000 (upper 1023/1024) + start=0x00000000 length=0x00ffe000 (lower 2047/2048) + start=0x00002000 length=0x00ffe000 (upper 2047/2048) + start=0x00000000 length=0x00fff000 (lower 4095/4096) + start=0x00001000 length=0x00fff000 (upper 4095/4096) + start=0x00000000 length=0x01000000 (all) + +Pick a range by scanning the list in the top down order (because the smaller ranges come first): + + * if bootblock is at the start of a chip, look for the first lower range whose length is greater than the end offset + * if bootblock is at the end of a chip, look for the first upper range which starts before or at the start offset + * mind that you're unlikely to find an ideal match and will probably protect more than you need; this is fine + if that's just an empty space, but can cause trouble with future updates if that's some data or metadata which + changes with every release (see :doc:`fw_updates_vs_spi_wp` for more on this) + +This is the first upper range starting before 0xff7140:: + + start=0x00fc0000 length=0x00040000 (upper 1/64) + +It covers :code:`0x00fc0000 - 0x00ffffff` which includes our bootblock. This area takes up 256 KiB, about 7 times bigger +than our bootblock, but there is no better choice in this case and output of :code:`cbfstool rom layout` shows +that we additionally include a part of 876 KiB empty space which will hopefully remain there in future firmware versions +(it's a good idea to check before a firmware update). + +Protection setup +================ + +The following command sets the range and enables WP at the same time, the values are taken from the chosen range above:: + + flashrom --programmer internal --wp-range=0x00fc0000,0x00040000 --wp-enable + +You can set the range and change WP status independently as well if needed (just specify one :code:`--wp-*` option at a time). +Make sure that hardware protection is off (state of :code:`W#`/:code:`W/` pin of the chip) or you won't be able +to change WP configuration. + +On success, the output of the above command will include such lines:: + + Enabled hardware protection + Activated protection range: start=0x00fc0000 length=0x00040000 (upper 1/64) + +**Caveat:** :code:`flashrom` automatically tries to disable WP before any operation on a chip (read, write, erase, verify), +so double-check status of WP before changing state of WP pin on your chip! + +Verifying hardware protection +============================= + +Once you're happy with the configuration and changed state of WP pin, you can try disabling WP +using :code:`flashrom --wp-disable` to make sure that it fails now. diff --git a/doc/user_docs/fw_updates_vs_spi_wp.rst b/doc/user_docs/fw_updates_vs_spi_wp.rst new file mode 100644 index 000000000..43bcbe04e --- /dev/null +++ b/doc/user_docs/fw_updates_vs_spi_wp.rst @@ -0,0 +1,60 @@ +======================================== +Firmware updates vs SPI write-protection +======================================== + +Enabling write-protection of any kind is meant to obstruct changing data, but it also limits +what you can do to the part of firmware that's still writable. This document is meant to cover +some of the origins of such limitations and situations which might arise after +part of a flash chip has been protected. + +Firmware updates after locking bootblock +======================================== + +This section is primarily concerned with :code:`coreboot` with bootblock being protected from writing, +but similar problems can happen for any kind of firmware. + +Risks of partial updates +------------------------ + +Partial updates can produce an unbootable image if an old bootblock doesn't work with a more recent +version of :code:`coreboot`. This can be manifested in various ways ranging from an old bootblock not being able +to find new romstage to system booting successfully but data in :code:`coreboot` tables being mangled or incomplete. + +The incompatibilities might happen when switching version of firmware or even when using the same version +with a slightly different configuration. + +Another thing that can potentially cause trouble is CBFS layout. When bootblock is part of CBFS, +it doesn't necessarily have a fixed address, moreover it can change location as well if it depends on file size +(when bootblock's last byte must be the last byte of the image, which is the case on x86). If newer bootblock +is smaller such that an old WP range now covers bootblock and some other file, this file won't be fully updated +due to write-protection, potentially resulting in a corrupt image. Luckily, when bootblock is the last file +it's normally preceded by a significant amount of empty space, which won't let this situation to occur. + +On top of that, last 4 bytes of the image contain offset to the master header of CBFS. Depending on +the :code:`coreboot` version this offset might be crucial for the loading of romstage, in which case moving CBFS +within the image without updating the offset (when it's locked by WP) can also prevent the system from booting. + +Recovering from a broken state +------------------------------ + +Since broken flash won't let the system to boot, the way to fix it is to flash the chip externally by connecting +it to a different device. A possible alternative could be to have a backup flash created beforehand and swapping +it for the broken one (not very applicable if swapping doesn't require soldering). There are also some mainboards +with dual flash chips one of which acts as a backup that can be restored by holding power on button long enough. + +Flashing whole firmware image +============================= + +The function of the hardware protection mechanism (:code:`W#` or :code:`W/` pin of flash chips) is to lock state of +software protection thus preventing it from being disabled. After the chip is physically unlocked by changing +the state of the pin, the state of the write protection doesn't change. However, in this state the protection +can be easily turned off programmatically, which is what :code:`flashrom` tries to do before performing an operation on a chip. + +In other words, changing state of the WP pin might be enough to be able to flash the chip in full. +If :code:`flashrom` errors or you don't want to rely on the automatic behaviour, you can try to +explicitly disable the protection by running :code:`flashrom` like this:: + + flashrom --wp-disable + +If you need to pass extra parameters to flash your chip (e.g., programmer or chip name), add them to the above command +(order of such parameters shouldn't matter). diff --git a/doc/user_docs/in_system.rst b/doc/user_docs/in_system.rst new file mode 100644 index 000000000..84716d38c --- /dev/null +++ b/doc/user_docs/in_system.rst @@ -0,0 +1,45 @@ +===================== +In-System Programming +===================== + +**In-System Programming** (ISP) sometimes also called **in situ programming** is used to describe +the procedure of writing a flash chip while it is (already/still) attached to the circuit +it is to be used with. Of course any normal "BIOS flash" procedure is a kind of ISP +but when we refer to ISP we usually mean something different: programming a flash chip by external means +while it is mounted on a motherboard. + +This is usually done with SPI chips only. Some mainboards have a special header for this +(often named "ISP", "ISP1", or "SPI") and there should be no problem with accessing the chip +then as long as the wires are not too long. + +If there is no special header then using a special SO(IC) clip is an easy and reliable way +to attach an external programmer. They are produced by different vendors (e.g. Pomona, 3M) +and are available from many distributors (e.g. Distrelec) for 20-50$/€. + +Problems +======== + +* Check the other potential problems (:doc:`misc_notes`) with other types of programming setups first. +* The SPI bus is not isolated enough. Often parts of the chipset are powered on partially + (by the voltage supplied via the Vcc pin of the flash chip). In that case + disconnect Vcc from the programmer and power it with its normal PSU and: + + * Try powering up the board normally and holding it in reset (e.g. use a jumper instead of the reset push button). + * Some chipsets (e.g. Intel ICHs/PCHs) have edge triggered resets. In this case holding them in reset will not work. + This is especially a problem with Intel chipsets because they contain an EC (named ME by Intel, see :doc:`management_engine`), + which uses the flash (r/w!). In this case you can trigger the reset line in short intervals. + For example by connecting it to the chip select (CS) line of the SPI bus or a dedicated clock signal from the programmer. + This should not be too fast though! Reset lines usually require pulses with a minimum duration. + * On some boards, you can try disconnecting the ATX12V header (yellow/black wires only) from the motherboard, + or even remove the CPU or RAM - if the programmer supports SPI sniffing, you may be able to verify that the there is no SPI traffic. + +Images +======== + +Pomona 8-pin SOIC clip with attached jumper wires. + +.. image:: Pomona_5250_soic8.jpg + +A cheap, but very fragile alternative: DIP socket as clip + +.. image:: 1200px-DIP_socket_as_SOIC_clip.jpg diff --git a/doc/user_docs/index.rst b/doc/user_docs/index.rst new file mode 100644 index 000000000..e03789ebf --- /dev/null +++ b/doc/user_docs/index.rst @@ -0,0 +1,17 @@ +Users documentation +=================== + +.. toctree:: + :maxdepth: 1 + + overview + fw_updates_vs_spi_wp + example_partial_wp + chromebooks + management_engine + misc_intel + in_system + msi_jspi1 + misc_notes + +.. Keep misc notes last diff --git a/doc/user_docs/management_engine.rst b/doc/user_docs/management_engine.rst new file mode 100644 index 000000000..f1cf3fcff --- /dev/null +++ b/doc/user_docs/management_engine.rst @@ -0,0 +1,45 @@ +====================== +ME (Management Engine) +====================== + +ME stands for Management Engine (or Manageability Engine) and refers to an Embedded Controller found in Intel chipsets. It uses different versions +of an `ARC `_ 32-bit microcontroller that runs its own operating system independently from the user's. +The ME has access to all kinds of buses which allows for out-of-band processing which is used for features +like `Active Management Technology `_, but it makes it also a very interesting target for black hats. +The firmware it runs is secured by certificates stored in ROM, but it is a complex beast and it is very unlikely that there is +no `way around its security measures `_ (intentional backdoors included). +For further details about the ME please see these excellent `slides by Igor Skochinsky `_ +and the `Security Evaluation of AMT by Vassilios Ververis `_. + +Effects on flashrom +=================== + +The firmware of the ME usually shares the flash memory with the firmware of the host PC (BIOS/UEFI/coreboot). +The address space is separated into regions (similar to partitions on a harddisk). The first one (*Descriptor region*) +contains configuration data which contains something similar to a partition table and access rights for the different devices that can access the flash +(host CPU, ME, GbE controller). These restrictions are enforced by the chipset's SPI controller which is the main interface for flashrom +to access the flash chip(s) attached to the chipset. Intel recommends to set the descriptor region read-only and to forbid reads and writes to the ME region by the host CPU. +Writes by the host could interfere with the code running on the ME. This means that flashrom which runs on the host PC can not access +the ME firmware region of the flash at all in this configuration. flashrom detects that, warns the user and disables write access for safety reasons in that case. + +Unlocking the ME region +======================= + +There are a few ways to enable full access to the ME region, but they are not user friendly at all in general. Also, the Descriptor region is not affected by these actions, +so it is still not possible to access the complete flash memory even when the ME region is unlocked. For the different possibilities please see +the document :doc:`misc_intel`. + +Suggested workarounds +===================== + + * If you just want to update the proprietary firmware of the board use the vendor tool(s). + * If you need full access to the flash chip get an external programmer (see :doc:`/supported_hw/supported_prog/index`) and try in-circuit programming. + * If you only need to update the BIOS region, then you may use the options ``--ifd -i bios --noverify-all`` to write (and verify) only the BIOS region as described in the Intel flash descriptor. + +.. todo:: Migrate page for in-circuit programming (ISP) + +See also +======== + + * The respective `coreboot page on the management engine `_ + * :doc:`misc_intel` diff --git a/doc/user_docs/misc_intel.rst b/doc/user_docs/misc_intel.rst new file mode 100644 index 000000000..dca535eee --- /dev/null +++ b/doc/user_docs/misc_intel.rst @@ -0,0 +1,205 @@ +======================== +Miscellaneous Intel info +======================== + +BBAR on ICH8 +============ + +There is no sign of BBAR (BIOS Base Address Configuration Register) in the +public datasheet (or specification update) of the ICH8. Also, the offset of +that register has changed between ICH7 (SPIBAR + 50h) and ICH9 (SPIBAR + +A0h), so we have no clue if or where it is on ICH8. Out current policy is to +not touch it at all and assume/hope it is 0. + +Software Sequencing vs. Hardware Sequencing and the "Opaque flash chip" +======================================================================= + +Software sequencing and hardware sequencing are two methods used to interface +with the SPI controller on Intel platforms. They can be selected using either +ich_spi_mode=swseq or ich_spi_mode=hwseq programmer parameters. Flashrom will +attempt to automatically detect which mode to use. + +Software sequencing is the traditional method whereby software running on the +CPU handles most of the logic needed to interact with the flash chip. This +offers good flexibility since the user can utilize any opcode available in the +OPMENU registers, and OPMENU can be left unlocked or on coreboot-supported +platforms the owner of the system may program it for their needs before locking +it. Advanced or non-standard features of a chip such as write protection and +OTP may therefore be directly utilized by software. + +Hardware sequencing is a newer method (since around 2011) whereby most of the +logic for interacting with the SPI flash chip is contained within the SPI +controller itself and software such as flashrom may only select a few operations +chosen by Intel via the Flash Cycle (FCYCLE) field. The chip must conform to +specifications from Intel for each chipset/PCH. The specs are given in the +"SPI Programming Guide" application note. See [SPI_PROG] cited at the bottom of +this document for an example. + +Hardware sequencing simplifies things from a software perspective since the +software is guaranteed some minimal level of support and doesn't even need to +know the chip's ID or opcodes; it just needs to tell the SPI controller to +perform a type of transaction such as "read", "4k block erase", etc. Hence when +using hardware sequencing one will see "Opaque flash chip" as the chip's +description since software might not be able to identify the chip. The SPI +controller can combine multiple physical flash chips to logically appear as a +single large flash device, and in such cases it would not make sense for +flashrom to try to identify the chip. + +In many non-Intel systems the software has full control of a generic SPI +controller where the software controls the SPI signals and also constructs the +data payload including pre-op (e.g. write enable latch), opcode, address, and +data. Intel SPI flash controllers are purpose-built for flash chip access and +the software does not control the hardware directly. This makes Intel SPI +controllers less flexible from a software standpoint, however there are some +benefits such as guaranteed atomicity and multi-master arbitration needed for +modern Intel platforms where the CPU and various microprocessors can share the +same flash chip. + +SMM BIOS Write Protection +========================= + +Sometimes a hardware vendor will enable "SMM BIOS Write Protect" (SMM_BWP) +in the firmware during boot time. The bits that control SMM_BWP are in the +BIOS_CNTL register in the LPC interface. + +When enabled, the SPI flash can only be written when the system is operating in +in System Management Mode (SMM). In other words, only certain code that was +installed by the BIOS can write to the flash chip. Programs that run in OS +context such as flashrom can still read the flash chip, but cannot write to the +flash chip. + +Flashrom will attempt to detect this and print a warning such as the following: +"Warning: BIOS region SMM protection is enabled!" + +Many vendor-supplied firmware update utilities do not actually write to the ROM; +instead they transfer data to/from memory which is read/written by a routine +running in SMM and is responsible for writing to the firmware ROM. This causes +severe system performance degradataion since all processors must be in SMM +context (ring -2) instead of OS context (ring 0) while the firmware ROM is being +written. + +Accesses beyond region bounds in descriptor mode +================================================ + +Intel's flash image tool will always expand the last region so that it covers +the whole flash chip, but some boards ship with a different configuration. +It seems that in descriptor mode all addresses outside the used regions can not +be accessed whatsoever. This is not specified anywhere publicly as far as we +could tell. flashrom does not handle this explicitly yet. It will just fail +when trying to touch an address outside of any region. +See also http://www.flashrom.org/pipermail/flashrom/2011-August/007606.html + +(Un)locking the ME region +========================= + +If the ME region is locked by the FRAP register in descriptor mode, the host +software is not allowed to read or write any address inside that region. +Although the chipset datasheets specify that "[t]he contents of this register +are that of the Flash Descriptor" [PANTHER], this is not entirely true. +The firmware has to fill at least some of the registers involved. It is not +known when they become read-only or any other details, but there is at least +one HM67-based board, that provides an user-changeable setting in the firmware +user interface to enable ME region updates that lead to a FRAP content that is +not equal to the descriptor region bits [NC9B]. + +There are different ways to unlock access: + + * A pin strap: Flash Descriptor Security Override Strap (as indicated by the + Flash Descriptor Override Pin Strap Status (FDOPSS) in HSFS. That pin is + probably not accessible to end users on consumer boards (every Intel doc i + have seen stresses that this is for debugging in manufacturing only and + should not be available for end users). + The ME indicates this in bits [19:16] (Operation Mode) in the HFS register of + the HECI/MEI PCI device by setting them to 4 (SECOVR_JMPR) [MODE_CTRL]. + + * Intel Management Engine BIOS Extension (MEBx) Disable + This option may be available to end users on some boards usually accessible + by hitting ctrl+p after BIOS POST. Quote: "'Disabling' the Intel ME does not + really disable it: it causes the Intel ME code to be halted at an early stage + of the Intel ME's booting so that the system has no traffic originating from + the Intel ME on any of the buses." [MEBX] The ME indicates this in + bits [19:16] (Operation Mode) in the HFS register of the HECI/MEI PCI device + by setting them to 3 (Soft Temporary Disable) [MODE_CTRL]. + + * Previous to Ibex Peak/5 Series chipsets removing the DIMM from slot (or + channel?) #0 disables the ME completely, which may give the host access to + the ME region. + + * HMRFPO (Host ME Region Flash Protection Override) Enable MEI command + This is the most interesting one because it allows to temporarily disable + the ME region protection by software. The ME indicates this in bits [19:16] + (Operation Mode) in the HFS register of the HECI/MEI PCI device by setting + them to 5 (SECOVER_MEI_MSG) [MODE_CTRL]. + +MEI/HECI +======== + +Communication between the host software and the different services provided by +the ME is done via a packet-based protocol that uses MMIO transfers to one or +more virtual PCI devices. Upon this layer there exist various services that can +be used to read out hardware management values (e.g. temperatures, fan speeds +etc.). The lower levels of that protocol are well documented: +The locations/offsets of the PCI MMIO registers are noted in the chipset +datasheets. The actually communication is documented in a whitepaper [DCMI] and +an outdated as well as a current Linux kernel implementation (currently in +staging/ exist [KERNEL]. There exists a patch that re-implements this in user +space (as part of flashrom). + +Problems +======== + +The problem is that only very few higher level protocols are documented publicly, +especially the bunch of messages that contain the HMRFPO commands is probably +well protected and only documented in ME-specific docs and the BIOS writer's +guides. We are aware of a few leaked documents though that give us a few hints +about it, but nothing substantial regarding its implementation. + +The documents are somewhat contradicting each other in various points which +might be due to factual changes in process of time or due to the different +capabilities of the ME firmwares, example: + +Intel's Flash Programming Tool (FPT) "automatically stops ME writing to SPI +ME Region, to prevent both writing at the same time, causing data corruption." [ME8] + +"FPT is not HMRFPO-capable, so needs [the help of the FDOPS pin] HDA_SDO if +used to update the ME Region." [SPS] + +When looking at the various ME firmware editions (and different chipsets), things +get very unclear. Some docs say that HMRFPO needs to be sent before End-of-POST +(EOP), others say that the ME region can be updated in the field or that some +vendor tools use it for updates. This needs to be investigated further before +drawing any conclusion. + +[PANTHER] + Intel 7 Series Chipset Family Platform Controller Hub (PCH) Datasheet + Document Number: 326776, April 2012, page 857 + +[NC9B] + Jetway NC9B flashrom v0.9.5.2-r1517 log with ME region unlocked. + NB: "FRAP 0e0f" vs. "FLMSTR1 0a0b". + http://paste.flashrom.org/view.php?id=1215 + +[MODE_CTRL] + Client Platform Enabling Tour: Platform Software + Document Number: 439167, Revision 1.2, page 52 + +[MEBX] + Intel Management Engine BIOS Extension (MEBX) User's Guide + Revision 1.2, Section 3.1 and 3.5 + +[DCMI] + DCMI Host Interface Specification + Revision 1.0 + +[SPI_PROG] + Ibex Peak SPI Programming Guide + Document Number: 403598, Revision 1.3, page 79 + +[ME8] + Manufacturing with Intel Management Engine (ME) Firmware 8.X on Intel 7 Series + Revision 2.0, page 59 + +[SPS] + Manufacturing with Intel Management Engine (ME) on Intel C600 Series Chipset 1 + for Romley Server 2 Platforms using Server Platform Services (SPS) Firmware + Revision 2.2, page 51 diff --git a/doc/user_docs/misc_notes.rst b/doc/user_docs/misc_notes.rst new file mode 100644 index 000000000..fcb170065 --- /dev/null +++ b/doc/user_docs/misc_notes.rst @@ -0,0 +1,149 @@ +===================== +Misc notes and advice +===================== + +This document contains miscellaneous and unstructured (and mostly, legacy) notes and advice about using flashrom. + +Command set tricks for parallel and LPC chips +============================================= + +This is only mentioned in very few datasheets, but it applies to some parallel (and some LPC) chips. + +Upper address bits of commands are ignored if they are not mentioned explicitly. If a datasheet specifies the following sequence:: + + chip_writeb(0xAA, bios + 0x555); + chip_writeb(0x55, bios + 0x2AA); + chip_writeb(0x90, bios + 0x555); + +then it is quite likely the following sequence will work as well:: + + chip_writeb(0xAA, bios + 0x5555); + chip_writeb(0x55, bios + 0x2AAA); + chip_writeb(0x90, bios + 0x5555); + +However, if the chip datasheet specifies addresses like ``0x5555``, you can't shorten them to ``0x555``. + +To summarize, replacing short addresses with long addresses usually works, but the other way round usually fails. + +flashrom doesn't work on my board, what can I do? +================================================= + +* First of all, check if your chipset, ROM chip, and mainboard are supported + (see :doc:`/supported_hw/index`). +* If your board has a jumper for BIOS flash protection (check the manual), disable it. +* Should your BIOS menu have a BIOS flash protection option, disable it. +* If you run flashrom on Linux and see messages about ``/dev/mem``, see next section. +* If you run flashrom on OpenBSD, you might need to obtain raw access permission by setting + ``securelevel = -1`` in ``/etc/rc.securelevel`` and rebooting, or rebooting into single user mode. + +What can I do about /dev/mem errors? +==================================== + +* If flashrom tells you ``/dev/mem mmap failed: Operation not permitted``: + + * Most common at the time of writing is a Linux kernel option, ``CONFIG_IO_STRICT_DEVMEM``, + that prevents even the root user from accessing hardware from user-space if the resource is unknown + to the kernel or a conflicting kernel driver reserved it. On Intel systems, this is most often ``lpc_ich``, + so ``modprobe -r lpc_ich`` can help. A more invasive solution is to try again after rebooting + with ``iomem=relaxed`` in the kernel command line. + + * Some systems with incorrect memory reservations (e.g. E820 map) may have the same problem + even with ``CONFIG_STRICT_DEVMEM``. In that case ``iomem=relaxed`` in the kernel command line may help too. + +* If it tells you ``/dev/mem mmap failed: Resource temporarily unavailable``: + + * This may be an issue with PAT (e.g. if the memory flashrom tries to map is already mapped + in an incompatible mode). Try again after rebooting with nopat in the kernel command line. + +* If you see this message ``Can't mmap memory using /dev/mem: Invalid argument``: + + * Your flashrom is very old, better update it. If the issue persists, try the kernel options mentioned above. + +* Generally, if your version of flashrom is very old, an update might help. + Flashrom has less strict requirements now and works on more systems without having to change the kernel. + +Connections +=========== + +Using In-System programming requires some means to connect the external programmer to the flash chip. + +Note that some external flashers (like the Openmoko debug board) lack a connector, +so they do requires some soldering to be used. Some other don't. For instance the buspirate has a pin connector on it. + +Programmer <-> Removable chip connection +---------------------------------------- + +A breadboard can be used to connect Dual in-line 8 pins chips to the programmer, as they they fit well into it. + +Programmer <-> Clip connection +------------------------------ + +If your programmer has a pin connector, and that you want to avoid soldering, you can use +**Short** `Jump Wires `_ to connect it to a clip. +They usually can be found on some electronic shops. + +Other issues +------------- + +* Wires length and connection quality: Long wires, and bad connection can create some issues, so avoid them. + + * The maximum wires length is very dependent on your setup, so try to have the shortest wires possible. + * If you can't avoid long wires and if you're flash chip is SPI, then lowering the SPI clock could make + it work in some cases. Many programmers do support such option (Called spispeed with most of them, or divisor with ft2232_spi). + +* When soldering wires, the wire tend to break near the soldering point. To avoid such issue, + you have to prevent the wires from bending near the soldering point. + To do that `Heat-shrink_tubing `_ or similar methods can be used. + +Common problems +=============== + +The following describes problems commonly found when trying to access flash chips in systems +that are not designed properly for this job, e.g. ad-hoc setups to flash in-system +(TODO add a doc for in-system-specific problems). + +Symptoms indicating you may have at least one of these are for example inconsistent reads or probing results. +This happens basically because the analog electrical waveforms representing the digital information +get too distorted to by interpreted correctly all the time. Depending on the cause different steps can be tried. + +* Not all input pins are connected to the correct voltage level/output pin of the programmer. + Always connect all input pins of ICs! + +* The easiest thing to try is lowering the (SPI) clock frequency if your programmer supports it. + That way the waveforms have more time to settle before being sampled by the receiver which might be enough. + Depending on the design of the driver and receiver as well as the actual communication path + this might not change anything as well. + +* Wires are too long. Shortening them to a few cm (i.e. < 20, the lesser the better) might help. + +* The impedances of the wires/traces do not match the impedances of the input pins + (of either the circuit/chip on the mainboard or the external programmer). + Try using shorter wires, adding small (<100 Ohm) series resistors or parallel capacitors (<20pF) + as near as possible to the input pins (this includes also the MISO line which ends near the programmer)\ + and/or ask someone who has experience with high frequency electronics. + +* The supply voltage of the flash chip is not stable enough. Try adding a 0.1 µF - 1 µF (ceramic) capacitor + between the flash chip's VCC and GND pins as near as possible to the chip. + +Live CD +========= + +A Live CD containing flashrom provides a user with a stable work environment to read, write and verify a flash device on any supported hardware. + +It can help avoid Linux installation issues, which can be a hassle for some users. + +flashrom is already shipped in some of the Live CDs, see below. *Please note, some of these ship very old versions of flashrom*. + +* `SystemRescueCd `_ has been including flashrom since about version 2.5.1. + +* `grml `_ + + * Note: You need the full grml ISO, "small" (and "medium") ISOs do not contain flashrom. + * Note: Some releases (e.g. 2011.12) did not contain flashrom. + +* `Parted Magic `_ + +* `Hiren's BootCD `_ + + * When you select "Linux based rescue environment (Parted Magic 6.7)" and then "Live with default settings", + you have access to a system which has flashrom. diff --git a/doc/user_docs/msi_jspi1.rst b/doc/user_docs/msi_jspi1.rst new file mode 100644 index 000000000..dc20866f7 --- /dev/null +++ b/doc/user_docs/msi_jspi1.rst @@ -0,0 +1,50 @@ +========= +MSI JSPI1 +========= + +JSPI1 is a 5x2 or 6x2 2.0mm pitch pin header on many MSI motherboards. +It is used to recover from bad boot ROM images. Specifically, +it appears to be used to connect an alternate ROM with a working image. +Pull the #HOLD line low to deselect the onboard SPI ROM, allowing another +SPI ROM to take its place on the bus. Pull the #WP line high to disable write-protection. +Some boards use 1.8V flash chips, while others use 3.3V flash chips; +Check the flash chip datasheet to determine the correct value. + +**JSPI1 (5x2)** + +======== ======== ======== ==== +name pin pin name +======== ======== ======== ==== +VCC 1 2 VCC +MISO 3 4 MOSI +#SS 5 6 SCLK +GND 7 8 GND +#HOLD 9 10 NC +======== ======== ======== ==== + +**JSPI1 (6x2)** + +======== ======== ======== ============ +name pin pin name +======== ======== ======== ============ +VCC 1 2 VCC +SO 3 4 SI +#SS 5 6 CLK +GND 7 8 GND +NC 9 10 NC (no pin) +#WP 11 12 #HOLD +======== ======== ======== ============ + +======== ===================================== +name function +======== ===================================== +VCC Voltage (See flash chip datasheet) +MISO SPI Master In/Slave Out +MOSI SPI Master Out/Slave In +#SS SPI Slave (Chip) Select (active low) +SCLK SPI Clock +GND ground/common +#HOLD SPI hold (active low) +#WP SPI write-protect (active low) +NC Not Connected (or no pin) +======== ===================================== diff --git a/doc/user_docs/overview.rst b/doc/user_docs/overview.rst new file mode 100644 index 000000000..9825f22ea --- /dev/null +++ b/doc/user_docs/overview.rst @@ -0,0 +1,301 @@ +========== +Overview +========== + +Modern mainboards store the BIOS in a reprogrammable flash chip. +There are hundreds of different flash (`EEPROM `_) chips, +with variables such as memory size, speed, communication bus (Parallel, LPC, FWH, SPI) and packaging to name just a few. + +Packaging/housing/form factor +============================= + +DIP32: Dual In-line Package, 32 pins +------------------------------------ + +DIP32 top + +.. image:: Dip32_chip.jpg + :alt: DIP32 top + +DIP32 bottom + +.. image:: Dip32_chip_back.jpg + :alt: DIP32 bottom + +DIP32 in a socket + +.. image:: Dip32_in_socket.jpg + :alt: DIP32 in a socket + +DIP32 socket + +.. image:: Empty_dip32_socket.jpg + :alt: DIP32 socket + +DIP32 extractor tool + +.. image:: Dip_tool.jpg + :alt: DIP32 extractor tool + +A rectangular black plastic block with 16 pins along each of the two longer sides of the package +(32 pins in total). DIP32 chips can be socketed which means they are detachable from the mainboard +using physical force. If they haven't been moved in and out of the socket very much, +they can appear to be quite difficult to release from the socket. One way to remove a DIP32 chip +from a socket is by prying a **thin screwdriver** in between the plastic package and the socket, +along the shorter sides where there are no pins, and then gently bending the screwdriver to push +the chip upwards, away from the mainboard. Alternate between the two sides to avoid bending the pins, +and don't touch any of the pins with the screwdriver (search about ESD, electro-static discharge). +If the chip is **soldered directly to the mainboard**, it has to be desoldered in order to be +reprogrammed outside the mainboard. If you do this, it's a good idea to +`solder a socket to the mainboard `_ instead, +to ease any future experiments. + +PLCC32: Plastic Leaded Chip Carrier, 32 pins +-------------------------------------------- + +PLCC32 top + + .. image:: Plcc32_chip.jpg + :alt: PLCC32 top + +PLCC32 botto + + .. image:: Plcc32_chip_back.jpg + :alt: PLCC32 bottom + +PLCC32 socket + + .. image:: Plcc32_in_socket.jpg + :alt: PLCC32 socket + +PLCC32 in a socket + + .. image:: Empty_plcc32_socket.jpg + :alt: PLCC32 in a socket + +Soldered PLCC3 + + .. image:: Soldered_plcc32.jpg + :alt: Soldered PLCC32 + +Two soldered PLCC32 + + .. image:: Dual_plcc32_soldered.jpg + :alt: Two soldered PLCC32 + +PLCC32 Bios Savior + + .. image:: Bios_savior.jpg + :alt: PLCC32 Bios Savior + +PLCC32 Top-Hat-Flash adapte + + .. image:: Top_hat_flash.jpeg + :alt: PLCC32 Top-Hat-Flash adapter + +PLCC32 pushpin trick + + .. image:: Pushpin_roms_2.jpg + :alt: PLCC32 pushpin trick + +PLCC extractor tool + + .. image:: Plcc_tool.jpg + :alt: PLCC extractor tool + +Black plastic block again, but this one is much more square. +PLCC32 was becoming the standard for mainboards after DIP32 chips because of its smaller physical size. +PLCC can also be **socketed** or **soldered directly to the mainboard**. +Socketed PLCC32 chips can be removed using a special PLCC removal tool, +or using a piece of nylon line tied in a loop around the chip and pulled swiftly straight up, +or bending/prying using small screwdrivers if one is careful. PLCC32 sockets are often fragile +so the screwdriver approach is not recommended. While the nylon line method sounds strange it works well. +Desoldering PLCC32 chips and soldering on a socket can be done using either a desoldering station +or even just a heat gun. You can also cut the chip with a sharp knife, **but it will be destroyed in the process, of course**. + +DIP8: Dual In-line Package, 8 pins +---------------------------------- + +DIP8 top + + .. image:: Dip8_chip.jpg + :alt: DIP8 top + +DIP8 bottom + + .. image:: Dip8_chip_back.jpg + :alt: DIP8 bottom + +DIP8 in a socket + + .. image:: Dip8_in_socket.jpg + :alt: DIP8 in a socket + +DIP8 socket + + .. image:: Empty_dip8_socket.jpg + :alt: DIP8 socket + +Most recent boards use DIP8 chips (which always employ the SPI protocol) or SO8/SOIC8 chips (see below). +DIP8 chips are always **socketed**, and can thus be easily removed (and hot-swapped), +for example using a small screwdriver. This allows for relatively simple recovery in case of an incorrectly flashed chip. + +SO8/SOIC8: Small-Outline Integrated Circuit, 8 pins +--------------------------------------------------- + +Soldered SOIC8 + + .. image:: Soic8_chip.jpg + :alt: Soldered SOIC8 + +SOIC8 socket, front, closed + + .. image:: Soic8_socket_front_closed.jpg + :alt: SOIC8 socket, front, closed + +SOIC8 socket, half open + + .. image:: Soic8_socket_half_opened.jpg + :alt: SOIC8 socket, half open + +SOIC8 socket, open + + .. image:: Soic8_socket_open.jpg + :alt: SOIC8 socket, open + +SOIC8 socket, back + + .. image:: Soic8_socket_back.jpg + :alt: SOIC8 socket, back + +SOIC8 socket, chip nearby + + .. image:: Soic8_socket_with_chip.jpg + :alt: SOIC8 socket, chip nearby + +SOIC8 socket, chip inserted + + .. image:: Soic8_socket_with_chip_inserted.jpg + :alt: SOIC8 socket, chip inserted + +Another type of SOIC8 adapter + + .. image:: Spi-socket-dscn2913-1024x768.jpg + :alt: Another type of SOIC8 adapter + +Similarly to the DIP8 chips, these always use the SPI protocol. +However, SO8/SOIC8 chips are most often soldered onto the board directly without a socket. +In that case a few boards have a header to allow :doc:`in_system`. You can also desolder +a soldered SO8 chip and solder an SO8 socket/adapter in its place, or build +a `SOIC-to-DIP adapter `_. +Some of the cheapest SOIC ZIF sockets are made by `Wieson `_. +They have 3 models available - G6179-10(0000), G6179-20(0000) and a 16 pin version named G6179-07(0000). +They are available for example from `siliconkit `_, +`Dediprog `_, as well as `alibaba `_. +For the usual "BIOS" flash chips you want the G6179-10 model (look also for G6179-100000). +Dediprog usually has them or similar ones as well but has steep shipping costs and an unpractical minimum order quantity. + +TSOP: Thin Small-Outline Package, 32, 40, or 48 pins +---------------------------------------------------- + +Soldered TSOP32 + + .. image:: Amd_am29f010_tsop32.jpg + :alt: Soldered TSOP32 + +Soldered TSOP32 + + .. image:: Sst_39vf040_tsop32.jpg + :alt: Soldered TSOP32 + +Soldered TSOP40 + + .. image:: Soldered_tsop40.jpg + :alt: Soldered TSOP40 + +Soldered TSOP48 + + .. image:: Soldered_tsop48.jpg + :alt: Soldered TSOP48 + +TSOPs are often used in embedded systems where size is important and there is no need +for replacement in the field. It is possible to (de)solder TSOPs by hand, +but it's not trivial and a reasonable amount of soldering skills are required. + +BGA: Ball Grid Array +-------------------- + +BGA package flash + + .. image:: Flash-BGA.jpg + :alt: BGA package flash + +BGAs are often used in embedded systems where size is important and there is no need +for replacement in the field. It is not easily possible to (de)solder BGA by hand. + +Communication bus protocol +========================== + +There are four major communication bus protocols for flash chips, +each with multiple subtle variants in the command set: + +* **SPI**: Serial Peripheral Interface, introduced ca. 2006. +* **Parallel**: The oldest flash bus, phased out on mainboards around 2002. +* **LPC**: Low Pin Count, a standard introduced ca. 1998. +* **FWH**: Firmware Hub, a variant of the LPC standard introduced at the same time. + FWH is a special case variant of LPC with one bit set differently in the memory read/write commands. + That means some data sheets mention the chips speak LPC although + they will not respond to regular LPC read/write cycles. + +Here's an attempt to create a marketing language -> chip type mapping: + +* JEDEC Flash -> Parallel (well, mostly) +* FWH -> FWH +* Firmware Hub -> FWH +* LPC Firmware -> FWH +* Firmware Memory -> FWH +* Low Pin Count (if Firmware/FWH is not mentioned) -> LPC +* LPC (if Firmware is not mentioned) -> LPC +* Serial Flash -> SPI + +SST data sheets have the following conventions: + +* LPC Memory Read -> LPC +* Firmware Memory Read -> FWH + +If both are mentioned, the chip supports both. + +If you're not sure about whether a device is LPC or FWH, look at the read/write cycle definitions. + +FWH + +=========== ========== ============== ========================================================== +Clock Cycle Field Name Field contents Comments +=========== ========== ============== ========================================================== +1 START 1101/1110 1101 for READ, 1110 for WRITE. +2 IDSEL 0000 to 1111 IDSEL value to be shifted out to the chip. +3-9 IMADDR YYYY The address to be read/written. 7 cycles total == 28 bits. +10+ ... ... ... +=========== ========== ============== ========================================================== + +LPC + +=========== =================== ============== ========================================================== +Clock Cycle Field Name Field contents Comments +=========== =================== ============== ========================================================== +1 START 0000 ... +2 CYCLETYPE+DIRECTION 010X/011X 010X for READ, 011X for WRITE. X means "reserved". +3-10 ADDRESS YYYY The address to be read/written. 8 cycles total == 32 bits. +11+ ... ... ... +=========== =================== ============== ========================================================== + +Generally, a parallel flash chip will not speak any other protocols. +SPI flash chips also don't speak any other protocols. +LPC flash chips sometimes speak FWH as well and vice versa, +but they will not speak any protocols besides LPC/FWH. + +Hardware Redundancy +=================== +Gigabyte's DualBios: http://www.google.com/patents/US6892323 + +ASUS: http://www.google.com/patents/US8015449 diff --git a/drkaiser.c b/drkaiser.c index 96f2c99e5..ebf511915 100644 --- a/drkaiser.c +++ b/drkaiser.c @@ -71,13 +71,7 @@ static int drkaiser_shutdown(void *par_data) static const struct par_master par_master_drkaiser = { .chip_readb = drkaiser_chip_readb, - .chip_readw = fallback_chip_readw, - .chip_readl = fallback_chip_readl, - .chip_readn = fallback_chip_readn, .chip_writeb = drkaiser_chip_writeb, - .chip_writew = fallback_chip_writew, - .chip_writel = fallback_chip_writel, - .chip_writen = fallback_chip_writen, .shutdown = drkaiser_shutdown, }; diff --git a/dummyflasher.c b/dummyflasher.c index 22f392a91..ef49f48f9 100644 --- a/dummyflasher.c +++ b/dummyflasher.c @@ -55,7 +55,7 @@ struct emu_data { uint8_t emu_status_len; /* number of emulated status registers */ /* If "freq" parameter is passed in from command line, commands will delay * for this period before returning. */ - unsigned long int delay_us; + unsigned long long delay_ns; unsigned int emu_max_byteprogram_size; unsigned int emu_max_aai_size; unsigned int emu_jedec_se_size; @@ -75,6 +75,10 @@ struct emu_data { unsigned int spi_write_256_chunksize; uint8_t *flashchip_contents; + + /* An instance of this structure is shared between multiple masters, so + * store the number of references to clean up only once at shutdown time. */ + uint8_t refs_cnt; }; /* A legit complete SFDP table based on the MX25L6436E (rev. 1.8) datasheet. */ @@ -122,10 +126,10 @@ static int dummy_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsig emu_data->spi_write_256_chunksize); } -static bool dummy_spi_probe_opcode(struct flashctx *flash, uint8_t opcode) +static bool dummy_spi_probe_opcode(const struct flashctx *flash, uint8_t opcode) { size_t i; - struct emu_data *emu_data = flash->mst->spi.data; + const struct emu_data *emu_data = flash->mst->spi.data; for (i = 0; i < emu_data->spi_blacklist_size; i++) { if (emu_data->spi_blacklist[i] == opcode) return false; @@ -145,7 +149,7 @@ static int probe_variable_size(struct flashctx *flash) msg_cdbg("%s: set flash->total_size to %dK bytes.\n", __func__, flash->chip->total_size); - flash->chip->tested = TEST_OK_PREW; + flash->chip->tested = TEST_OK_PREWB; if (emu_data->erase_to_zero) flash->chip->feature_bits |= FEATURE_ERASED_ZERO; @@ -211,7 +215,7 @@ static void dummy_chip_writew(const struct flashctx *flash, uint16_t val, chipad static void dummy_chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr) { - msg_pspew("%s: addr=0x%" PRIxPTR ", val=0x%08x\n", __func__, addr, val); + msg_pspew("%s: addr=0x%" PRIxPTR ", val=0x%08"PRIx32"\n", __func__, addr, val); } static void dummy_chip_writen(const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len) @@ -897,7 +901,7 @@ static int dummy_spi_send_command(const struct flashctx *flash, unsigned int wri msg_pspew(" 0x%02x", readarr[i]); msg_pspew("\n"); - programmer_delay((writecnt + readcnt) * emu_data->delay_us); + default_delay(((writecnt + readcnt) * emu_data->delay_ns) / 1000); return 0; } @@ -905,6 +909,11 @@ static int dummy_shutdown(void *data) { msg_pspew("%s\n", __func__); struct emu_data *emu_data = (struct emu_data *)data; + + emu_data->refs_cnt--; + if (emu_data->refs_cnt != 0) + return 0; + if (emu_data->emu_chip != EMULATE_NONE) { if (emu_data->emu_persistent_image && emu_data->emu_modified) { msg_pdbg("Writing %s\n", emu_data->emu_persistent_image); @@ -919,6 +928,37 @@ static int dummy_shutdown(void *data) return 0; } +static void dummy_nop_delay(const struct flashctx *flash, unsigned int usecs) +{ +} + +static enum flashrom_wp_result dummy_wp_read_cfg(struct flashrom_wp_cfg *cfg, struct flashctx *flash) +{ + cfg->mode = FLASHROM_WP_MODE_DISABLED; + cfg->range.start = 0; + cfg->range.len = 0; + + return FLASHROM_WP_OK; +} + +static enum flashrom_wp_result dummy_wp_write_cfg(struct flashctx *flash, const struct flashrom_wp_cfg *cfg) +{ + if (cfg->mode != FLASHROM_WP_MODE_DISABLED) + return FLASHROM_WP_ERR_MODE_UNSUPPORTED; + + if (cfg->range.start != 0 || cfg->range.len != 0) + return FLASHROM_WP_ERR_RANGE_UNSUPPORTED; + + return FLASHROM_WP_OK; +} + +static enum flashrom_wp_result dummy_wp_get_available_ranges(struct flashrom_wp_ranges **list, struct flashctx *flash) +{ + /* Not supported */ + return FLASHROM_WP_ERR_RANGE_LIST_UNAVAILABLE; +} + + static const struct spi_master spi_master_dummyflasher = { .map_flash_region = dummy_map, .unmap_flash_region = dummy_unmap, @@ -926,11 +966,11 @@ static const struct spi_master spi_master_dummyflasher = { .max_data_read = MAX_DATA_READ_UNLIMITED, .max_data_write = MAX_DATA_UNSPECIFIED, .command = dummy_spi_send_command, - .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = dummy_spi_write_256, - .write_aai = default_spi_write_aai, + .shutdown = dummy_shutdown, .probe_opcode = dummy_spi_probe_opcode, + .delay = dummy_nop_delay, }; static const struct par_master par_master_dummyflasher = { @@ -944,13 +984,20 @@ static const struct par_master par_master_dummyflasher = { .chip_writew = dummy_chip_writew, .chip_writel = dummy_chip_writel, .chip_writen = dummy_chip_writen, + .shutdown = dummy_shutdown, + .delay = dummy_nop_delay, }; static const struct opaque_master opaque_master_dummyflasher = { - .probe = probe_variable_size, - .read = dummy_opaque_read, - .write = dummy_opaque_write, - .erase = dummy_opaque_erase, + .probe = probe_variable_size, + .read = dummy_opaque_read, + .write = dummy_opaque_write, + .erase = dummy_opaque_erase, + .shutdown = dummy_shutdown, + .delay = dummy_nop_delay, + .wp_read_cfg = dummy_wp_read_cfg, + .wp_write_cfg = dummy_wp_write_cfg, + .wp_get_ranges = dummy_wp_get_available_ranges, }; static int init_data(const struct programmer_cfg *cfg, @@ -1081,7 +1128,7 @@ static int init_data(const struct programmer_cfg *cfg, /* frequency to emulate in Hz (default), KHz, or MHz */ tmp = extract_programmer_param_str(cfg, "freq"); if (tmp) { - unsigned long int freq; + unsigned long long freq; char *units = tmp; char *end = tmp + strlen(tmp); @@ -1119,13 +1166,13 @@ static int init_data(const struct programmer_cfg *cfg, } } - if (freq == 0) { - msg_perr("%s: invalid value 0 for freq parameter\n", __func__); + if (freq == 0 || freq > 8000000000) { + msg_perr("%s: invalid value %llu for freq parameter\n", __func__, freq); free(tmp); return 1; } /* Assume we only work with bytes and transfer at 1 bit/Hz */ - data->delay_us = (1000000 * 8) / freq; + data->delay_ns = (1000000000ull * 8) / freq; } free(tmp); @@ -1346,6 +1393,7 @@ static int init_data(const struct programmer_cfg *cfg, static int dummy_init(const struct programmer_cfg *cfg) { + int ret = 0; struct stat image_stat; struct emu_data *data = calloc(1, sizeof(*data)); @@ -1354,7 +1402,7 @@ static int dummy_init(const struct programmer_cfg *cfg) return 1; } data->emu_chip = EMULATE_NONE; - data->delay_us = 0; + data->delay_ns = 0; data->spi_write_256_chunksize = 256; msg_pspew("%s\n", __func__); @@ -1403,23 +1451,22 @@ static int dummy_init(const struct programmer_cfg *cfg) } dummy_init_out: - if (register_shutdown(dummy_shutdown, data)) { - free(data->emu_persistent_image); - free(data->flashchip_contents); - free(data); - return 1; + if (dummy_buses_supported & BUS_PROG) { + data->refs_cnt++; + ret |= register_opaque_master(&opaque_master_dummyflasher, data); + } + if ((dummy_buses_supported & BUS_NONSPI) && !ret) { + data->refs_cnt++; + ret |= register_par_master(&par_master_dummyflasher, + dummy_buses_supported & BUS_NONSPI, + data); + } + if ((dummy_buses_supported & BUS_SPI) && !ret) { + data->refs_cnt++; + ret |= register_spi_master(&spi_master_dummyflasher, data); } - if (dummy_buses_supported & BUS_PROG) - register_opaque_master(&opaque_master_dummyflasher, data); - if (dummy_buses_supported & BUS_NONSPI) - register_par_master(&par_master_dummyflasher, - dummy_buses_supported & BUS_NONSPI, - data); - if (dummy_buses_supported & BUS_SPI) - register_spi_master(&spi_master_dummyflasher, data); - - return 0; + return ret; } const struct programmer_entry programmer_dummy = { diff --git a/edi.c b/edi.c index a2219ac6c..56ed62cec 100644 --- a/edi.c +++ b/edi.c @@ -304,7 +304,7 @@ int edi_chip_block_erase(struct flashctx *flash, unsigned int page, unsigned int return -1; while (edi_spi_busy(flash) == 1 && timeout) { - programmer_delay(10); + programmer_delay(flash, 10); timeout--; } @@ -379,7 +379,7 @@ int edi_chip_write(struct flashctx *flash, const uint8_t *buf, unsigned int star return -1; while (edi_spi_busy(flash) == 1 && timeout) { - programmer_delay(10); + programmer_delay(flash, 10); timeout--; } @@ -435,7 +435,7 @@ int edi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsi /* Just in case. */ while (edi_spi_busy(flash) == 1 && timeout) { - programmer_delay(10); + programmer_delay(flash, 10); timeout--; } diff --git a/en29lv640b.c b/en29lv640b.c index 6c0a565a8..4d938442d 100644 --- a/en29lv640b.c +++ b/en29lv640b.c @@ -26,7 +26,7 @@ * functions. */ -/* chunksize is 1 */ +/* chunksize is 2 */ int write_en29lv640b(struct flashctx *flash, const uint8_t *src, unsigned int start, unsigned int len) { unsigned int i; @@ -64,7 +64,7 @@ int probe_en29lv640b(struct flashctx *flash) chip_writeb(flash, 0x55, bios + 0x555); chip_writeb(flash, 0x90, bios + 0xAAA); - programmer_delay(10); + programmer_delay(flash, 10); id1 = chip_readb(flash, bios + 0x200); id1 |= (chip_readb(flash, bios) << 8); @@ -73,7 +73,7 @@ int probe_en29lv640b(struct flashctx *flash) chip_writeb(flash, 0xF0, bios + 0xAAA); - programmer_delay(10); + programmer_delay(flash, 10); msg_cdbg("%s: id1 0x%04x, id2 0x%04x\n", __func__, id1, id2); diff --git a/erasure_layout.c b/erasure_layout.c new file mode 100644 index 000000000..56841ab32 --- /dev/null +++ b/erasure_layout.c @@ -0,0 +1,408 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2022 Aarya Chaumal + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "flash.h" +#include "layout.h" +#include "erasure_layout.h" + +static size_t calculate_block_count(const struct flashchip *chip, size_t eraser_idx) +{ + size_t block_count = 0; + + chipoff_t addr = 0; + for (size_t i = 0; addr < chip->total_size * 1024; i++) { + const struct eraseblock *block = &chip->block_erasers[eraser_idx].eraseblocks[i]; + block_count += block->count; + addr += block->size * block->count; + } + + return block_count; +} + +static void init_eraseblock(struct erase_layout *layout, size_t idx, size_t block_num, + chipoff_t start_addr, chipoff_t end_addr, size_t *sub_block_index) +{ + struct eraseblock_data *edata = &layout[idx].layout_list[block_num]; + edata->start_addr = start_addr; + edata->end_addr = end_addr; + edata->selected = false; + edata->block_num = block_num; + + if (!idx) + return; + + edata->first_sub_block_index = *sub_block_index; + struct eraseblock_data *subedata = &layout[idx - 1].layout_list[*sub_block_index]; + while (*sub_block_index < layout[idx-1].block_count && + subedata->start_addr >= start_addr && subedata->end_addr <= end_addr) { + (*sub_block_index)++; + subedata++; + } + edata->last_sub_block_index = *sub_block_index - 1; +} + +/* + * @brief Function to free the created erase_layout + * + * @param layout pointer to allocated layout + * @param erasefn_count number of erase functions for which the layout was created + * + */ +void free_erase_layout(struct erase_layout *layout, unsigned int erasefn_count) +{ + if (!layout) + return; + for (size_t i = 0; i < erasefn_count; i++) { + free(layout[i].layout_list); + } + free(layout); +} + +/* + * @brief Function to create an erase layout + * + * @param flashctx flash context + * @param e_layout address to the pointer to store the layout + * @return 0 on success, + * -1 if layout creation fails + * + * This function creates a layout of which erase functions erase which regions + * of the flash chip. This helps to optimally select the erase functions for + * erase/write operations. + */ +int create_erase_layout(struct flashctx *const flashctx, struct erase_layout **e_layout) +{ + const struct flashchip *chip = flashctx->chip; + const size_t erasefn_count = count_usable_erasers(flashctx); + if (!erasefn_count) { + msg_gerr("No erase functions supported\n"); + return 0; + } + + struct erase_layout *layout = calloc(erasefn_count, sizeof(struct erase_layout)); + if (!layout) { + msg_gerr("Out of memory!\n"); + return -1; + } + + size_t layout_idx = 0; + for (size_t eraser_idx = 0; eraser_idx < NUM_ERASEFUNCTIONS; eraser_idx++) { + if (check_block_eraser(flashctx, eraser_idx, 0)) + continue; + + layout[layout_idx].eraser = &chip->block_erasers[eraser_idx]; + const size_t block_count = calculate_block_count(flashctx->chip, eraser_idx); + size_t sub_block_index = 0; + + layout[layout_idx].block_count = block_count; + layout[layout_idx].layout_list = (struct eraseblock_data *)calloc(block_count, + sizeof(struct eraseblock_data)); + + if (!layout[layout_idx].layout_list) { + free_erase_layout(layout, layout_idx); + return -1; + } + + size_t block_num = 0; + chipoff_t start_addr = 0; + + for (int i = 0; block_num < block_count; i++) { + const struct eraseblock *block = &chip->block_erasers[eraser_idx].eraseblocks[i]; + + for (size_t num = 0; num < block->count; num++) { + chipoff_t end_addr = start_addr + block->size - 1; + init_eraseblock(layout, layout_idx, block_num, + start_addr, end_addr, &sub_block_index); + block_num += 1; + start_addr = end_addr + 1; + } + } + layout_idx++; + } + + *e_layout = layout; + return layout_idx; +} + +/* + * @brief Function to align start and address of the region boundaries + * + * @param layout erase layout + * @param flashctx flash context + * @param region_start pointer to start address of the region to align + * @param region_end pointer to end address of the region to align + * + * This function aligns start and end address of the region + * to some erase sector boundaries and modify the region start and end addresses + * to match nearest erase sector boundaries. This function will be used in the + * new algorithm for erase function selection. + */ +static void align_region(const struct erase_layout *layout, struct flashctx *const flashctx, + chipoff_t *region_start, chipoff_t *region_end) +{ + chipoff_t start_diff = UINT_MAX, end_diff = UINT_MAX; + const size_t erasefn_count = count_usable_erasers(flashctx); + for (size_t i = 0; i < erasefn_count; i++) { + for (size_t j = 0; j < layout[i].block_count; j++) { + const struct eraseblock_data *ll = &layout[i].layout_list[j]; + if (ll->start_addr <= *region_start) + start_diff = (*region_start - ll->start_addr) > start_diff ? + start_diff : (*region_start - ll->start_addr); + if (ll->end_addr >= *region_end) + end_diff = (ll->end_addr - *region_end) > end_diff ? + end_diff : (ll->end_addr - *region_end); + } + } + + if (start_diff) { + msg_cinfo("Region [0x%08x - 0x%08x] is not sector aligned! " + "Extending start boundaries by 0x%08x bytes, from 0x%08x -> 0x%08x\n", + *region_start, *region_end, + start_diff, *region_start, *region_start - start_diff); + *region_start = *region_start - start_diff; + } + if (end_diff) { + msg_cinfo("Region [0x%08x - 0x%08x] is not sector aligned! " + "Extending end boundaries by 0x%08x bytes, from 0x%08x -> 0x%08x\n", + *region_start, *region_end, + end_diff, *region_end, *region_end + end_diff); + *region_end = *region_end + end_diff; + } +} + +/* + * @brief Function to select the list of sectors that need erasing + * + * @param flashctx flash context + * @param layout erase layout + * @param findex index of the erase function + * @param block_num index of the block to erase according to the erase function index + * @param curcontents buffer containg the current contents of the flash + * @param newcontents buffer containg the new contents of the flash + * @param rstart start address of the region + * @rend rend end address of the region + */ +static void select_erase_functions(struct flashctx *flashctx, const struct erase_layout *layout, + size_t findex, size_t block_num, uint8_t *curcontents, uint8_t *newcontents, + chipoff_t rstart, chipoff_t rend) +{ + struct eraseblock_data *ll = &layout[findex].layout_list[block_num]; + if (!findex) { + if (ll->start_addr >= rstart && ll->end_addr <= rend) { + chipoff_t start_addr = ll->start_addr; + chipoff_t end_addr = ll->end_addr; + const chipsize_t erase_len = end_addr - start_addr + 1; + const uint8_t erased_value = ERASED_VALUE(flashctx); + ll->selected = need_erase(curcontents + start_addr, newcontents + start_addr, erase_len, + flashctx->chip->gran, erased_value); + } + } else { + int count = 0; + const int sub_block_start = ll->first_sub_block_index; + const int sub_block_end = ll->last_sub_block_index; + + for (int j = sub_block_start; j <= sub_block_end; j++) { + select_erase_functions(flashctx, layout, findex - 1, j, curcontents, newcontents, + rstart, rend); + if (layout[findex - 1].layout_list[j].selected) + count++; + } + + const int total_blocks = sub_block_end - sub_block_start + 1; + if (count == total_blocks) { + if (ll->start_addr >= rstart && ll->end_addr <= rend) { + for (int j = sub_block_start; j <= sub_block_end; j++) + layout[findex - 1].layout_list[j].selected = false; + ll->selected = true; + } + } + } +} + +static int erase_write_helper(struct flashctx *const flashctx, chipoff_t region_start, chipoff_t region_end, + uint8_t *curcontents, uint8_t *newcontents, + struct erase_layout *erase_layout, bool *all_skipped) +{ + const size_t erasefn_count = count_usable_erasers(flashctx); + + // select erase functions + for (size_t i = 0; i < erase_layout[erasefn_count - 1].block_count; i++) { + if (erase_layout[erasefn_count - 1].layout_list[i].start_addr <= region_end && + region_start <= erase_layout[erasefn_count - 1].layout_list[i].end_addr) + select_erase_functions(flashctx, erase_layout, + erasefn_count - 1, i, + curcontents, newcontents, + region_start, region_end); + } + + // erase + for (size_t i = 0; i < erasefn_count; i++) { + for (size_t j = 0; j < erase_layout[i].block_count; j++) { + if (!erase_layout[i].layout_list[j].selected) + continue; + + chipoff_t start_addr = erase_layout[i].layout_list[j].start_addr; + unsigned int block_len = erase_layout[i].layout_list[j].end_addr - start_addr + 1; + const uint8_t erased_value = ERASED_VALUE(flashctx); + // execute erase + erasefunc_t *erasefn = lookup_erase_func_ptr(erase_layout[i].eraser); + + + if (erasefn(flashctx, start_addr, block_len)) { + return -1; + } + if (check_erased_range(flashctx, start_addr, block_len)) { + return -1; + msg_cerr("ERASE FAILED!\n"); + } + + // adjust curcontents + memset(curcontents+start_addr, erased_value, block_len); + // after erase make it unselected again + erase_layout[i].layout_list[j].selected = false; + msg_cdbg("E(%"PRIx32":%"PRIx32")", start_addr, start_addr + block_len - 1); + + *all_skipped = false; + } + } + + // write + unsigned int start_here = 0, len_here = 0, erase_len = region_end - region_start + 1; + while ((len_here = get_next_write(curcontents + region_start + start_here, + newcontents + region_start + start_here, + erase_len - start_here, &start_here, + flashctx->chip->gran))) { + // execute write + int ret = write_flash(flashctx, + newcontents + region_start + start_here, + region_start + start_here, len_here); + if (ret) { + msg_cerr("Write failed at %#x, Abort.\n", region_start + start_here); + return -1; + } + + // adjust curcontents + memcpy(curcontents + region_start + start_here, + newcontents + region_start + start_here, len_here); + msg_cdbg("W(%"PRIx32":%"PRIx32")", region_start + start_here, region_start + start_here + len_here - 1); + + *all_skipped = false; + } + + return 0; +} + + +/* + * @brief wrapper to use the erase algorithm + * + * @param flashctx flash context + * @param region_start start address of the region + * @param region_end end address of the region + * @param curcontents buffer containg the current contents of the flash + * @param newcontents buffer containg the new contents of the flash + * @param erase_layout erase layout + * @param all_skipped pointer to the flag to chec if any block was erased + */ +int erase_write(struct flashctx *const flashctx, chipoff_t region_start, chipoff_t region_end, + uint8_t *curcontents, uint8_t *newcontents, + struct erase_layout *erase_layout, bool *all_skipped) +{ + int ret = 0; + chipoff_t old_start = region_start, old_end = region_end; + align_region(erase_layout, flashctx, ®ion_start, ®ion_end); + + if (!flashctx->flags.skip_unwritable_regions) { + if (check_for_unwritable_regions(flashctx, region_start, region_end - region_start + 1)) + return -1; + } + + uint8_t *old_start_buf = NULL, *old_end_buf = NULL; + const size_t start_buf_len = old_start - region_start; + const size_t end_buf_len = region_end - old_end; + + if (start_buf_len) { + old_start_buf = (uint8_t *)malloc(start_buf_len); + if (!old_start_buf) { + msg_cerr("Not enough memory!\n"); + ret = -1; + goto _end; + } + read_flash(flashctx, curcontents + region_start, region_start, start_buf_len); + memcpy(old_start_buf, newcontents + region_start, start_buf_len); + memcpy(newcontents + region_start, curcontents + region_start, start_buf_len); + } + if (end_buf_len) { + chipoff_t end_offset = old_end + 1; + old_end_buf = (uint8_t *)malloc(end_buf_len); + if (!old_end_buf) { + msg_cerr("Not enough memory!\n"); + ret = -1; + goto _end; + } + read_flash(flashctx, curcontents + end_offset, end_offset, end_buf_len); + memcpy(old_end_buf, newcontents + end_offset, end_buf_len); + memcpy(newcontents + end_offset, curcontents + end_offset, end_buf_len); + } + + unsigned int len; + for (unsigned int addr = region_start; addr <= region_end; addr += len) { + struct flash_region region; + get_flash_region(flashctx, addr, ®ion); + len = min(region_end, region.end) - addr + 1; + + if (region.write_prot) { + msg_gdbg("%s: cannot erase inside %s " + "region (%#08"PRIx32"..%#08"PRIx32"), skipping range (%#08x..%#08x).\n", + __func__, region.name, + region.start, region.end, + addr, addr + len - 1); + free(region.name); + continue; + } + + msg_gdbg("%s: %s region (%#08"PRIx32"..%#08"PRIx32") is " + "writable, erasing range (%#08x..%#08x).\n", + __func__, region.name, + region.start, region.end, + addr, addr + len - 1); + free(region.name); + + + ret = erase_write_helper(flashctx, addr, addr + len - 1, curcontents, newcontents, erase_layout, all_skipped); + if (ret) + goto _end; + } +_end: + if (old_start_buf) { + memcpy(newcontents + region_start, old_start_buf, start_buf_len); + free(old_start_buf); + } + + if (old_end_buf) { + memcpy(newcontents + old_end + 1, old_end_buf, end_buf_len); + free(old_end_buf); + } + + msg_cinfo("Erase/write done from %"PRIx32" to %"PRIx32"\n", region_start, region_end); + return ret; +} diff --git a/flashchips.c b/flashchips.c index 076a721ee..42f1b9d85 100644 --- a/flashchips.c +++ b/flashchips.c @@ -66,7 +66,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_SHORT_RESET | FEATURE_ADDR_2AA, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -77,14 +77,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 3}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4750, 5250}, /* 4.75-5.25V for type -55, others 4.5-5.5V */ }, @@ -98,7 +98,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_EITHER_RESET | FEATURE_ADDR_2AA, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -109,14 +109,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4750, 5250}, /* 4.75-5.25V for type -55, others 4.5-5.5V */ }, @@ -130,20 +130,20 @@ const struct flashchip flashchips[] = { .page_size = 16 * 1024, .feature_bits = FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {16 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -157,20 +157,20 @@ const struct flashchip flashchips[] = { .page_size = 16 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_OK_PRE, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {16 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -184,20 +184,20 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -211,20 +211,20 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -238,20 +238,20 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -265,20 +265,20 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -292,20 +292,20 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -319,7 +319,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, /* unused */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -329,14 +329,14 @@ const struct flashchip flashchips[] = { {4 * 1024, 2}, {16 * 1024, 7}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* 3.0-3.6V for type -45R, others 2.7-3.6V */ }, @@ -350,7 +350,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, /* unused */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -360,14 +360,14 @@ const struct flashchip flashchips[] = { {4 * 1024, 2}, {8 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* 3.0-3.6V for type -45R, others 2.7-3.6V */ }, @@ -381,7 +381,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, /* unused */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -392,14 +392,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 3}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* 3.0-3.6V for type -55, others 2.7-3.6V */ }, @@ -413,7 +413,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, /* unused */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -424,14 +424,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* 3.0-3.6V for type -55, others 2.7-3.6V */ }, @@ -445,7 +445,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, /* unused */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -456,14 +456,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 7}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -477,7 +477,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, /* unused */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -488,14 +488,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -509,7 +509,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, /* unused */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -520,14 +520,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 15}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* 3.0-3.6V for type -70R, others 2.7-3.6V */ }, @@ -541,7 +541,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, /* unused */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -552,14 +552,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* 3.0-3.6V for type -70R, others 2.7-3.6V */ }, @@ -572,21 +572,21 @@ const struct flashchip flashchips[] = { .total_size = 512, .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, - .tested = TEST_OK_PRE, - .probe = probe_jedec, + .tested = TEST_OK_PREW, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* 3.0-3.6V for type -60R, others 2.7-3.6V*/ }, @@ -600,20 +600,20 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, /* datasheet specifies address as don't care */ .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* 3.0-3.6V for type -70R, others 2.7-3.6V */ }, @@ -627,25 +627,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 4 * 1024, 32 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { { 64 * 1024, 2 } }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 128 * 1024, 1 } }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -659,25 +659,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 4 * 1024, 512 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { { 64 * 1024, 32 } }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 2048 * 1024, 1 } }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -691,25 +691,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 4 * 1024, 64 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { { 64 * 1024, 4 } }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 256 * 1024, 1 } }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -724,31 +724,31 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, 0x48; write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 4 * 1024, 1024 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { { 64 * 1024, 64 } }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { { 64 * 1024, 64 } }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 4096 * 1024, 1 } }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 4096 * 1024, 1 } }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_amic_a25l032, /* bit5: T/B, bit6: prot size */ - .unlock = spi_disable_blockprotect_bp2_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -762,25 +762,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 4 * 1024, 128 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { { 64 * 1024, 8 } }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 512 * 1024, 1 } }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -794,7 +794,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid4, + .probe = PROBE_SPI_RDID4, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -805,16 +805,16 @@ const struct flashchip flashchips[] = { {8 * 1024, 1}, {4 * 1024, 2}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -828,7 +828,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid4, + .probe = PROBE_SPI_RDID4, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -839,16 +839,16 @@ const struct flashchip flashchips[] = { {16 * 1024, 1}, {32 * 1024, 1}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -862,25 +862,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 4 * 1024, 256 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { { 64 * 1024, 16 } }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 1024 * 1024, 1 } }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -894,7 +894,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid4, + .probe = PROBE_SPI_RDID4, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -906,16 +906,16 @@ const struct flashchip flashchips[] = { {8 * 1024, 1}, {4 * 1024, 2}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -929,7 +929,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid4, + .probe = PROBE_SPI_RDID4, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -941,16 +941,16 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 1}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -964,7 +964,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid4, + .probe = PROBE_SPI_RDID4, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -976,19 +976,19 @@ const struct flashchip flashchips[] = { {8 * 1024, 1}, {4 * 1024, 2}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1002,7 +1002,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PR, - .probe = probe_spi_rdid4, + .probe = PROBE_SPI_RDID4, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -1014,19 +1014,19 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 31}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1040,7 +1040,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid4, + .probe = PROBE_SPI_RDID4, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -1052,16 +1052,16 @@ const struct flashchip flashchips[] = { {8 * 1024, 1}, {4 * 1024, 2}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1075,7 +1075,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid4, + .probe = PROBE_SPI_RDID4, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -1087,16 +1087,16 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 3}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1115,7 +1115,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PR, - .probe = probe_spi_rdid4, + .probe = PROBE_SPI_RDID4, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -1127,16 +1127,16 @@ const struct flashchip flashchips[] = { {8 * 1024, 1}, {4 * 1024, 2}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1150,7 +1150,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid4, + .probe = PROBE_SPI_RDID4, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -1162,16 +1162,16 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 7}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1185,25 +1185,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 4 * 1024, 16 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { { 64 * 1024, 1 } }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 64 * 1024, 1 } }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1217,7 +1217,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PRE, - .probe = probe_spi_rdid4, + .probe = PROBE_SPI_RDID4, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -1229,16 +1229,16 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 15}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1254,31 +1254,31 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, 0x48; write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 4 * 1024, 1024 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { { 64 * 1024, 64 } }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { { 64 * 1024, 64 } }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 4096 * 1024, 1 } }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 4096 * 1024, 1 } }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_amic_a25l032, /* bit5: T/B, bit6: prot size */ - .unlock = spi_disable_blockprotect_bp2_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1294,31 +1294,31 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, 0x48; write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 4 * 1024, 512 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { { 64 * 1024, 32 } }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { { 64 * 1024, 32 } }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 2048 * 1024, 1 } }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 2048 * 1024, 1 } }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_amic_a25l032, /* bit5: T/B, bit6: prot size */ - .unlock = spi_disable_blockprotect_bp2_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1335,31 +1335,31 @@ const struct flashchip flashchips[] = { /* QPI enable 0x35, disable 0xF5 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 4 * 1024, 2048 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { { 32 * 1024, 256 } }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { { 64 * 1024, 128 } }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 8192 * 1024, 1 } }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 8192 * 1024, 1 } }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enhance (sic!) */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enhance (sic!) */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1373,7 +1373,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -1384,14 +1384,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 3}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -1405,7 +1405,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -1416,14 +1416,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -1437,20 +1437,20 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -1464,24 +1464,63 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_OK_PR, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* routine is wrapper to probe_jedec (pm49fl00x.c) */ .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .unlock = unlock_regspace2_uniform_64k, - .write = write_jedec_1, - .read = read_memmapped, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, + { + .vendor = "Atmel", + .name = "AT25DF011", + .bustype = BUS_SPI, + .manufacture_id = ATMEL_ID, + .model_id = ATMEL_AT25DF011, + .total_size = 128, + .page_size = 256, + /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 4} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {32 * 1024, 4} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {128 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {128 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 3600}, + }, + { .vendor = "Atmel", .name = "AT25DF021", @@ -1493,31 +1532,31 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25df, - .unlock = spi_disable_blockprotect_at2x_global_unprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, /* 2.3-3.6V & 2.7-3.6V models available */ }, @@ -1532,31 +1571,31 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25df, - .unlock = spi_disable_blockprotect_at2x_global_unprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 3600}, }, @@ -1570,31 +1609,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25df, - .unlock = spi_disable_blockprotect_at2x_global_unprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, /* 2.3-3.6V & 2.7-3.6V models available */ }, @@ -1608,31 +1647,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25df, - .unlock = spi_disable_blockprotect_at2x_global_unprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1600, 2000}, /* Datasheet says range is 1.65-1.95 V */ }, @@ -1646,31 +1685,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25df_sec, - .unlock = spi_disable_blockprotect_at2x_global_unprotect_sec, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF_SEC, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT_SEC, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1684,31 +1723,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25df_sec, - .unlock = spi_disable_blockprotect_at2x_global_unprotect_sec, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF_SEC, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT_SEC, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1723,31 +1762,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25df, - .unlock = spi_disable_blockprotect_at2x_global_unprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1762,31 +1801,31 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25df_sec, - .unlock = spi_disable_blockprotect_at2x_global_unprotect_sec, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF_SEC, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT_SEC, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1800,31 +1839,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25df_sec, - .unlock = spi_disable_blockprotect_at2x_global_unprotect_sec, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF_SEC, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT_SEC, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1839,31 +1878,31 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25df_sec, - .unlock = spi_disable_blockprotect_at2x_global_unprotect_sec, - .write = spi_chip_write_256, /* Dual I/O (0xA2) supported */ - .read = spi_chip_read, /* Fast read (0x0B), dual I/O (0x3B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF_SEC, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT_SEC, + .write = SPI_CHIP_WRITE256, /* Dual I/O (0xA2) supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O (0x3B) supported */ .voltage = {1650, 1950}, }, @@ -1878,31 +1917,31 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25df_sec, - .unlock = spi_disable_blockprotect_at2x_global_unprotect_sec, - .write = spi_chip_write_256, /* Dual I/O (0xA2) supported */ - .read = spi_chip_read, /* Fast read (0x0B), dual I/O (0x3B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF_SEC, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT_SEC, + .write = SPI_CHIP_WRITE256, /* Dual I/O (0xA2) supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O (0x3B) supported */ .voltage = {1650, 1950}, }, @@ -1917,31 +1956,31 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25df_sec, - .unlock = spi_disable_blockprotect_at2x_global_unprotect_sec, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF_SEC, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT_SEC, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1957,22 +1996,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_at25f, + .probe = PROBE_SPI_AT25F, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_62, + .block_erase = SPI_BLOCK_ERASE_62, } }, - .printlock = spi_prettyprint_status_register_at25f, - .unlock = spi_disable_blockprotect_at25f, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25F, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT25F, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -1986,22 +2025,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_at25f, + .probe = PROBE_SPI_AT25F, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_62, + .block_erase = SPI_BLOCK_ERASE_62, } }, - .printlock = spi_prettyprint_status_register_at25f, - .unlock = spi_disable_blockprotect_at25f, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25F, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT25F, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -2015,23 +2054,23 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_at25f, + .probe = PROBE_SPI_AT25F, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_62, + .block_erase = SPI_BLOCK_ERASE_62, } }, - .printlock = spi_prettyprint_status_register_at25f4096, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25F4096, /* "Bits 5-6 are 0s when device is not in an internal write cycle." Better leave them alone: */ - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -2045,22 +2084,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_at25f, + .probe = PROBE_SPI_AT25F, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_62, + .block_erase = SPI_BLOCK_ERASE_62, } }, - .printlock = spi_prettyprint_status_register_at25f, - .unlock = spi_disable_blockprotect_at25f, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25F, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT25F, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -2074,23 +2113,23 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_at25f, + .probe = PROBE_SPI_AT25F, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_62, + .block_erase = SPI_BLOCK_ERASE_62, } }, - .printlock = spi_prettyprint_status_register_at25f512a, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25F512A, /* FIXME: It is not correct to use this one, because the BP1 bit is N/A. */ - .unlock = spi_disable_blockprotect_at25f512a, - .write = spi_chip_write_256, - .read = spi_chip_read, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT25F512A, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -2105,34 +2144,34 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_62, + .block_erase = SPI_BLOCK_ERASE_62, } }, - .printlock = spi_prettyprint_status_register_at25f512b, - .unlock = spi_disable_blockprotect_at25f512b, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25F512B, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT25F512B, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -2146,34 +2185,34 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25fs010, - .unlock = spi_disable_blockprotect_at25fs010, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25FS010, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT25FS010, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -2187,31 +2226,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25fs040, - .unlock = spi_disable_blockprotect_at25fs040, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25FS040, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT25FS040, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -2225,31 +2264,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2500, 3600}, }, @@ -2263,31 +2302,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2300, 3600}, }, @@ -2301,31 +2340,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PR, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 2000}, }, @@ -2339,31 +2378,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2500, 3600}, }, @@ -2377,31 +2416,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PR, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4096 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4096 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2500, 3600}, }, @@ -2416,31 +2455,31 @@ const struct flashchip flashchips[] = { /* supports SFDP */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_WRSR2, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 2000}, .reg_bits = { @@ -2451,7 +2490,7 @@ const struct flashchip flashchips[] = { .sec = {STATUS1, 6, RW}, .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -2464,25 +2503,25 @@ const struct flashchip flashchips[] = { .page_size = 256, /* does not support EWSR nor WREN and has no writable status register bits whatsoever */ .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256, 2048} }, - .block_erase = spi_block_erase_81, + .block_erase = SPI_BLOCK_ERASE_81, }, { .eraseblocks = { {2 * 1024, 256} }, - .block_erase = spi_block_erase_50, + .block_erase = SPI_BLOCK_ERASE_50, }, { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, } }, - .printlock = spi_prettyprint_status_register_plain, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* Supports also an incompatible page write (of exactly 256 B) and an auto-erasing write. */ - .write = spi_chip_write_1, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .write = SPI_CHIP_WRITE1, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, /* 3.0-3.6V for higher speed, 2.7-3.6V normal */ }, @@ -2496,31 +2535,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at26df081a, - .unlock = spi_disable_blockprotect_at2x_global_unprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT26DF081A, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -2534,31 +2573,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at25df, - .unlock = spi_disable_blockprotect_at2x_global_unprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -2572,31 +2611,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_at26df081a, - .unlock = spi_disable_blockprotect_at2x_global_unprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT26DF081A, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -2609,31 +2648,31 @@ const struct flashchip flashchips[] = { .total_size = 512, .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, - .tested = {.probe = NT, .read = NT, .erase = NT, .write = BAD}, - .probe = probe_spi_rdid, + .tested = {.probe = NT, .read = NT, .erase = NT, .write = BAD, .wp = NA}, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .write = NULL, /* Incompatible Page write */ - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .write = 0, /* Incompatible Page write */ + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -2646,18 +2685,18 @@ const struct flashchip flashchips[] = { .total_size = 128, .page_size = 128, .feature_bits = FEATURE_LONG_RESET, - .tested = TEST_OK_PRE, - .probe = probe_jedec, + .tested = TEST_OK_PREW, + .probe = PROBE_JEDEC, .probe_timing = 10000, /* 10mS, Enter=Exec */ .block_erasers = { { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec, /* FIXME */ - .read = read_memmapped, + .write = WRITE_JEDEC, /* FIXME */ + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -2671,17 +2710,17 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_LONG_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10000, /* 10ms */ .block_erasers = { { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec, - .read = read_memmapped, + .write = WRITE_JEDEC, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -2695,17 +2734,17 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_LONG_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10000, /* 10 ms */ .block_erasers = { { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec, - .read = read_memmapped, + .write = WRITE_JEDEC, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -2719,17 +2758,17 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_LONG_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10000, /* 10mS, Enter=Exec */ .block_erasers = { { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec, - .read = read_memmapped, + .write = WRITE_JEDEC, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -2745,7 +2784,7 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77 (4 dummy bytes); write 0x9A (via buffer) */ .feature_bits = FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -2755,14 +2794,14 @@ const struct flashchip flashchips[] = { {248 * 1056, 1}, /* sector 0b: opcode 7Ch */ {256 * 1056, 63}, /* sectors 1 - 63: opcode 7Ch */ }, - .block_erase = spi_erase_at45cs_sector, + .block_erase = SPI_ERASE_AT45CS_SECTOR, } }, - .printlock = spi_prettyprint_status_register_plain, - .write = spi_write_at45db, - .read = spi_read_at45db, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .write = SPI_WRITE_AT45DB, + .read = SPI_READ_AT45DB, .voltage = {2700, 3600}, - .gran = write_gran_1056bytes, + .gran = WRITE_GRAN_1056BYTES, }, { @@ -2777,33 +2816,33 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_at45db, + .probe = PROBE_SPI_AT45DB, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256, 512} }, - .block_erase = spi_erase_at45db_page, + .block_erase = SPI_ERASE_AT45DB_PAGE, }, { .eraseblocks = { {8 * 256, 512/8} }, - .block_erase = spi_erase_at45db_block, + .block_erase = SPI_ERASE_AT45DB_BLOCK, }, { .eraseblocks = { {8 * 256, 1}, {120 * 256, 1}, {128 * 256, 3}, }, - .block_erase = spi_erase_at45db_sector + .block_erase = SPI_ERASE_AT45DB_SECTOR }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_erase_at45db_chip, + .block_erase = SPI_ERASE_AT45DB_CHIP, } }, - .printlock = spi_prettyprint_status_register_at45db, - .unlock = spi_disable_blockprotect_at45db, /* Impossible if locked down or #WP is low */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT45DB, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT45DB, /* Impossible if locked down or #WP is low */ /* granularity will be set by the probing function. */ - .write = spi_write_at45db, - .read = spi_read_at45db, /* Fast read (0x0B) supported */ + .write = SPI_WRITE_AT45DB, + .read = SPI_READ_AT45DB, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -2819,33 +2858,33 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_at45db, + .probe = PROBE_SPI_AT45DB, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256, 1024} }, - .block_erase = spi_erase_at45db_page, + .block_erase = SPI_ERASE_AT45DB_PAGE, }, { .eraseblocks = { {8 * 256, 1024/8} }, - .block_erase = spi_erase_at45db_block, + .block_erase = SPI_ERASE_AT45DB_BLOCK, }, { .eraseblocks = { {8 * 256, 1}, {120 * 256, 1}, {128 * 256, 7}, }, - .block_erase = spi_erase_at45db_sector + .block_erase = SPI_ERASE_AT45DB_SECTOR }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_erase_at45db_chip, + .block_erase = SPI_ERASE_AT45DB_CHIP, } }, - .printlock = spi_prettyprint_status_register_at45db, - .unlock = spi_disable_blockprotect_at45db, /* Impossible if locked down or #WP is low */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT45DB, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT45DB, /* Impossible if locked down or #WP is low */ /* granularity will be set by the probing function. */ - .write = spi_write_at45db, - .read = spi_read_at45db, /* Fast read (0x0B) supported */ + .write = SPI_WRITE_AT45DB, + .read = SPI_READ_AT45DB, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -2861,33 +2900,33 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_at45db, + .probe = PROBE_SPI_AT45DB, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256, 2048} }, - .block_erase = spi_erase_at45db_page, + .block_erase = SPI_ERASE_AT45DB_PAGE, }, { .eraseblocks = { {8 * 256, 2048/8} }, - .block_erase = spi_erase_at45db_block, + .block_erase = SPI_ERASE_AT45DB_BLOCK, }, { .eraseblocks = { {8 * 256, 1}, {248 * 256, 1}, {256 * 256, 7}, }, - .block_erase = spi_erase_at45db_sector + .block_erase = SPI_ERASE_AT45DB_SECTOR }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_erase_at45db_chip, + .block_erase = SPI_ERASE_AT45DB_CHIP, } }, - .printlock = spi_prettyprint_status_register_at45db, - .unlock = spi_disable_blockprotect_at45db, /* Impossible if locked down or #WP is low */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT45DB, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT45DB, /* Impossible if locked down or #WP is low */ /* granularity will be set by the probing function. */ - .write = spi_write_at45db, - .read = spi_read_at45db, /* Fast read (0x0B) supported */ + .write = SPI_WRITE_AT45DB, + .read = SPI_READ_AT45DB, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, /* 2.5-3.6V & 2.7-3.6V models available */ }, @@ -2903,33 +2942,33 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_at45db, + .probe = PROBE_SPI_AT45DB, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256, 4096} }, - .block_erase = spi_erase_at45db_page, + .block_erase = SPI_ERASE_AT45DB_PAGE, }, { .eraseblocks = { {8 * 256, 4096/8} }, - .block_erase = spi_erase_at45db_block, + .block_erase = SPI_ERASE_AT45DB_BLOCK, }, { .eraseblocks = { {8 * 256, 1}, {248 * 256, 1}, {256 * 256, 15}, }, - .block_erase = spi_erase_at45db_sector + .block_erase = SPI_ERASE_AT45DB_SECTOR }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_erase_at45db_chip, + .block_erase = SPI_ERASE_AT45DB_CHIP, } }, - .printlock = spi_prettyprint_status_register_at45db, - .unlock = spi_disable_blockprotect_at45db, /* Impossible if locked down or #WP is low */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT45DB, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT45DB, /* Impossible if locked down or #WP is low */ /* granularity will be set by the probing function. */ - .write = spi_write_at45db, - .read = spi_read_at45db, /* Fast read (0x0B) supported */ + .write = SPI_WRITE_AT45DB, + .read = SPI_READ_AT45DB, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, /* 2.5-3.6V & 2.7-3.6V models available */ }, @@ -2945,33 +2984,33 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_at45db, + .probe = PROBE_SPI_AT45DB, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {512, 4096} }, - .block_erase = spi_erase_at45db_page, + .block_erase = SPI_ERASE_AT45DB_PAGE, }, { .eraseblocks = { {8 * 512, 4096/8} }, - .block_erase = spi_erase_at45db_block, + .block_erase = SPI_ERASE_AT45DB_BLOCK, }, { .eraseblocks = { {8 * 512, 1}, {248 * 512, 1}, {256 * 512, 15}, }, - .block_erase = spi_erase_at45db_sector + .block_erase = SPI_ERASE_AT45DB_SECTOR }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = spi_erase_at45db_chip, + .block_erase = SPI_ERASE_AT45DB_CHIP, } }, - .printlock = spi_prettyprint_status_register_at45db, - .unlock = spi_disable_blockprotect_at45db, /* Impossible if locked down or #WP is low */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT45DB, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT45DB, /* Impossible if locked down or #WP is low */ /* granularity will be set by the probing function. */ - .write = spi_write_at45db, - .read = spi_read_at45db, /* Fast read (0x0B) supported */ + .write = SPI_WRITE_AT45DB, + .read = SPI_READ_AT45DB, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, /* 2.5-3.6V & 2.7-3.6V models available */ }, @@ -2987,16 +3026,16 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77 (4 dummy bytes); write 0x9A (via buffer) */ .feature_bits = FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {528, 8192} }, - .block_erase = spi_erase_at45db_page, + .block_erase = SPI_ERASE_AT45DB_PAGE, }, { .eraseblocks = { {8 * 528, 8192/8} }, - .block_erase = spi_erase_at45db_block, + .block_erase = SPI_ERASE_AT45DB_BLOCK, }, /* Although the datasheets describes sectors (which can be write protected) * there seems to be no erase functions for them. { @@ -3005,17 +3044,17 @@ const struct flashchip flashchips[] = { {120 * 528, 1}, {128 * 528, 63}, }, - .block_erase = spi_erase_at45db_sector + .block_erase = SPI_ERASE_AT45DB_SECTOR }, */ { .eraseblocks = { {4224 * 1024, 1} }, - .block_erase = spi_erase_at45db_chip, + .block_erase = SPI_ERASE_AT45DB_CHIP, } }, - .printlock = spi_prettyprint_status_register_at45db, /* Bit 0 is undefined, no lockdown */ - .write = spi_write_at45db, - .read = spi_read_at45db_e8, /* 3 address and 4 dummy bytes */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT45DB, /* Bit 0 is undefined, no lockdown */ + .write = SPI_WRITE_AT45DB, + .read = SPI_READ_AT45DB_E8, /* 3 address and 4 dummy bytes */ .voltage = {2700, 3600}, - .gran = write_gran_528bytes, + .gran = WRITE_GRAN_528BYTES, }, { @@ -3030,33 +3069,33 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_at45db, + .probe = PROBE_SPI_AT45DB, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {512, 8192} }, - .block_erase = spi_erase_at45db_page, + .block_erase = SPI_ERASE_AT45DB_PAGE, }, { .eraseblocks = { {8 * 512, 8192/8} }, - .block_erase = spi_erase_at45db_block, + .block_erase = SPI_ERASE_AT45DB_BLOCK, }, { .eraseblocks = { {8 * 512, 1}, {120 * 512, 1}, {128 * 512, 63}, }, - .block_erase = spi_erase_at45db_sector + .block_erase = SPI_ERASE_AT45DB_SECTOR }, { .eraseblocks = { {4096 * 1024, 1} }, - .block_erase = spi_erase_at45db_chip, + .block_erase = SPI_ERASE_AT45DB_CHIP, } }, - .printlock = spi_prettyprint_status_register_at45db, - .unlock = spi_disable_blockprotect_at45db, /* Impossible if locked down or #WP is low */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT45DB, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT45DB, /* Impossible if locked down or #WP is low */ /* granularity will be set by the probing function. */ - .write = spi_write_at45db, - .read = spi_read_at45db, /* Fast read (0x0B) supported */ + .write = SPI_WRITE_AT45DB, + .read = SPI_READ_AT45DB, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, /* 2.5-3.6V & 2.7-3.6V models available */ }, @@ -3072,33 +3111,33 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_at45db, + .probe = PROBE_SPI_AT45DB, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {512, 8192} }, - .block_erase = spi_erase_at45db_page, + .block_erase = SPI_ERASE_AT45DB_PAGE, }, { .eraseblocks = { {8 * 512, 8192/8} }, - .block_erase = spi_erase_at45db_block, + .block_erase = SPI_ERASE_AT45DB_BLOCK, }, { .eraseblocks = { {8 * 512, 1}, {120 * 512, 1}, {128 * 512, 63}, }, - .block_erase = spi_erase_at45db_sector + .block_erase = SPI_ERASE_AT45DB_SECTOR }, { .eraseblocks = { {4096 * 1024, 1} }, - .block_erase = spi_erase_at45db_chip, + .block_erase = SPI_ERASE_AT45DB_CHIP, } }, - .printlock = spi_prettyprint_status_register_at45db, /* has a 2nd status register */ - .unlock = spi_disable_blockprotect_at45db, /* Impossible if locked down or #WP is low */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT45DB, /* has a 2nd status register */ + .unlock = SPI_DISABLE_BLOCKPROTECT_AT45DB, /* Impossible if locked down or #WP is low */ /* granularity will be set by the probing function. */ - .write = spi_write_at45db, - .read = spi_read_at45db, /* Fast read (0x0B) supported */ + .write = SPI_WRITE_AT45DB, + .read = SPI_READ_AT45DB, /* Fast read (0x0B) supported */ .voltage = {2500, 3600}, /* 2.3-3.6V & 2.5-3.6V models available */ }, @@ -3114,33 +3153,33 @@ const struct flashchip flashchips[] = { /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */ .feature_bits = FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_at45db, + .probe = PROBE_SPI_AT45DB, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {1024, 8192} }, - .block_erase = spi_erase_at45db_page, + .block_erase = SPI_ERASE_AT45DB_PAGE, }, { .eraseblocks = { {8 * 1024, 8192/8} }, - .block_erase = spi_erase_at45db_block, + .block_erase = SPI_ERASE_AT45DB_BLOCK, }, { .eraseblocks = { {8 * 1024, 1}, {248 * 1024, 1}, {256 * 1024, 31}, }, - .block_erase = spi_erase_at45db_sector + .block_erase = SPI_ERASE_AT45DB_SECTOR }, { .eraseblocks = { {8192 * 1024, 1} }, - .block_erase = spi_erase_at45db_chip, + .block_erase = SPI_ERASE_AT45DB_CHIP, } }, - .printlock = spi_prettyprint_status_register_at45db, - .unlock = spi_disable_blockprotect_at45db, /* Impossible if locked down or #WP is low */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_AT45DB, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT45DB, /* Impossible if locked down or #WP is low */ /* granularity will be set by the probing function. */ - .write = spi_write_at45db, - .read = spi_read_at45db, /* Fast read (0x0B) supported */ + .write = SPI_WRITE_AT45DB, + .read = SPI_READ_AT45DB, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -3154,18 +3193,18 @@ const struct flashchip flashchips[] = { .page_size = 0, /* unused */ .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .printlock = printlock_at49f, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_AT49F, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -3179,17 +3218,17 @@ const struct flashchip flashchips[] = { .page_size = 64, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -3203,7 +3242,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { @@ -3214,14 +3253,14 @@ const struct flashchip flashchips[] = { {96 * 1024, 1}, {128 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -3235,7 +3274,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PR, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { @@ -3246,14 +3285,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -3267,13 +3306,13 @@ const struct flashchip flashchips[] = { .page_size = 0, /* unused */ .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PRE, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } /* Chip features an optional permanent write protection * of the first 8 kB. The erase function is the same as @@ -3282,9 +3321,9 @@ const struct flashchip flashchips[] = { * supported. */ }, - .printlock = printlock_at49f, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_AT49F, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -3298,13 +3337,13 @@ const struct flashchip flashchips[] = { .page_size = 0, /* unused */ .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } /* Chip features an optional permanent write protection * of the first 16 kB. The erase function is the same as @@ -3313,9 +3352,9 @@ const struct flashchip flashchips[] = { * supported. */ }, - .printlock = printlock_at49f, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_AT49F, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -3329,13 +3368,13 @@ const struct flashchip flashchips[] = { .page_size = 0, /* unused */ .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } /* Chip features an optional permanent write protection * of the first 16 kB. The erase function is the same as @@ -3344,9 +3383,9 @@ const struct flashchip flashchips[] = { * supported. */ }, - .printlock = printlock_at49f, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_AT49F, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -3361,13 +3400,13 @@ const struct flashchip flashchips[] = { .page_size = 0, /* unused */ .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } /* Chip features an optional permanent write protection * of the first 16 kB. The erase function is the same as @@ -3376,9 +3415,9 @@ const struct flashchip flashchips[] = { * supported. */ }, - .printlock = printlock_at49f, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_AT49F, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -3392,7 +3431,7 @@ const struct flashchip flashchips[] = { .page_size = 0, /* unused */ .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_UNTESTED, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -3403,18 +3442,18 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = NULL, /* TODO: Implement. */ + .block_erase = NO_BLOCK_ERASE_FUNC, /* TODO: Implement. */ }, { .eraseblocks = { {64 * 1024, 4}, }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, }, }, - .printlock = printlock_regspace2_block_eraser_0, - .unlock = unlock_regspace2_block_eraser_0, - .write = write_82802ab, - .read = read_memmapped, + .printlock = PRINTLOCK_REGSPACE2_BLOCK_ERASER_0, + .unlock = UNLOCK_REGSPACE2_BLOCK_ERASER_0, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -3428,7 +3467,7 @@ const struct flashchip flashchips[] = { .page_size = 0, /* unused */ .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_UNTESTED, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -3439,18 +3478,18 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, }, { .eraseblocks = { {64 * 1024, 8}, }, - .block_erase = NULL, /* TODO: Implement. */ + .block_erase = NO_BLOCK_ERASE_FUNC, /* TODO: Implement. */ }, }, - .printlock = printlock_regspace2_block_eraser_0, - .unlock = unlock_regspace2_block_eraser_0, - .write = write_82802ab, - .read = read_memmapped, + .printlock = PRINTLOCK_REGSPACE2_BLOCK_ERASER_0, + .unlock = UNLOCK_REGSPACE2_BLOCK_ERASER_0, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -3464,7 +3503,7 @@ const struct flashchip flashchips[] = { .page_size = 0, /* unused */ .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_UNTESTED, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -3475,18 +3514,18 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 7}, }, - .block_erase = NULL, /* TODO: Implement. */ + .block_erase = NO_BLOCK_ERASE_FUNC, /* TODO: Implement. */ }, { .eraseblocks = { {64 * 1024, 8}, }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, }, }, - .printlock = printlock_regspace2_block_eraser_0, - .unlock = unlock_regspace2_block_eraser_0, - .write = write_82802ab, - .read = read_memmapped, + .printlock = PRINTLOCK_REGSPACE2_BLOCK_ERASER_0, + .unlock = UNLOCK_REGSPACE2_BLOCK_ERASER_0, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -3500,31 +3539,107 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PR, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + }, + + { + .vendor = "Boya/BoHong Microelectronics", + .name = "B.25D80A", + .bustype = BUS_SPI, + .manufacture_id = BOYA_BOHONG_ID, + .model_id = BOYA_BOHONG_B__25D80A, + .total_size = 1024, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN, + .tested = TEST_OK_PR, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {1 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {1 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + }, + + { + .vendor = "Boya/BoHong Microelectronics", + .name = "B.25Q64AS", + .bustype = BUS_SPI, + .manufacture_id = BOYA_BOHONG_ID, + .model_id = BOYA_BOHONG_B_25Q64AS, + .total_size = 8192, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {16 * 512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {16 * 512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -3538,31 +3653,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, - .unlock = spi_disable_blockprotect_at25fs040, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT_AT25FS040, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -3576,20 +3691,20 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PR, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -3602,18 +3717,18 @@ const struct flashchip flashchips[] = { .total_size = 64, .page_size = 0, /* unused */ .feature_bits = 0, - .tested = {.probe = OK, .read = OK, .erase = BAD, .write = BAD}, - .probe = probe_jedec, /* FIXME! */ + .tested = {.probe = OK, .read = OK, .erase = BAD, .write = BAD, .wp = NA}, + .probe = PROBE_JEDEC, /* FIXME! */ .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = NULL, /* TODO */ + .block_erase = NO_BLOCK_ERASE_FUNC, /* TODO */ }, }, - .write = NULL, /* TODO */ - .read = read_memmapped, + .write = 0, /* TODO */ + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -3626,19 +3741,19 @@ const struct flashchip flashchips[] = { .feature_bits = FEATURE_ERASED_ZERO, .tested = TEST_OK_PREW, .spi_cmd_set = SPI_EDI, - .probe = edi_probe_kb9012, + .probe = PROBE_EDI_KB9012, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {128, 1024} }, - .block_erase = edi_chip_block_erase, + .block_erase = EDI_CHIP_BLOCK_ERASE, }, }, - .write = edi_chip_write, - .read = edi_chip_read, + .write = EDI_CHIP_WRITE, + .read = EDI_CHIP_READ, .voltage = {2700, 3600}, - .gran = write_gran_128bytes, + .gran = WRITE_GRAN_128BYTES, }, { @@ -3653,22 +3768,22 @@ const struct flashchip flashchips[] = { * supports read (0x53), fast read (0x5B), erase (0xD5) and program (0x52) instructions. */ .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast Read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast Read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -3684,22 +3799,22 @@ const struct flashchip flashchips[] = { * supports read (0x53), fast read (0x5B), erase (0xD5) and program (0x52) instructions. */ .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast Read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast Read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -3715,22 +3830,22 @@ const struct flashchip flashchips[] = { * supports read (0x53), fast read (0x5B), erase (0xD5) and program (0x52) instructions. */ .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast Read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast Read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -3744,28 +3859,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EITHER, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_1, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE1, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -3779,28 +3894,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EITHER | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_bpl, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_BPL, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -3814,7 +3929,7 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { @@ -3825,14 +3940,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -3846,7 +3961,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -3857,16 +3972,16 @@ const struct flashchip flashchips[] = { {16 * 1024, 1}, {32 * 1024, 1}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -3880,7 +3995,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -3891,16 +4006,16 @@ const struct flashchip flashchips[] = { {8 * 1024, 1}, {4 * 1024, 2}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -3914,7 +4029,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -3925,16 +4040,16 @@ const struct flashchip flashchips[] = { {16 * 1024, 1}, {32 * 1024, 3}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -3948,7 +4063,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -3959,16 +4074,16 @@ const struct flashchip flashchips[] = { {8 * 1024, 1}, {4 * 1024, 2}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -3982,7 +4097,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -3994,16 +4109,16 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 31}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4017,7 +4132,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -4029,16 +4144,16 @@ const struct flashchip flashchips[] = { {8 * 1024, 1}, {4 * 1024, 2}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4052,7 +4167,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -4064,16 +4179,16 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 3} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4087,7 +4202,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -4099,16 +4214,16 @@ const struct flashchip flashchips[] = { {8 * 1024, 1}, {4 * 1024, 2}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4123,7 +4238,7 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -4135,16 +4250,16 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 63}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4159,7 +4274,7 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -4171,16 +4286,16 @@ const struct flashchip flashchips[] = { {8 * 1024, 1}, {4 * 1024, 2}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4194,7 +4309,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -4206,16 +4321,16 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 7} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4229,7 +4344,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -4241,16 +4356,16 @@ const struct flashchip flashchips[] = { {8 * 1024, 1}, {4 * 1024, 2}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4265,7 +4380,7 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -4277,16 +4392,16 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 127}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4301,7 +4416,7 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -4313,16 +4428,16 @@ const struct flashchip flashchips[] = { {8 * 1024, 1}, {4 * 1024, 2}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4336,7 +4451,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -4348,16 +4463,16 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 15} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4371,7 +4486,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -4383,16 +4498,16 @@ const struct flashchip flashchips[] = { {8 * 1024, 1}, {4 * 1024, 2}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4406,31 +4521,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -4444,31 +4559,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -4482,28 +4597,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -4517,31 +4632,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -4555,28 +4670,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -4590,28 +4705,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -4625,28 +4740,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -4660,28 +4775,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -4695,23 +4810,23 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4725,22 +4840,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4754,22 +4869,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4783,22 +4898,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4813,22 +4928,22 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4842,22 +4957,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4872,22 +4987,22 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4901,22 +5016,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -4931,28 +5046,28 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, }, { @@ -4968,32 +5083,32 @@ const struct flashchip flashchips[] = { /* OTP: D16 512B/Q16 128B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { /* not supported by Q16 version */ .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -5008,28 +5123,28 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -5044,28 +5159,28 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -5080,28 +5195,28 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -5116,28 +5231,28 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -5154,28 +5269,28 @@ const struct flashchip flashchips[] = { /* QPI enable 0x38, disable 0xFF */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, .reg_bits = { @@ -5183,7 +5298,7 @@ const struct flashchip flashchips[] = { .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, .tb = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like TB */ }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -5199,28 +5314,28 @@ const struct flashchip flashchips[] = { /* QPI enable 0x38, disable 0xFF */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 2048, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 2048, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -5237,28 +5352,76 @@ const struct flashchip flashchips[] = { /* QPI enable 0x38, disable 0xFF */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {1024 * 4096, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {1024 * 4096, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like TB */ + }, + .decode_range = DECODE_RANGE_SPI25, + }, + + { + .vendor = "Eon", + .name = "EN25QH32B", + .bustype = BUS_SPI, + .manufacture_id = EON_ID_NOPREFIX, + .model_id = EON_EN25QH32, + .total_size = 4096, + .page_size = 256, + /* supports SFDP */ + /* OTP: 1536B total; enter 0x3A */ + /* QPI enable 0x38, disable 0xFF */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 4096, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 4096, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -5275,28 +5438,76 @@ const struct flashchip flashchips[] = { /* QPI enable 0x38, disable 0xFF */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { { 8192 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { { 8192 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like TB */ + }, + .decode_range = DECODE_RANGE_SPI25_64K_BLOCK, + }, + + { + .vendor = "Eon", + .name = "EN25QH64A", + .bustype = BUS_SPI, + .manufacture_id = EON_ID_NOPREFIX, + .model_id = EON_EN25QH64, + .total_size = 8192, + .page_size = 256, + /* supports SFDP */ + /* OTP: 512B total; enter 0x3A */ + /* QPI enable 0x38, disable 0xFF */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 8192 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 8192 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -5311,28 +5522,28 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 1950}, }, @@ -5347,31 +5558,31 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_en25s_wp, - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_EN25S_WP, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 1950}, }, @@ -5386,28 +5597,28 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 1950}, }, @@ -5422,31 +5633,31 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4096 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4096 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_en25s_wp, - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_EN25S_WP, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 1950}, }, @@ -5461,28 +5672,28 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 1950}, }, @@ -5497,28 +5708,28 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8192 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8192 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_en25s_wp, - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_EN25S_WP, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 1950}, }, @@ -5533,28 +5744,28 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 1950}, }, @@ -5568,7 +5779,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_ADDR_AAA | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { @@ -5579,14 +5790,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 3}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -5600,7 +5811,7 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_ADDR_AAA | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { @@ -5611,14 +5822,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -5632,21 +5843,21 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_OK_PRE, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {16 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -5660,7 +5871,7 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -5669,14 +5880,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 8}, {64 * 1024, 127}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -5690,7 +5901,7 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -5699,14 +5910,14 @@ const struct flashchip flashchips[] = { {64 * 1024, 127}, {8 * 1024, 8}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -5720,20 +5931,20 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -5747,20 +5958,20 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {128 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -5773,21 +5984,21 @@ const struct flashchip flashchips[] = { .total_size = 512, .page_size = 4 * 1024, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* 3.0-3.6V for type -45R and 55R, others 2.7-3.6V */ }, @@ -5801,7 +6012,7 @@ const struct flashchip flashchips[] = { .page_size = 8192, .feature_bits = FEATURE_ADDR_SHIFTED, .tested = TEST_OK_PREW, - .probe = probe_en29lv640b, + .probe = PROBE_EN29LV640B, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { @@ -5810,14 +6021,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 8}, {64 * 1024, 127}, }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_en29lv640b, - .read = read_memmapped, + .write = WRITE_EN29LV640B, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -5832,30 +6043,30 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_tb_bpl, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O (0x3B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O (0x3B) supported */ .voltage = {2700, 3600}, /* 2.3-2.7V acceptable results in lower performance */ }, @@ -5869,31 +6080,31 @@ const struct flashchip flashchips[] = { .page_size = 256, /* OTP: 256B total; enter 0x3A */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 2} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_tb_bpl, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O (0x3B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O (0x3B) supported */ .voltage = {2700, 3600}, /* 2.3-2.7V acceptable results in lower performance */ }, @@ -5908,30 +6119,30 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; enter 0x3A, (A version only:) read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 256, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 256, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_bp2_tb_bpl, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O (0x3B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O (0x3B) supported */ .voltage = {2700, 3600}, /* 2.3-2.7V acceptable results in lower performance */ }, @@ -5946,30 +6157,74 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; enter 0x3A, (A version only:) read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 512, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 512, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, + }, + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O (0x3B) supported */ + .voltage = {2700, 3600}, + }, + + { + .vendor = "Fudan", + .name = "FM25Q04", + .bustype = BUS_SPI, + .manufacture_id = FUDAN_ID_NOPREFIX, + .model_id = FUDAN_FM25Q04, + .total_size = 512, + .page_size = 256, + /* supports SFDP */ + /* QPI enable 0x38, disable 0xFF */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = { + { + /* 128 * 4KB sectors */ + .eraseblocks = { {4 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + /* 16 * 32KB blocks */ + .eraseblocks = { {32 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + /* 8 * 64KB blocks */ + .eraseblocks = { {64 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + /* Full chip erase (0x60) */ + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + /* Full chip erase (0xC7) */ + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_bp2_tb_bpl, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O (0x3B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -5985,31 +6240,31 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ /* QPI enable 0x38, disable 0xFF */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_bp2_tb_bpl, /* bit6 selects size of protected blocks; TODO: SR2 */ - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, /* bit6 selects size of protected blocks; TODO: SR2 */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -6025,31 +6280,31 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ /* QPI enable 0x38, disable 0xFF */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .tested = TEST_OK_PR, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_tb_bpl, /* bit6 selects size of protected blocks; TODO: SR2 */ - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, /* bit6 selects size of protected blocks; TODO: SR2 */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -6066,30 +6321,118 @@ const struct flashchip flashchips[] = { /* QPI enable 0x38, disable 0xFF */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, + }, + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, /* bit6 selects size of protected blocks; TODO: SR2 */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2700, 3600}, + }, + + { + .vendor = "Fudan", + .name = "FM25Q64", + .bustype = BUS_SPI, + .manufacture_id = FUDAN_ID_NOPREFIX, + .model_id = FUDAN_FM25Q64, + .total_size = 8192, + .page_size = 256, + /* supports SFDP */ + /* QPI enable 0x38, disable 0xFF */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = { + { + /* 2048 * 4KB sectors */ + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + /* 256 * 32KB blocks */ + .eraseblocks = { {32 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + /* 128 * 64KB blocks */ + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + /* Full chip erase (0x60) */ + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + /* Full chip erase (0xC7) */ + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + }, + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, /* bit6 selects size of protected blocks; TODO: SR2 */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2700, 3600}, + }, + + { + .vendor = "Fudan", + .name = "FM25Q128", + .bustype = BUS_SPI, + .manufacture_id = FUDAN_ID_NOPREFIX, + .model_id = FUDAN_FM25Q128, + .total_size = 16384, + .page_size = 256, + /* supports SFDP */ + /* QPI enable 0x38, disable 0xFF */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PR, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = { + { + /* 4096 * 4KB sectors */ + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + /* 512 * 32KB blocks */ + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + /* 256 * 64KB blocks */ + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + /* Full chip erase (0x60) */ + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + /* Full chip erase (0xC7) */ + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_bp2_tb_bpl, /* bit6 selects size of protected blocks; TODO: SR2 */ - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, /* bit6 selects size of protected blocks; TODO: SR2 */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -6103,7 +6446,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { @@ -6114,14 +6457,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 7}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = NULL, - .read = read_memmapped, + .write = 0, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -6135,7 +6478,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { @@ -6146,14 +6489,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = NULL, - .read = read_memmapped, + .write = 0, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -6168,7 +6511,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_SHIFTED | FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, // FIXME: check datasheet. Using the 10 us from probe_m29f400bt .block_erasers = { @@ -6179,14 +6522,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 7}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4750, 5250}, /* 4.75-5.25V for type -55, others 4.5-5.5V */ }, @@ -6200,7 +6543,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_SHIFTED | FEATURE_ADDR_AAA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, // FIXME: check datasheet. Using the 10 us from probe_m29f400bt .block_erasers = { @@ -6211,14 +6554,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4750, 5250}, /* 4.75-5.25V for type -55, others 4.5-5.5V */ }, @@ -6232,7 +6575,7 @@ const struct flashchip flashchips[] = { .page_size = 0, .feature_bits = FEATURE_ADDR_SHIFTED | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, // FIXME: check datasheet. Using the 10 us from probe_m29f400bt .block_erasers = { @@ -6243,14 +6586,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 31}, }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, /* Supports a fast mode too */ - .read = read_memmapped, + .write = WRITE_JEDEC1, /* Supports a fast mode too */ + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* 3.0-3.6V for type -70, others 2.7-3.6V */ }, @@ -6264,7 +6607,7 @@ const struct flashchip flashchips[] = { .page_size = 0, .feature_bits = FEATURE_ADDR_SHIFTED | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, // FIXME: check datasheet. Using the 10 us from probe_m29f400bt .block_erasers = { @@ -6275,14 +6618,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, /* Supports a fast mode too */ - .read = read_memmapped, + .write = WRITE_JEDEC1, /* Supports a fast mode too */ + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* 3.0-3.6V for type -70, others 2.7-3.6V */ }, @@ -6297,70 +6640,70 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, { .vendor = "GigaDevice", - .name = "GD25LQ128C/GD25LQ128D/GD25LQ128E", + .name = "GD25LF128E", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25LQ128CD, + .model_id = GIGADEVICE_GD25LF128E, .total_size = 16384, .page_size = 256, /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1695, 1950}, .reg_bits = { @@ -6371,163 +6714,217 @@ const struct flashchip flashchips[] = { .sec = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */ .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "GigaDevice", - .name = "GD25LQ16", + .name = "GD25LF256F", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25LQ16, - .total_size = 2048, + .model_id = GIGADEVICE_GD25LF256F, + .total_size = 32768, .page_size = 256, /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2 | FEATURE_4BA, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_21, }, { - .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_5C, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {1695, 1950}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1650, 2000}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like TB */ + .cmp = {STATUS2, 6, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "GigaDevice", - .name = "GD25LQ32", + .name = "GD25LF512MF", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25LQ32, - .total_size = 4096, + .model_id = GIGADEVICE_GD25LF512MF, + .total_size = 65536, .page_size = 256, - /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2 | FEATURE_4BA, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_21, }, { - .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_5C, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {32 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1695, 1950}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like TB */ + .srl = {STATUS2, 0, RW}, + .cmp = {STATUS2, 6, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "GigaDevice", - .name = "GD25LQ40", + .name = "GD25LQ128E/GD25LB128E/GD25LR128E/GD25LQ128D/GD25LQ128C", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25LQ40, - .total_size = 512, + .model_id = GIGADEVICE_GD25LQ128CD, + .total_size = 16384, .page_size = 256, /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1695, 1950}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like TB */ + .sec = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */ + .cmp = {STATUS2, 6, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "GigaDevice", - .name = "GD25LQ64(B)", + .name = "GD25LQ255E", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25LQ64, - .total_size = 8192, + .model_id = GIGADEVICE_GD25LQ255E, + .total_size = 32768, .page_size = 256, /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2 | FEATURE_4BA, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_21, }, { - .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_5C, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {1695, 1950}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1650, 2000}, .reg_bits = { .srp = {STATUS1, 7, RW}, @@ -6537,125 +6934,163 @@ const struct flashchip flashchips[] = { .sec = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */ .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "GigaDevice", - .name = "GD25LQ80", + .name = "GD25LQ16", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25LQ80, - .total_size = 1024, + .model_id = GIGADEVICE_GD25LQ16, + .total_size = 2048, .page_size = 256, /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {1 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {1 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1695, 1950}, }, { .vendor = "GigaDevice", - .name = "GD25Q10", + .name = "GD25LQ32", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25Q10, - .total_size = 128, + .model_id = GIGADEVICE_GD25LQ32, + .total_size = 4096, .page_size = 256, - .feature_bits = FEATURE_WRSR_WREN, + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1695, 1950}, + }, + + { + .vendor = "GigaDevice", + .name = "GD25LQ40", + .bustype = BUS_SPI, + .manufacture_id = GIGADEVICE_ID, + .model_id = GIGADEVICE_GD25LQ40, + .total_size = 512, + .page_size = 256, + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 2} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1695, 1950}, }, { .vendor = "GigaDevice", - .name = "GD25Q127C/GD25Q128C", + .name = "GD25LQ64(B)", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25Q128, - .total_size = 16384, + .model_id = GIGADEVICE_GD25LQ64, + .total_size = 8192, .page_size = 256, - /* OTP: 1536B total; read 0x48; write 0x42, erase 0x44 */ - /* QPI: enable 0x38, disable 0xFF */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_WRSR2, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - /* TODO: 2nd status reg (read 0x35, write 0x31) and 3rd status reg (read 0x15, write 0x11) */ - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1695, 1950}, .reg_bits = { .srp = {STATUS1, 7, RW}, @@ -6665,300 +7100,346 @@ const struct flashchip flashchips[] = { .sec = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */ .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "GigaDevice", - .name = "GD25Q16(B)", + .name = "GD25LQ80", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25Q16, - .total_size = 2048, + .model_id = GIGADEVICE_GD25LQ80, + .total_size = 1024, .page_size = 256, - /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 (B version only) */ + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {1 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {1 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1695, 1950}, }, { - .vendor = "GigaDevice", - .name = "GD25Q20(B)", - .bustype = BUS_SPI, - .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25Q20, - .total_size = 256, - .page_size = 256, - .feature_bits = FEATURE_WRSR_WREN, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, - .probe_timing = TIMING_ZERO, - .block_erasers = + .vendor = "GigaDevice", + .name = "GD25LB256E/GD25LR256E", + .bustype = BUS_SPI, + .manufacture_id = GIGADEVICE_ID, + .model_id = GIGADEVICE_GD25LR256E, + .total_size = 32768, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_4BA, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = { { - .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_21, }, { - .eraseblocks = { {32 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_5C, }, { - .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 2000}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like TB */ + }, + .decode_range = DECODE_RANGE_SPI25, + }, { .vendor = "GigaDevice", - .name = "GD25Q256D/GD25Q256E", + .name = "GD25LB256F/GD25LR256F", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25Q256D, + .model_id = GIGADEVICE_GD25LQ255E, .total_size = 32768, .page_size = 256, - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN | - FEATURE_WRSR_EXT2 | FEATURE_WRSR2 | FEATURE_WRSR3, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2 | FEATURE_4BA, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_5C, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1650, 2000}, .reg_bits = { .srp = {STATUS1, 7, RW}, - .srl = {STATUS2, 6, RW}, + .srl = {STATUS2, 0, RW}, .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, - .tb = {STATUS1, 6, RW}, + .tb = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like TB */ + .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "GigaDevice", - .name = "GD25Q32(B)", + .name = "GD25LB512MF/GD25LR512MF", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25Q32, - .total_size = 4096, + .model_id = GIGADEVICE_GD25LB512MF, + .total_size = 65536, .page_size = 256, - /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR2, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2 | FEATURE_4BA, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_21, }, { - .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_5C, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {32 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1695, 1950}, .reg_bits = { .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like TB */ .srl = {STATUS2, 0, RW}, - .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, - .tb = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like TB */ - .sec = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */ .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { - .vendor = "GigaDevice", - .name = "GD25Q40(B)", - .bustype = BUS_SPI, - .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25Q40, - .total_size = 512, - .page_size = 256, - .feature_bits = FEATURE_WRSR_WREN, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, - .probe_timing = TIMING_ZERO, - .block_erasers = + .vendor = "GigaDevice", + .name = "GD25LB512ME/GD25LR512ME", + .bustype = BUS_SPI, + .manufacture_id = GIGADEVICE_ID, + .model_id = GIGADEVICE_GD25LR512ME, + .total_size = 65536, + .page_size = 256, + /* OTP: 4096B total; read 0x48; write 0x42, erase 0x44 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_4BA, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = { { - .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_21, }, { - .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_5C, }, { - .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {32 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 2000}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like TB */ + }, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "GigaDevice", - .name = "GD25Q512", + .name = "GD25Q10", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25Q512, - .total_size = 64, + .model_id = GIGADEVICE_GD25Q10, + .total_size = 128, .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 16} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 4} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {64 * 1024, 2} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {128 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {128 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, { .vendor = "GigaDevice", - .name = "GD25Q64(B)", + .name = "GD25Q128E/GD25B128E/GD25R128E/GD25Q127C", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25Q64, - .total_size = 8192, + .model_id = GIGADEVICE_GD25Q128, + .total_size = 16384, .page_size = 256, - /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ + /* OTP: 3072B total; read 0x48; write 0x42, erase 0x44 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR2, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + /* TODO: 2nd status reg (read 0x35, write 0x31) and 3rd status reg (read 0x15, write 0x11) */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, .reg_bits = { @@ -6969,2514 +7450,4218 @@ const struct flashchip flashchips[] = { .sec = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */ .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "GigaDevice", - .name = "GD25Q80(B)", + .name = "GD25Q128C", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25Q80, - .total_size = 1024, + .model_id = GIGADEVICE_GD25Q128, + .total_size = 16384, .page_size = 256, - /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 (B version only) */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* OTP: 1536B total; read 0x48; write 0x42, erase 0x44 */ + /* QPI: enable 0x38, disable 0xFF */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_WRSR2, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + /* TODO: 2nd status reg (read 0x35, write 0x31) and 3rd status reg (read 0x15, write 0x11) */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like TB */ + .sec = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */ + .cmp = {STATUS2, 6, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "GigaDevice", - .name = "GD25T80", + .name = "GD25Q16(B)", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25T80, - .total_size = 1024, + .model_id = GIGADEVICE_GD25Q16, + .total_size = 2048, .page_size = 256, - /* OTP: 256B total; enter 0x3A */ + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 (B version only) */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, { .vendor = "GigaDevice", - .name = "GD25VQ16C", + .name = "GD25Q20(B)", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25VQ16C, - .total_size = 2 * 1024, + .model_id = GIGADEVICE_GD25Q20, + .total_size = 256, .page_size = 256, - /* Supports SFDP */ - /* OTP: 1024B total; read 0x48, write 0x42, erase 0x44 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { { 4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { { 32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { { 64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 4} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {2300, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2700, 3600}, }, { .vendor = "GigaDevice", - .name = "GD25VQ21B", + .name = "GD25Q256E/GD25B256E/GD25R256E/GD25Q256D", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25VQ21B, - .total_size = 256, + .model_id = GIGADEVICE_GD25Q256D, + .total_size = 32768, .page_size = 256, - /* OTP: 1536B total; read 0x48, write 0x42, erase 0x44 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA | FEATURE_WRSR2 | FEATURE_WRSR3, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { { 4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_21, }, { - .eraseblocks = { { 32 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { { 64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_5C, }, { - .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {2300, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 6, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like TB */ + }, + .decode_range = DECODE_RANGE_SPI25, }, - { +{ .vendor = "GigaDevice", - .name = "GD25VQ40C", + .name = "GD25B512MF/GD25R512MF", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25VQ41B, - .total_size = 512, + .model_id = GIGADEVICE_GD25B512MF, + .total_size = 65536, .page_size = 256, - /* Supports SFDP */ - /* OTP: 1024B total; read 0x48, write 0x42, erase 0x44 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR2 | FEATURE_WRSR3 | FEATURE_4BA, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { { 4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_21, }, { - .eraseblocks = { { 32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { { 64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_5C, }, { - .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {32 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {2300, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 6, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like TB */ + .cmp = {STATUS3, 3, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "GigaDevice", - .name = "GD25VQ41B", + .name = "GD25Q32(B)", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25VQ41B, - .total_size = 512, + .model_id = GIGADEVICE_GD25Q32, + .total_size = 4096, .page_size = 256, - /* OTP: 1536B total; read 0x48, write 0x42, erase 0x44 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR2, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { { 4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { { 32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { { 64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {2300, 3600}, - }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like TB */ + .sec = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */ + .cmp = {STATUS2, 6, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, + }, { .vendor = "GigaDevice", - .name = "GD25VQ80C", + .name = "GD25Q40(B)", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25VQ80C, - .total_size = 1024, + .model_id = GIGADEVICE_GD25Q40, + .total_size = 512, .page_size = 256, - /* Supports SFDP */ - /* OTP: 1024B total; read 0x48, write 0x42, erase 0x44 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { { 4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { { 32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { { 64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, /* TODO: 2nd status reg (read with 0x35) */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {2300, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2700, 3600}, }, { .vendor = "GigaDevice", - .name = "GD25WQ80E", + .name = "GD25Q512", .bustype = BUS_SPI, .manufacture_id = GIGADEVICE_ID, - .model_id = GIGADEVICE_GD25WQ80E, - .total_size = 1024, + .model_id = GIGADEVICE_GD25Q512, + .total_size = 64, .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, - }, { - .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {4 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 2} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {1 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {1 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp4_srwd, - .unlock = spi_disable_blockprotect_bp4_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, - .voltage = {1650, 3600}, - }, - - { - .vendor = "Hyundai", - .name = "HY29F002B", - .bustype = BUS_PARALLEL, - .manufacture_id = HYUNDAI_ID, - .model_id = HYUNDAI_HY29F002B, - .total_size = 256, - .page_size = 256 * 1024, - .feature_bits = FEATURE_EITHER_RESET, /* Some revisions may need FEATURE_ADDR_2AA */ - .tested = TEST_UNTESTED, - .probe = probe_jedec, - .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ - .block_erasers = - { - { - .eraseblocks = { - {16 * 1024, 1}, - {8 * 1024, 2}, - {32 * 1024, 1}, - {64 * 1024, 3}, - }, - .block_erase = erase_sector_jedec, - }, { - .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, - }, - }, - .write = write_jedec_1, - .read = read_memmapped, - .voltage = {4750, 5250}, /* 4.75-5.25V for type -45, others 4.5-5.5V */ - }, - - { - .vendor = "Hyundai", - .name = "HY29F002T", - .bustype = BUS_PARALLEL, - .manufacture_id = HYUNDAI_ID, - .model_id = HYUNDAI_HY29F002T, - .total_size = 256, - .page_size = 256 * 1024, - .feature_bits = FEATURE_EITHER_RESET, /* Some revisions may need FEATURE_ADDR_2AA */ - .tested = TEST_OK_PRE, - .probe = probe_jedec, - .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ - .block_erasers = - { - { - .eraseblocks = { - {64 * 1024, 3}, - {32 * 1024, 1}, - {8 * 1024, 2}, - {16 * 1024, 1}, - }, - .block_erase = erase_sector_jedec, - }, { - .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, - }, - }, - .write = write_jedec_1, - .read = read_memmapped, - .voltage = {4750, 5250}, /* 4.75-5.25V for type -45, others 4.5-5.5V */ - }, - - { - .vendor = "Hyundai", - .name = "HY29F040A", - .bustype = BUS_PARALLEL, - .manufacture_id = HYUNDAI_ID, - .model_id = HYUNDAI_HY29F040A, - .total_size = 512, - .page_size = 64 * 1024, - .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, - .tested = TEST_UNTESTED, - .probe = probe_jedec, - .probe_timing = TIMING_ZERO, - .block_erasers = - { - { - .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, - }, { - .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, - }, - }, - .write = write_jedec_1, - .read = read_memmapped, - .voltage = {4500, 5500}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2700, 3600}, }, { - .vendor = "ISSI", - .name = "IS25LP064", + .vendor = "GigaDevice", + .name = "GD25Q64(B)", .bustype = BUS_SPI, - .manufacture_id = ISSI_ID_SPI, - .model_id = ISSI_IS25LP064, + .manufacture_id = GIGADEVICE_ID, + .model_id = GIGADEVICE_GD25Q64, .total_size = 8192, .page_size = 256, - /* OTP: 1024B total; read 0x48; write 0x42 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR2, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, - }, { - .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, - .voltage = {2300, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like TB */ + .sec = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */ + .cmp = {STATUS2, 6, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { - .vendor = "ISSI", - .name = "IS25LP128", + .vendor = "GigaDevice", + .name = "GD25Q80(B)", .bustype = BUS_SPI, - .manufacture_id = ISSI_ID_SPI, - .model_id = ISSI_IS25LP128, - .total_size = 16384, + .manufacture_id = GIGADEVICE_ID, + .model_id = GIGADEVICE_GD25Q80, + .total_size = 1024, .page_size = 256, - /* OTP: 1024B total; read 0x48; write 0x42 */ + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 (B version only) */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, - }, { - .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_d7, + .eraseblocks = { {4 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, - .voltage = {2300, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2700, 3600}, }, { - .vendor = "ISSI", - .name = "IS25LP256", + .vendor = "GigaDevice", + .name = "GD25T80", .bustype = BUS_SPI, - .manufacture_id = ISSI_ID_SPI, - .model_id = ISSI_IS25LP256, - .total_size = 32768, + .manufacture_id = GIGADEVICE_ID, + .model_id = GIGADEVICE_GD25T80, + .total_size = 1024, .page_size = 256, - /* supports SFDP */ - /* OTP: 1024B total; read 0x68; write 0x62, erase 0x64, read ID 0x4B */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | - FEATURE_4BA | FEATURE_4BA_ENTER_EAR7 | FEATURE_4BA_EAR_1716, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* OTP: 256B total; enter 0x3A */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, - }, { - .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, - /* could also use spi_block_erase_d7 */ - }, { - .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_5c, - }, { - .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {4 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, - .voltage = {2300, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, }, { - .vendor = "ISSI", - .name = "IS25WP032", + .vendor = "GigaDevice", + .name = "GD25VQ16C", .bustype = BUS_SPI, - .manufacture_id = ISSI_ID_SPI, - .model_id = ISSI_IS25WP032, - .total_size = 4096, + .manufacture_id = GIGADEVICE_ID, + .model_id = GIGADEVICE_GD25VQ16C, + .total_size = 2 * 1024, .page_size = 256, - /* OTP: 1024B total; read 0x48; write 0x42 */ - /* QPI enable 0x35, disable 0xF5 */ + /* Supports SFDP */ + /* OTP: 1024B total; read 0x48, write 0x42, erase 0x44 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, - }, { - .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_d7, + .eraseblocks = { { 4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { { 32 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { { 64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, - .voltage = {1650, 1950}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2300, 3600}, }, { - .vendor = "ISSI", - .name = "IS25WP064", + .vendor = "GigaDevice", + .name = "GD25VQ21B", .bustype = BUS_SPI, - .manufacture_id = ISSI_ID_SPI, - .model_id = ISSI_IS25WP064, - .total_size = 8192, + .manufacture_id = GIGADEVICE_ID, + .model_id = GIGADEVICE_GD25VQ21B, + .total_size = 256, .page_size = 256, - /* OTP: 1024B total; read 0x48; write 0x42 */ - /* QPI enable 0x35, disable 0xF5 */ + /* OTP: 1536B total; read 0x48, write 0x42, erase 0x44 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { { 4 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_d7, + .eraseblocks = { { 32 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { { 64 * 1024, 4} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2300, 3600}, + }, + + { + .vendor = "GigaDevice", + .name = "GD25VQ40C", + .bustype = BUS_SPI, + .manufacture_id = GIGADEVICE_ID, + .model_id = GIGADEVICE_GD25VQ41B, + .total_size = 512, + .page_size = 256, + /* Supports SFDP */ + /* OTP: 1024B total; read 0x48, write 0x42, erase 0x44 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { { 4 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { { 32 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { { 64 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, - .voltage = {1650, 1950}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2300, 3600}, }, { - .vendor = "ISSI", - .name = "IS25WP128", + .vendor = "GigaDevice", + .name = "GD25VQ41B", .bustype = BUS_SPI, - .manufacture_id = ISSI_ID_SPI, - .model_id = ISSI_IS25WP128, - .total_size = 16384, + .manufacture_id = GIGADEVICE_ID, + .model_id = GIGADEVICE_GD25VQ41B, + .total_size = 512, .page_size = 256, - /* OTP: 1024B total; read 0x48; write 0x42 */ - /* QPI enable 0x35, disable 0xF5 */ + /* OTP: 1536B total; read 0x48, write 0x42, erase 0x44 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { { 4 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_d7, + .eraseblocks = { { 32 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { { 64 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2300, 3600}, + }, + + { + .vendor = "GigaDevice", + .name = "GD25VQ80C", + .bustype = BUS_SPI, + .manufacture_id = GIGADEVICE_ID, + .model_id = GIGADEVICE_GD25VQ80C, + .total_size = 1024, + .page_size = 256, + /* Supports SFDP */ + /* OTP: 1024B total; read 0x48, write 0x42, erase 0x44 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { { 4 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { { 32 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { { 64 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, - .voltage = {1650, 1950}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2300, 3600}, + }, + +{ + .vendor = "GigaDevice", + .name = "GD25F64F", + .bustype = BUS_SPI, + .manufacture_id = GIGADEVICE_ID, + .model_id = GIGADEVICE_GD25F64F, + .total_size = 8192, + .page_size = 256, + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR2 | FEATURE_WRSR3, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, /* TODO: 2nd status reg (read with 0x35) */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like TB */ + .sec = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like SEC */ + .cmp = {STATUS3, 4, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { - .vendor = "ISSI", - .name = "IS25WP256", + .vendor = "GigaDevice", + .name = "GD25F256F", .bustype = BUS_SPI, - .manufacture_id = ISSI_ID_SPI, - .model_id = ISSI_IS25WP256, + .manufacture_id = GIGADEVICE_ID, + .model_id = GIGADEVICE_GD25F256F, .total_size = 32768, .page_size = 256, - /* supports SFDP */ - /* OTP: 1024B total; read 0x68; write 0x62, erase 0x64, read ID 0x4B */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | - FEATURE_4BA | FEATURE_4BA_ENTER_EAR7 | FEATURE_4BA_EAR_1716, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_WRSR2 | FEATURE_WRSR3 | FEATURE_4BA, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, - /* could also use spi_block_erase_d7 */ + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_5C, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, - .voltage = {1650, 1950}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + .reg_bits = + { + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {STATUS1, 6, RW}, /* Called BP4 in datasheet, acts like TB */ + }, + .decode_range = DECODE_RANGE_SPI25, }, { - .vendor = "ISSI", - .name = "IS29GL064B", - .bustype = BUS_PARALLEL, - .manufacture_id = ISSI_ID, - .model_id = ISSI_PMC_IS29GL064B, - .total_size = 8192, - .page_size = 128 * 1024, /* actual page size is 16 */ - .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, - .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .vendor = "GigaDevice", + .name = "GD25WQ80E", + .bustype = BUS_SPI, + .manufacture_id = GIGADEVICE_ID, + .model_id = GIGADEVICE_GD25WQ80E, + .total_size = 1024, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { - {8 * 1024, 8}, - {64 * 1024, 127}, - }, - .block_erase = erase_sector_jedec, + .eraseblocks = { {4 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, - }, + .eraseblocks = { {32 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {1 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {1 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } }, - .write = write_jedec_1, - .read = read_memmapped, - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 3600}, }, { - .vendor = "ISSI", - .name = "IS29GL064H/L", + .vendor = "Hyundai", + .name = "HY29F002B", .bustype = BUS_PARALLEL, - .manufacture_id = ISSI_ID, - .model_id = ISSI_PMC_IS29GL064HL, - .total_size = 8192, - .page_size = 128 * 1024, /* actual page size is 16 */ - .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, + .manufacture_id = HYUNDAI_ID, + .model_id = HYUNDAI_HY29F002B, + .total_size = 256, + .page_size = 256 * 1024, + .feature_bits = FEATURE_EITHER_RESET, /* Some revisions may need FEATURE_ADDR_2AA */ .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, - .probe_timing = TIMING_ZERO, + .probe = PROBE_JEDEC, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { - .eraseblocks = { {64 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .eraseblocks = { + {16 * 1024, 1}, + {8 * 1024, 2}, + {32 * 1024, 1}, + {64 * 1024, 3}, + }, + .block_erase = JEDEC_SECTOR_ERASE, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, - .voltage = {2700, 3600}, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, + .voltage = {4750, 5250}, /* 4.75-5.25V for type -45, others 4.5-5.5V */ }, { - .vendor = "ISSI", - .name = "IS29GL064T", + .vendor = "Hyundai", + .name = "HY29F002T", .bustype = BUS_PARALLEL, - .manufacture_id = ISSI_ID, - .model_id = ISSI_PMC_IS29GL064T, - .total_size = 8192, - .page_size = 128 * 1024, /* actual page size is 16 */ - .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, - .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, - .probe_timing = TIMING_ZERO, + .manufacture_id = HYUNDAI_ID, + .model_id = HYUNDAI_HY29F002T, + .total_size = 256, + .page_size = 256 * 1024, + .feature_bits = FEATURE_EITHER_RESET, /* Some revisions may need FEATURE_ADDR_2AA */ + .tested = TEST_OK_PRE, + .probe = PROBE_JEDEC, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { - {64 * 1024, 127}, - {8 * 1024, 8}, + {64 * 1024, 3}, + {32 * 1024, 1}, + {8 * 1024, 2}, + {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, - .voltage = {2700, 3600}, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, + .voltage = {4750, 5250}, /* 4.75-5.25V for type -45, others 4.5-5.5V */ }, { - .vendor = "ISSI", - .name = "IS29GL128H/L", + .vendor = "Hyundai", + .name = "HY29F040A", .bustype = BUS_PARALLEL, - .manufacture_id = ISSI_ID, - .model_id = ISSI_PMC_IS29GL128HL, - .total_size = 16384, - .page_size = 128 * 1024, /* actual page size is 16 */ - .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, + .manufacture_id = HYUNDAI_ID, + .model_id = HYUNDAI_HY29F040A, + .total_size = 512, + .page_size = 64 * 1024, + .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {128 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .eraseblocks = { {64 * 1024, 8} }, + .block_erase = JEDEC_SECTOR_ERASE, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, - .voltage = {2700, 3600}, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, + .voltage = {4500, 5500}, }, { - .vendor = "Intel", - .name = "25F160S33B8", + .vendor = "ISSI", + .name = "IS25LP016", .bustype = BUS_SPI, - .manufacture_id = INTEL_ID, - .model_id = INTEL_25F160S33B8, + .manufacture_id = ISSI_ID_SPI, + .model_id = ISSI_IS25LP016, .total_size = 2048, .page_size = 256, - /* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */ + /* OTP: 1024B total; read 0x48; write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - /* This chip supports erasing of the 8 so-called "parameter blocks" with - * opcode 0x40. Trying to access an address outside these 8 8kB blocks does - * have no effect on the memory contents, but sets a flag in the SR. - .eraseblocks = { - {8 * 1024, 8}, - {64 * 1024, 31} // inaccessible - }, - .block_erase = spi_block_erase_40, - }, { */ + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_D7, + }, { + .eraseblocks = { {32 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_ep_srwd, - .unlock = spi_disable_blockprotect_bp2_ep_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* also fast read 0x0B */ - .voltage = {2700, 3600}, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2300, 3600}, }, { - .vendor = "Intel", - .name = "25F160S33T8", + .vendor = "ISSI", + .name = "IS25LP064", .bustype = BUS_SPI, - .manufacture_id = INTEL_ID, - .model_id = INTEL_25F160S33T8, - .total_size = 2048, + .manufacture_id = ISSI_ID_SPI, + .model_id = ISSI_IS25LP064, + .total_size = 8192, .page_size = 256, - /* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */ + /* OTP: 1024B total; read 0x48; write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - /* This chip supports erasing of the 8 so-called "parameter blocks" with - * opcode 0x40. Trying to access an address outside these 8 8kB blocks does - * have no effect on the memory contents, but sets a flag in the SR. - .eraseblocks = { - {64 * 1024, 31}, // inaccessible - {8 * 1024, 8} - }, - .block_erase = spi_block_erase_40, - }, { */ - .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_D7, + }, { + .eraseblocks = { {32 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_ep_srwd, - .unlock = spi_disable_blockprotect_bp2_ep_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* also fast read 0x0B */ - .voltage = {2700, 3600}, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2300, 3600}, }, { - .vendor = "Intel", - .name = "25F320S33B8", + .vendor = "ISSI", + .name = "IS25LP128", .bustype = BUS_SPI, - .manufacture_id = INTEL_ID, - .model_id = INTEL_25F320S33B8, - .total_size = 4096, + .manufacture_id = ISSI_ID_SPI, + .model_id = ISSI_IS25LP128, + .total_size = 16384, .page_size = 256, - /* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */ + /* OTP: 1024B total; read 0x48; write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - /* This chip supports erasing of the 8 so-called "parameter blocks" with - * opcode 0x40. Trying to access an address outside these 8 8kB blocks does - * have no effect on the memory contents, but sets a flag in the SR. - .eraseblocks = { - {8 * 1024, 8}, - {64 * 1024, 63} // inaccessible - }, - .block_erase = spi_block_erase_40, - }, { */ - .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_D7, + }, { + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_ep_srwd, - .unlock = spi_disable_blockprotect_bp2_ep_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* also fast read 0x0B */ - .voltage = {2700, 3600}, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2300, 3600}, }, { - .vendor = "Intel", - .name = "25F320S33T8", + .vendor = "ISSI", + .name = "IS25LP256", .bustype = BUS_SPI, - .manufacture_id = INTEL_ID, - .model_id = INTEL_25F320S33T8, - .total_size = 4096, + .manufacture_id = ISSI_ID_SPI, + .model_id = ISSI_IS25LP256, + .total_size = 32768, .page_size = 256, - /* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + /* supports SFDP */ + /* OTP: 1024B total; read 0x68; write 0x62, erase 0x64, read ID 0x4B */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | + FEATURE_4BA | FEATURE_4BA_ENTER_EAR7 | FEATURE_4BA_EAR_1716, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - /* This chip supports erasing of the 8 so-called "parameter blocks" with - * opcode 0x40. Trying to access an address outside these 8 8kB blocks does - * have no effect on the memory contents, but sets a flag in the SR. - .eraseblocks = { - {64 * 1024, 63}, // inaccessible - {8 * 1024, 8} - }, - .block_erase = spi_block_erase_40, - }, { */ - .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_21, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_20, + /* could also use SPI_BLOCK_ERASE_D7 */ + }, { + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_5C, + }, { + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_ep_srwd, - .unlock = spi_disable_blockprotect_bp2_ep_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* also fast read 0x0B */ - .voltage = {2700, 3600}, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2300, 3600}, }, + { - .vendor = "Intel", - .name = "25F640S33B8", + .vendor = "ISSI", + .name = "IS25LQ016", .bustype = BUS_SPI, - .manufacture_id = INTEL_ID, - .model_id = INTEL_25F640S33B8, - .total_size = 8192, + .manufacture_id = ISSI_ID_SPI, + .model_id = ISSI_IS25LQ016, + .total_size = 2048, .page_size = 256, - /* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + /* OTP: 256B total; read 0x4b; write 0xb1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - /* This chip supports erasing of the 8 so-called "parameter blocks" with - * opcode 0x40. Trying to access an address outside these 8 8kB blocks does - * have no effect on the memory contents, but sets a flag in the SR. - .eraseblocks = { - {8 * 1024, 8}, - {64 * 1024, 127} // inaccessible - }, - .block_erase = spi_block_erase_40, - }, { */ - .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_D7, + }, { + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_ep_srwd, - .unlock = spi_disable_blockprotect_bp2_ep_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* also fast read 0x0B */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2300, 3600}, }, { - .vendor = "Intel", - .name = "25F640S33T8", + .vendor = "ISSI", + .name = "IS25WP016", .bustype = BUS_SPI, - .manufacture_id = INTEL_ID, - .model_id = INTEL_25F640S33T8, - .total_size = 8192, + .manufacture_id = ISSI_ID_SPI, + .model_id = ISSI_IS25WP016, + .total_size = 2048, .page_size = 256, - /* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + /* OTP: 1024B total; read 0x48; write 0x42 */ + /* QPI enable 0x35, disable 0xF5 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - /* This chip supports erasing of the 8 so-called "parameter blocks" with - * opcode 0x40. Trying to access an address outside these 8 8kB blocks does - * have no effect on the memory contents, but sets a flag in the SR. - .eraseblocks = { - {64 * 1024, 127}, // inaccessible - {8 * 1024, 8} - }, - .block_erase = spi_block_erase_40, - }, { */ - .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_D7, + }, { + .eraseblocks = { {32 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_ep_srwd, - .unlock = spi_disable_blockprotect_bp2_ep_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* also fast read 0x0B */ - .voltage = {2700, 3600}, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, }, { - .vendor = "Intel", - .name = "28F001BN/BX-B", - .bustype = BUS_PARALLEL, - .manufacture_id = INTEL_ID, - .model_id = INTEL_28F001B, - .total_size = 128, - .page_size = 128 * 1024, /* 8k + 2x4k + 112k */ + .vendor = "ISSI", + .name = "IS25WP020", + .bustype = BUS_SPI, + .manufacture_id = ISSI_ID_SPI, + .model_id = ISSI_IS25WP020, + .total_size = 256, + .page_size = 256, + /* OTP: 1024B total; read 0x48; write 0x42 */ + /* QPI enable 0x35, disable 0xF5 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_UNTESTED, - .probe = probe_jedec, - .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { - {8 * 1024, 1}, - {4 * 1024, 2}, - {112 * 1024, 1}, - }, - .block_erase = erase_block_82802ab, - }, + .eraseblocks = { {4 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {4 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D7, + }, { + .eraseblocks = { {32 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 4} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } }, - .write = write_82802ab, - .read = read_memmapped, - .voltage = {4500, 5500}, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, }, { - .vendor = "Intel", - .name = "28F001BN/BX-T", - .bustype = BUS_PARALLEL, + .vendor = "ISSI", + .name = "IS25WP032", + .bustype = BUS_SPI, + .manufacture_id = ISSI_ID_SPI, + .model_id = ISSI_IS25WP032, + .total_size = 4096, + .page_size = 256, + /* OTP: 1024B total; read 0x48; write 0x42 */ + /* QPI enable 0x35, disable 0xF5 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_D7, + }, { + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, + }, + + { + .vendor = "ISSI", + .name = "IS25WP040", + .bustype = BUS_SPI, + .manufacture_id = ISSI_ID_SPI, + .model_id = ISSI_IS25WP040, + .total_size = 512, + .page_size = 256, + /* OTP: 1024B total; read 0x48; write 0x42 */ + /* QPI enable 0x35, disable 0xF5 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {4 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D7, + }, { + .eraseblocks = { {32 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, + }, + + { + .vendor = "ISSI", + .name = "IS25WP064", + .bustype = BUS_SPI, + .manufacture_id = ISSI_ID_SPI, + .model_id = ISSI_IS25WP064, + .total_size = 8192, + .page_size = 256, + /* OTP: 1024B total; read 0x48; write 0x42 */ + /* QPI enable 0x35, disable 0xF5 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_D7, + }, { + .eraseblocks = { {32 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, + }, + + { + .vendor = "ISSI", + .name = "IS25WP080", + .bustype = BUS_SPI, + .manufacture_id = ISSI_ID_SPI, + .model_id = ISSI_IS25WP080, + .total_size = 1024, + .page_size = 256, + /* OTP: 1024B total; read 0x48; write 0x42 */ + /* QPI enable 0x35, disable 0xF5 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {4 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D7, + }, { + .eraseblocks = { {32 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, + }, + + { + .vendor = "ISSI", + .name = "IS25WP128", + .bustype = BUS_SPI, + .manufacture_id = ISSI_ID_SPI, + .model_id = ISSI_IS25WP128, + .total_size = 16384, + .page_size = 256, + /* OTP: 1024B total; read 0x48; write 0x42 */ + /* QPI enable 0x35, disable 0xF5 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_D7, + }, { + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, + }, + + { + .vendor = "ISSI", + .name = "IS25WP256", + .bustype = BUS_SPI, + .manufacture_id = ISSI_ID_SPI, + .model_id = ISSI_IS25WP256, + .total_size = 32768, + .page_size = 256, + /* supports SFDP */ + /* OTP: 1024B total; read 0x68; write 0x62, erase 0x64, read ID 0x4B */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | + FEATURE_4BA | FEATURE_4BA_ENTER_EAR7 | FEATURE_4BA_EAR_1716, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_21, + }, { + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_20, + /* could also use SPI_BLOCK_ERASE_D7 */ + }, { + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_5C, + }, { + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, + }, + + { + .vendor = "ISSI", + .name = "IS25WQ040", + .bustype = BUS_SPI, + .manufacture_id = ISSI_ID_SPI, + .model_id = ISSI_IS25WQ040, + .total_size = 512, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {4 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D7, + }, { + .eraseblocks = { {32 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, + }, + + { + .vendor = "ISSI", + .name = "IS29GL064B", + .bustype = BUS_PARALLEL, + .manufacture_id = ISSI_ID, + .model_id = ISSI_PMC_IS29GL064B, + .total_size = 8192, + .page_size = 128 * 1024, /* actual page size is 16 */ + .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, + .tested = TEST_UNTESTED, + .probe = PROBE_JEDEC_29GL, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { + {8 * 1024, 8}, + {64 * 1024, 127}, + }, + .block_erase = JEDEC_SECTOR_ERASE, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, + }, + }, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, + .voltage = {2700, 3600}, + }, + + { + .vendor = "ISSI", + .name = "IS29GL064H/L", + .bustype = BUS_PARALLEL, + .manufacture_id = ISSI_ID, + .model_id = ISSI_PMC_IS29GL064HL, + .total_size = 8192, + .page_size = 128 * 1024, /* actual page size is 16 */ + .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, + .tested = TEST_UNTESTED, + .probe = PROBE_JEDEC_29GL, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = JEDEC_SECTOR_ERASE, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, + }, + }, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, + .voltage = {2700, 3600}, + }, + + { + .vendor = "ISSI", + .name = "IS29GL064T", + .bustype = BUS_PARALLEL, + .manufacture_id = ISSI_ID, + .model_id = ISSI_PMC_IS29GL064T, + .total_size = 8192, + .page_size = 128 * 1024, /* actual page size is 16 */ + .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, + .tested = TEST_UNTESTED, + .probe = PROBE_JEDEC_29GL, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { + {64 * 1024, 127}, + {8 * 1024, 8}, + }, + .block_erase = JEDEC_SECTOR_ERASE, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, + }, + }, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, + .voltage = {2700, 3600}, + }, + + { + .vendor = "ISSI", + .name = "IS29GL128H/L", + .bustype = BUS_PARALLEL, + .manufacture_id = ISSI_ID, + .model_id = ISSI_PMC_IS29GL128HL, + .total_size = 16384, + .page_size = 128 * 1024, /* actual page size is 16 */ + .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, + .tested = TEST_UNTESTED, + .probe = PROBE_JEDEC_29GL, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {128 * 1024, 128} }, + .block_erase = JEDEC_SECTOR_ERASE, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, + }, + }, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, + .voltage = {2700, 3600}, + }, + + { + .vendor = "Intel", + .name = "25F160S33B8", + .bustype = BUS_SPI, + .manufacture_id = INTEL_ID, + .model_id = INTEL_25F160S33B8, + .total_size = 2048, + .page_size = 256, + /* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + /* This chip supports erasing of the 8 so-called "parameter blocks" with + * opcode 0x40. Trying to access an address outside these 8 8kB blocks does + * have no effect on the memory contents, but sets a flag in the SR. + .eraseblocks = { + {8 * 1024, 8}, + {64 * 1024, 31} // inaccessible + }, + .block_erase = SPI_BLOCK_ERASE_40, + }, { */ + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_EP_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* also fast read 0x0B */ + .voltage = {2700, 3600}, + }, + + { + .vendor = "Intel", + .name = "25F160S33T8", + .bustype = BUS_SPI, + .manufacture_id = INTEL_ID, + .model_id = INTEL_25F160S33T8, + .total_size = 2048, + .page_size = 256, + /* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + /* This chip supports erasing of the 8 so-called "parameter blocks" with + * opcode 0x40. Trying to access an address outside these 8 8kB blocks does + * have no effect on the memory contents, but sets a flag in the SR. + .eraseblocks = { + {64 * 1024, 31}, // inaccessible + {8 * 1024, 8} + }, + .block_erase = SPI_BLOCK_ERASE_40, + }, { */ + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_EP_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* also fast read 0x0B */ + .voltage = {2700, 3600}, + }, + + { + .vendor = "Intel", + .name = "25F320S33B8", + .bustype = BUS_SPI, + .manufacture_id = INTEL_ID, + .model_id = INTEL_25F320S33B8, + .total_size = 4096, + .page_size = 256, + /* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + /* This chip supports erasing of the 8 so-called "parameter blocks" with + * opcode 0x40. Trying to access an address outside these 8 8kB blocks does + * have no effect on the memory contents, but sets a flag in the SR. + .eraseblocks = { + {8 * 1024, 8}, + {64 * 1024, 63} // inaccessible + }, + .block_erase = SPI_BLOCK_ERASE_40, + }, { */ + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_EP_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* also fast read 0x0B */ + .voltage = {2700, 3600}, + }, + + { + .vendor = "Intel", + .name = "25F320S33T8", + .bustype = BUS_SPI, + .manufacture_id = INTEL_ID, + .model_id = INTEL_25F320S33T8, + .total_size = 4096, + .page_size = 256, + /* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + /* This chip supports erasing of the 8 so-called "parameter blocks" with + * opcode 0x40. Trying to access an address outside these 8 8kB blocks does + * have no effect on the memory contents, but sets a flag in the SR. + .eraseblocks = { + {64 * 1024, 63}, // inaccessible + {8 * 1024, 8} + }, + .block_erase = SPI_BLOCK_ERASE_40, + }, { */ + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_EP_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* also fast read 0x0B */ + .voltage = {2700, 3600}, + }, + + { + .vendor = "Intel", + .name = "25F640S33B8", + .bustype = BUS_SPI, + .manufacture_id = INTEL_ID, + .model_id = INTEL_25F640S33B8, + .total_size = 8192, + .page_size = 256, + /* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + /* This chip supports erasing of the 8 so-called "parameter blocks" with + * opcode 0x40. Trying to access an address outside these 8 8kB blocks does + * have no effect on the memory contents, but sets a flag in the SR. + .eraseblocks = { + {8 * 1024, 8}, + {64 * 1024, 127} // inaccessible + }, + .block_erase = SPI_BLOCK_ERASE_40, + }, { */ + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_EP_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* also fast read 0x0B */ + .voltage = {2700, 3600}, + }, + + { + .vendor = "Intel", + .name = "25F640S33T8", + .bustype = BUS_SPI, + .manufacture_id = INTEL_ID, + .model_id = INTEL_25F640S33T8, + .total_size = 8192, + .page_size = 256, + /* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + /* This chip supports erasing of the 8 so-called "parameter blocks" with + * opcode 0x40. Trying to access an address outside these 8 8kB blocks does + * have no effect on the memory contents, but sets a flag in the SR. + .eraseblocks = { + {64 * 1024, 127}, // inaccessible + {8 * 1024, 8} + }, + .block_erase = SPI_BLOCK_ERASE_40, + }, { */ + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_EP_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* also fast read 0x0B */ + .voltage = {2700, 3600}, + }, + + { + .vendor = "Intel", + .name = "28F001BN/BX-B", + .bustype = BUS_PARALLEL, + .manufacture_id = INTEL_ID, + .model_id = INTEL_28F001B, + .total_size = 128, + .page_size = 128 * 1024, /* 8k + 2x4k + 112k */ + .tested = TEST_UNTESTED, + .probe = PROBE_JEDEC, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .block_erasers = + { + { + .eraseblocks = { + {8 * 1024, 1}, + {4 * 1024, 2}, + {112 * 1024, 1}, + }, + .block_erase = ERASE_BLOCK_82802AB, + }, + }, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, + .voltage = {4500, 5500}, + }, + + { + .vendor = "Intel", + .name = "28F001BN/BX-T", + .bustype = BUS_PARALLEL, + .manufacture_id = INTEL_ID, + .model_id = INTEL_28F001T, + .total_size = 128, + .page_size = 128 * 1024, /* 112k + 2x4k + 8k */ + .tested = TEST_OK_PREW, + .probe = PROBE_JEDEC, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .block_erasers = + { + { + .eraseblocks = { + {112 * 1024, 1}, + {4 * 1024, 2}, + {8 * 1024, 1}, + }, + .block_erase = ERASE_BLOCK_82802AB, + }, + }, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, + .voltage = {4500, 5500}, + }, + + { + .vendor = "Intel", + .name = "28F002BC/BL/BV/BX-T", + .bustype = BUS_PARALLEL, + .manufacture_id = INTEL_ID, + .model_id = INTEL_28F002T, + .total_size = 256, + .page_size = 256 * 1024, + .tested = TEST_OK_PRE, + .probe = PROBE_AT82802AB, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .block_erasers = + { + { + .eraseblocks = { + {128 * 1024, 1}, + {96 * 1024, 1}, + {8 * 1024, 2}, + {16 * 1024, 1}, + }, + .block_erase = ERASE_BLOCK_82802AB, + }, + }, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, + }, + + { + .vendor = "Intel", + .name = "28F004B5/BE/BV/BX-B", + .bustype = BUS_PARALLEL, + .manufacture_id = INTEL_ID, + .model_id = INTEL_28F004B, + .total_size = 512, + .page_size = 128 * 1024, /* maximal block size */ + .tested = TEST_UNTESTED, + .probe = PROBE_AT82802AB, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .block_erasers = + { + { + .eraseblocks = { + {16 * 1024, 1}, + {8 * 1024, 2}, + {96 * 1024, 1}, + {128 * 1024, 3}, + }, + .block_erase = ERASE_BLOCK_82802AB, + }, + }, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, + }, + + { + .vendor = "Intel", + .name = "28F004B5/BE/BV/BX-T", + .bustype = BUS_PARALLEL, + .manufacture_id = INTEL_ID, + .model_id = INTEL_28F004T, + .total_size = 512, + .page_size = 128 * 1024, /* maximal block size */ + .tested = TEST_UNTESTED, + .probe = PROBE_AT82802AB, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .block_erasers = + { + { + .eraseblocks = { + {128 * 1024, 3}, + {96 * 1024, 1}, + {8 * 1024, 2}, + {16 * 1024, 1}, + }, + .block_erase = ERASE_BLOCK_82802AB, + }, + }, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, + }, + + { + .vendor = "Intel", + .name = "28F008S3/S5/SC", + .bustype = BUS_PARALLEL, + .manufacture_id = INTEL_ID, + .model_id = INTEL_28F004S3, + .total_size = 512, + .page_size = 256, + .tested = TEST_UNTESTED, + .probe = PROBE_AT82802AB, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .block_erasers = + { + { + .eraseblocks = { {64 * 1024, 8} }, + .block_erase = ERASE_BLOCK_82802AB, + }, + }, + .unlock = UNLOCK_28F004S5, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, + }, + + { + .vendor = "Intel", + .name = "28F400BV/BX/CE/CV-B", + .bustype = BUS_PARALLEL, + .manufacture_id = INTEL_ID, + .model_id = INTEL_28F400B, + .total_size = 512, + .page_size = 128 * 1024, /* maximal block size */ + .feature_bits = FEATURE_ADDR_SHIFTED, + .tested = TEST_UNTESTED, + .probe = PROBE_AT82802AB, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .block_erasers = + { + { + .eraseblocks = { + {16 * 1024, 1}, + {8 * 1024, 2}, + {96 * 1024, 1}, + {128 * 1024, 3}, + }, + .block_erase = ERASE_BLOCK_82802AB, + }, + }, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, + }, + + { + .vendor = "Intel", + .name = "28F400BV/BX/CE/CV-T", + .bustype = BUS_PARALLEL, + .manufacture_id = INTEL_ID, + .model_id = INTEL_28F400T, + .total_size = 512, + .page_size = 128 * 1024, /* maximal block size */ + .feature_bits = FEATURE_ADDR_SHIFTED, + .tested = TEST_UNTESTED, + .probe = PROBE_AT82802AB, + .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .block_erasers = + { + { + .eraseblocks = { + {128 * 1024, 3}, + {96 * 1024, 1}, + {8 * 1024, 2}, + {16 * 1024, 1}, + }, + .block_erase = ERASE_BLOCK_82802AB, + }, + }, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, + }, + + { + .vendor = "Intel", + .name = "AT82802AB", + .bustype = BUS_FWH, .manufacture_id = INTEL_ID, - .model_id = INTEL_28F001T, + .model_id = INTEL_82802AB, + .total_size = 512, + .page_size = 64 * 1024, + .feature_bits = FEATURE_REGISTERMAP, + .tested = TEST_OK_PREW, + .probe = PROBE_AT82802AB, + .probe_timing = TIMING_IGNORED, /* routine does not use probe_timing (82802ab.c) */ + .block_erasers = + { + { + .eraseblocks = { {64 * 1024, 8} }, + .block_erase = ERASE_BLOCK_82802AB, + }, + }, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, + .voltage = {3000, 3600}, + }, + + { + .vendor = "Intel", + .name = "82802AC", + .bustype = BUS_FWH, + .manufacture_id = INTEL_ID, + .model_id = INTEL_82802AC, + .total_size = 1024, + .page_size = 64 * 1024, + .feature_bits = FEATURE_REGISTERMAP, + .tested = TEST_OK_PR, + .probe = PROBE_AT82802AB, + .probe_timing = TIMING_IGNORED, /* routine does not use probe_timing (82802ab.c) */ + .block_erasers = + { + { + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = ERASE_BLOCK_82802AB, + }, + }, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, + .voltage = {3000, 3600}, + }, + + { + .vendor = "Macronix", + .name = "MX23L12854", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX23L12854, + .total_size = 16384, + .page_size = 256, + .tested = {.probe = NT, .read = NT, .erase = NA, .write = NA, .wp = NA}, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .write = 0, /* MX23L12854 is a mask ROM, so it is read-only */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {3000, 3600}, + }, + + { + .vendor = "Macronix", + .name = "MX23L1654", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX23L1654, + .total_size = 2048, + .page_size = 256, + .tested = {.probe = NT, .read = NT, .erase = NA, .write = NA, .wp = NA}, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .write = 0, /* MX23L1654 is a mask ROM, so it is read-only */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {3000, 3600}, + }, + + { + .vendor = "Macronix", + .name = "MX23L3254", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX23L3254, + .total_size = 4096, + .page_size = 256, + .tested = {.probe = OK, .read = OK, .erase = NA, .write = NA, .wp = NA}, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .write = 0, /* MX23L3254 is a mask ROM, so it is read-only */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {3000, 3600}, + }, + + { + .vendor = "Macronix", + .name = "MX23L6454", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX23L6454, + .total_size = 8192, + .page_size = 256, + .tested = {.probe = OK, .read = OK, .erase = NA, .write = NA, .wp = NA}, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .write = 0, /* MX23L6454 is a mask ROM, so it is read-only */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {3000, 3600}, + }, + + { + .vendor = "Macronix", + .name = "MX25L1005(C)/MX25L1006E", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L1005, .total_size = 128, - .page_size = 128 * 1024, /* 112k + 2x4k + 8k */ + .page_size = 256, + /* MX25L1006E supports SFDP */ + .feature_bits = FEATURE_WRSR_WREN, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 2} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {128 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {128 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + }, + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported, MX25L1006E supports dual I/O */ + .voltage = {2700, 3600}, + }, + + { + .vendor = "Macronix", + .name = "MX25L12805D", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L12805D, + .total_size = 16384, + .page_size = 256, + /* OTP: 64B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {2700, 3600}, + }, + + { + .vendor = "Macronix", + .name = "MX25L12833F", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L12805D, + .total_size = 16384, + .page_size = 256, + /* OTP: 1KB total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_CFGR | FEATURE_SCUR, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {CONFIG, 3, OTP}, + .wps = {SECURITY, 7, OTP}, /* This bit is set by WPSEL command */ + }, + .decode_range = DECODE_RANGE_SPI25, + }, + + { + .vendor = "Macronix", + .name = "MX25L12835F/MX25L12873F", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L12805D, + .total_size = 16384, + .page_size = 256, + /* OTP: 512B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_CFGR | FEATURE_SCUR, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {CONFIG, 3, OTP}, + .wps = {SECURITY, 7, OTP}, /* This bit is set by WPSEL command */ + }, + .decode_range = DECODE_RANGE_SPI25, + }, + + { + .vendor = "Macronix", + .name = "MX25L12845E/MX25L12865E", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L12805D, + .total_size = 16384, + .page_size = 256, + /* OTP: 512B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_SCUR, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .wps = {SECURITY, 7, OTP}, /* This bit is set by WPSEL command */ + }, + .decode_range = DECODE_RANGE_SPI25, + }, + + { + .vendor = "Macronix", + .name = "MX25L12850F", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L12805D, + .total_size = 16384, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_CFGR, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {CONFIG, 3, OTP} + }, + + .decode_range = DECODE_RANGE_SPI25, + }, + + { + .vendor = "Macronix", + .name = "MX25L1605", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L1605, + .total_size = 2048, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_jedec, - .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { - {112 * 1024, 1}, - {4 * 1024, 2}, - {8 * 1024, 1}, - }, - .block_erase = erase_block_82802ab, + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .write = write_82802ab, - .read = read_memmapped, - .voltage = {4500, 5500}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, /* bit6: error flag */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {2700, 3600}, }, { - .vendor = "Intel", - .name = "28F002BC/BL/BV/BX-T", - .bustype = BUS_PARALLEL, - .manufacture_id = INTEL_ID, - .model_id = INTEL_28F002T, - .total_size = 256, - .page_size = 256 * 1024, - .tested = TEST_OK_PRE, - .probe = probe_82802ab, - .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .vendor = "Macronix", + .name = "MX25V16066", /* was called KH25V16066 in rev v1.3 */ + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L1605, + .total_size = 2048, /* 16M-bits */ + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN, + .tested = TEST_OK_PR, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { - {128 * 1024, 1}, - {96 * 1024, 1}, - {8 * 1024, 2}, - {16 * 1024, 1}, - }, - .block_erase = erase_block_82802ab, + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .write = write_82802ab, - .read = read_memmapped, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {2700, 3600}, }, { - .vendor = "Intel", - .name = "28F004B5/BE/BV/BX-B", - .bustype = BUS_PARALLEL, - .manufacture_id = INTEL_ID, - .model_id = INTEL_28F004B, - .total_size = 512, - .page_size = 128 * 1024, /* maximal block size */ - .tested = TEST_UNTESTED, - .probe = probe_82802ab, - .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .vendor = "Macronix", + .name = "MX25L1605A/MX25L1606E/MX25L1608E", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L1605, + .total_size = 2048, + .page_size = 256, + /* OTP: 64B total; enter 0xB1, exit 0xC1 (MX25L1606E and MX25L1608E only) */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { - {16 * 1024, 1}, - {8 * 1024, 2}, - {96 * 1024, 1}, - {128 * 1024, 3}, - }, - .block_erase = erase_block_82802ab, + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .write = write_82802ab, - .read = read_memmapped, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* MX25L1605A bp2 only */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported (MX25L1608E supports dual-I/O read) */ + .voltage = {2700, 3600}, }, { - .vendor = "Intel", - .name = "28F004B5/BE/BV/BX-T", - .bustype = BUS_PARALLEL, - .manufacture_id = INTEL_ID, - .model_id = INTEL_28F004T, - .total_size = 512, - .page_size = 128 * 1024, /* maximal block size */ - .tested = TEST_UNTESTED, - .probe = probe_82802ab, - .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .vendor = "Macronix", + .name = "MX25L1605D/MX25L1608D/MX25L1673E", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L1605, + .total_size = 2048, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { - {128 * 1024, 3}, - {96 * 1024, 1}, - {8 * 1024, 2}, - {16 * 1024, 1}, - }, - .block_erase = erase_block_82802ab, + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .write = write_82802ab, - .read = read_memmapped, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6: Continuously Program (CP) mode, for 73E is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O supported */ + .voltage = {2700, 3600}, }, { - .vendor = "Intel", - .name = "28F008S3/S5/SC", - .bustype = BUS_PARALLEL, - .manufacture_id = INTEL_ID, - .model_id = INTEL_28F004S3, - .total_size = 512, + .vendor = "Macronix", + .name = "MX25L1635D", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L1635D, + .total_size = 2048, .page_size = 256, - .tested = TEST_UNTESTED, - .probe = probe_82802ab, - .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + /* OTP: 64B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_block_82802ab, - }, + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } }, - .unlock = unlock_28f004s5, - .write = write_82802ab, - .read = read_memmapped, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2700, 3600}, }, { - .vendor = "Intel", - .name = "28F400BV/BX/CE/CV-B", - .bustype = BUS_PARALLEL, - .manufacture_id = INTEL_ID, - .model_id = INTEL_28F400B, - .total_size = 512, - .page_size = 128 * 1024, /* maximal block size */ - .feature_bits = FEATURE_ADDR_SHIFTED, - .tested = TEST_UNTESTED, - .probe = probe_82802ab, - .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .vendor = "Macronix", + .name = "MX25L1633E", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L1635D, + .total_size = 2048, + .page_size = 256, + /* OTP: 64B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP , + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { - {16 * 1024, 1}, - {8 * 1024, 2}, - {96 * 1024, 1}, - {128 * 1024, 3}, - }, - .block_erase = erase_block_82802ab, - }, + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, }, - .write = write_82802ab, - .read = read_memmapped, + + .decode_range = DECODE_RANGE_SPI25, }, { - .vendor = "Intel", - .name = "28F400BV/BX/CE/CV-T", - .bustype = BUS_PARALLEL, - .manufacture_id = INTEL_ID, - .model_id = INTEL_28F400T, - .total_size = 512, - .page_size = 128 * 1024, /* maximal block size */ - .feature_bits = FEATURE_ADDR_SHIFTED, - .tested = TEST_UNTESTED, - .probe = probe_82802ab, - .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ + .vendor = "Macronix", + .name = "MX25L1635E/MX25L1636E", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L1635E, + .total_size = 2048, + .page_size = 256, + /* OTP: 512B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { - {128 * 1024, 3}, - {96 * 1024, 1}, - {8 * 1024, 2}, - {16 * 1024, 1}, - }, - .block_erase = erase_block_82802ab, - }, + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, }, - .write = write_82802ab, - .read = read_memmapped, + + .decode_range = DECODE_RANGE_SPI25, }, { - .vendor = "Intel", - .name = "82802AB", - .bustype = BUS_FWH, - .manufacture_id = INTEL_ID, - .model_id = INTEL_82802AB, - .total_size = 512, - .page_size = 64 * 1024, - .feature_bits = FEATURE_REGISTERMAP, + .vendor = "Macronix", + .name = "MX25L2005(C)/MX25L2006E", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L2005, + .total_size = 256, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_82802ab, - .probe_timing = TIMING_IGNORED, /* routine does not use probe_timing (82802ab.c) */ + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_block_82802ab, + .eraseblocks = { {4 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 4} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 4} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .unlock = unlock_regspace2_uniform_64k, - .write = write_82802ab, - .read = read_memmapped, - .voltage = {3000, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {2700, 3600}, }, { - .vendor = "Intel", - .name = "82802AC", - .bustype = BUS_FWH, - .manufacture_id = INTEL_ID, - .model_id = INTEL_82802AC, - .total_size = 1024, - .page_size = 64 * 1024, - .feature_bits = FEATURE_REGISTERMAP, - .tested = TEST_OK_PR, - .probe = probe_82802ab, - .probe_timing = TIMING_IGNORED, /* routine does not use probe_timing (82802ab.c) */ + .vendor = "Macronix", + .name = "MX25L25635F/MX25L25645G", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX25L25635F, + .total_size = 32768, + .page_size = 256, + /* OTP: 512B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {64 * 1024, 16} }, - .block_erase = erase_block_82802ab, - }, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_21, + }, { + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_5C, + }, { + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } }, - .unlock = unlock_regspace2_uniform_64k, - .write = write_82802ab, - .read = read_memmapped, - .voltage = {3000, 3600}, + /* TODO: security register and SBLK/SBULK; MX25L12835F: configuration register */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {2700, 3600}, }, { .vendor = "Macronix", - .name = "MX23L12854", + .name = "MX25L3205(A)", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX23L12854, - .total_size = 16384, + .model_id = MACRONIX_MX25L3205, + .total_size = 4096, .page_size = 256, - .tested = {.probe = NT, .read = NT, .erase = NA, .write = NA}, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, - .write = NULL, /* MX23L12854 is a mask ROM, so it is read-only */ - .read = spi_chip_read, /* Fast read (0x0B) supported */ - .voltage = {3000, 3600}, + .block_erasers = + { + { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + }, + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, /* bit6: error flag */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {2700, 3600}, }, { .vendor = "Macronix", - .name = "MX23L1654", + .name = "MX25L3205D/MX25L3208D", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX23L1654, - .total_size = 2048, + .model_id = MACRONIX_MX25L3205, + .total_size = 4096, .page_size = 256, - .tested = {.probe = NT, .read = NT, .erase = NA, .write = NA}, - .probe = probe_spi_rdid, + /* OTP: 64B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, - .write = NULL, /* MX23L1654 is a mask ROM, so it is read-only */ - .read = spi_chip_read, /* Fast read (0x0B) supported */ - .voltage = {3000, 3600}, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + }, + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6: continuously program mode */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and dual I/O supported */ + .voltage = {2700, 3600}, }, { .vendor = "Macronix", - .name = "MX23L3254", + .name = "MX25L3206E/MX25L3208E", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX23L3254, + .model_id = MACRONIX_MX25L3205, .total_size = 4096, .page_size = 256, - .tested = {.probe = OK, .read = OK, .erase = NA, .write = NA}, - .probe = probe_spi_rdid, + /* OTP: 64B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, - .write = NULL, /* MX23L3254 is a mask ROM, so it is read-only */ - .read = spi_chip_read, /* Fast read (0x0B) supported */ - .voltage = {3000, 3600}, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + }, + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and dual I/O supported */ + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .cmp = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like CMP */ + }, + .decode_range = DECODE_RANGE_SPI25_BIT_CMP, }, - - { + { .vendor = "Macronix", - .name = "MX23L6454", + .name = "MX25L3273F", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX23L6454, - .total_size = 8192, + .model_id = MACRONIX_MX25L3205, + .total_size = 4096, .page_size = 256, - .tested = {.probe = OK, .read = OK, .erase = NA, .write = NA}, - .probe = probe_spi_rdid, + /* OTP: 512B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_CFGR, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, - .write = NULL, /* MX23L6454 is a mask ROM, so it is read-only */ - .read = spi_chip_read, /* Fast read (0x0B) supported */ - .voltage = {3000, 3600}, - }, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit 6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2650, 3600}, + .reg_bits = + { + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {CONFIG, 3, OTP} + }, - { + .decode_range = DECODE_RANGE_SPI25, + }, + + { .vendor = "Macronix", - .name = "MX25L1005(C)/MX25L1006E", + .name = "MX25L3239E", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L1005, - .total_size = 128, + .model_id = MACRONIX_MX25L3239E, + .total_size = 4096, .page_size = 256, - /* MX25L1006E supports SFDP */ - .feature_bits = FEATURE_WRSR_WREN, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* OTP: 512B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_CFGR | FEATURE_SCUR , + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 2} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, - }, + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported, MX25L1006E supports dual I/O */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit 6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {CONFIG, 3, OTP}, + .wps = {SECURITY, 7, OTP}, /* This bit is set by WPSEL command */ + }, + + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "Macronix", - .name = "MX25L12805D", + .name = "MX25L3235D", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L12805D, - .total_size = 16384, + .model_id = MACRONIX_MX25L3235D, + .total_size = 4096, .page_size = 256, - /* OTP: 64B total; enter 0xB1, exit 0xC1 */ + /* OTP: 256B total; enter 0xB1, exit 0xC1 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, { .vendor = "Macronix", - .name = "MX25L12833F/MX25L12835F/MX25L12845E/MX25L12865E/MX25L12873F", + .name = "MX25L3233F/MX25L3273E", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L12805D, - .total_size = 16384, + .model_id = MACRONIX_MX25L3205, + .total_size = 4096, .page_size = 256, - /* OTP: MX25L12833F has 1KB total, others have 512B total; enter 0xB1, exit 0xC1 */ + /* OTP: 512B total; enter 0xB1, exit 0xC1 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, - } + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + }, }, - /* TODO: security register and SBLK/SBULK; MX25L12835F: configuration register */ - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and dual I/O supported */ + .voltage = {2700, 3600}, /* 33F 2.65V..3.6V */ }, { .vendor = "Macronix", - .name = "MX25L1605", + .name = "MX25L3255E", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L1605, - .total_size = 2048, + .model_id = MACRONIX_MX25L3255E, + .total_size = 4096, .page_size = 256, - .feature_bits = FEATURE_WRSR_WREN, + /* OTP: 4K total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_bp2_srwd, /* bit6: error flag */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + /* Fast read (0x0B), 2x and 4x I/O supported */ + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, { .vendor = "Macronix", - .name = "MX25L1605A/MX25L1606E/MX25L1608E", + .name = "MX25L4005(A/C)/MX25L4006E", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L1605, - .total_size = 2048, + .model_id = MACRONIX_MX25L4005, + .total_size = 512, .page_size = 256, - /* OTP: 64B total; enter 0xB1, exit 0xC1 (MX25L1606E and MX25L1608E only) */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {64 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* MX25L1605A bp2 only */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported (MX25L1608E supports dual-I/O read) */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, { .vendor = "Macronix", - .name = "MX25L1605D/MX25L1608D/MX25L1673E", + .name = "MX25L512(E)/MX25V512(C)", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L1605, - .total_size = 2048, + .model_id = MACRONIX_MX25L512, + .total_size = 64, .page_size = 256, + /* MX25L512E supports SFDP */ .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6: Continuously Program (CP) mode, for 73E is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported, MX25L512E supports dual I/O */ + .voltage = {2700, 3600}, /* 2.35-3.6V for MX25V512(C) */ }, { .vendor = "Macronix", - .name = "MX25L1635D", + .name = "MX25L5121E", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L1635D, - .total_size = 2048, - .page_size = 256, - /* OTP: 64B total; enter 0xB1, exit 0xC1 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .model_id = MACRONIX_MX25L5121E, + .total_size = 64, + .page_size = 32, + .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, - } + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + }, }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, { .vendor = "Macronix", - .name = "MX25L1635E", + .name = "MX25L6405", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L1635E, - .total_size = 2048, + .model_id = MACRONIX_MX25L6405, + .total_size = 8192, .page_size = 256, - /* OTP: 64B total; enter 0xB1, exit 0xC1 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + /* Has an additional 512B EEPROM sector */ + .feature_bits = FEATURE_WRSR_WREN, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6: error flag */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "Macronix", - .name = "MX25L2005(C)/MX25L2006E", + .name = "MX25L6405D", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L2005, - .total_size = 256, + .model_id = MACRONIX_MX25L6405, + .total_size = 8192, .page_size = 256, - .feature_bits = FEATURE_WRSR_WREN, + /* OTP: 64B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, - }, { - .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, - }, + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6: continuously program mode */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O read (0xBB) supported */ .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .cmp = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like CMP */ + }, + .decode_range = DECODE_RANGE_SPI25_BIT_CMP, }, { .vendor = "Macronix", - .name = "MX25L25635F/MX25L25645G", + .name = "MX25L6406E/MX25L6408E", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L25635F, - .total_size = 32768, + .model_id = MACRONIX_MX25L6405, + .total_size = 8192, .page_size = 256, - /* OTP: 512B total; enter 0xB1, exit 0xC1 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* MX25L6406E supports SFDP */ + /* OTP: 06E 64B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, - }, { - .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, - }, { - .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_5c, - }, { - .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - /* TODO: security register and SBLK/SBULK; MX25L12835F: configuration register */ - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O read supported */ .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .cmp = {STATUS1, 5, RW}, /* Called BP3 in datasheet, acts like CMP */ + }, + .decode_range = DECODE_RANGE_SPI25_BIT_CMP, }, { .vendor = "Macronix", - .name = "MX25L3205(A)", + .name = "MX25L6436E/MX25L6445E/MX25L6465E", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L3205, - .total_size = 4096, + .model_id = MACRONIX_MX25L6405, + .total_size = 8192, .page_size = 256, - .feature_bits = FEATURE_WRSR_WREN, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* supports SFDP */ + /* OTP: 512B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_SCUR, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, - }, + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, /* bit6: error flag */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .wps = {SECURITY, 7, OTP}, /* This bit is set by WPSEL command */ + }, + .decode_range = DECODE_RANGE_SPI25_2X_BLOCK, }, { .vendor = "Macronix", - .name = "MX25L3205D/MX25L3208D", + .name = "MX25L6473E", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L3205, - .total_size = 4096, + .model_id = MACRONIX_MX25L6405, + .total_size = 8192, .page_size = 256, - /* OTP: 64B total; enter 0xB1, exit 0xC1 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + /* supports SFDP */ + /* OTP: 512B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2 | FEATURE_SCUR, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, - }, + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6: continuously program mode */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and dual I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {CONFIG, 3, OTP}, + .wps = {SECURITY, 7, OTP}, /* This bit is set by WPSEL command */ + }, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "Macronix", - .name = "MX25L3206E/MX25L3208E", + .name = "MX25L6473F", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L3205, - .total_size = 4096, + .model_id = MACRONIX_MX25L6405, + .total_size = 8192, .page_size = 256, - /* OTP: 64B total; enter 0xB1, exit 0xC1 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + /* supports SFDP */ + /* OTP: 512B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, - }, + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and dual I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {CONFIG, 3, OTP}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "Macronix", - .name = "MX25L3235D", + .name = "MX25L6495F", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L3235D, - .total_size = 4096, + .model_id = MACRONIX_MX25L6495F, + .total_size = 8192, .page_size = 256, - /* OTP: 256B total; enter 0xB1, exit 0xC1 */ + /* OTP: 1024B total; enter 0xB1, exit 0xC1 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, { .vendor = "Macronix", - .name = "MX25L3233F/MX25L3273E", + .name = "MX25L8005/MX25L8006E/MX25L8008E/MX25V8005", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L3205, - .total_size = 4096, + .model_id = MACRONIX_MX25L8005, + .total_size = 1024, .page_size = 256, - /* OTP: 512B total; enter 0xB1, exit 0xC1 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + /* MX25L8006E, MX25L8008E support SFDP */ + /* OTP: 64B total; enter 0xB1, exit 0xC1 (MX25L8006E, MX25L8008E only) */ + .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and dual I/O supported */ - .voltage = {2700, 3600}, /* 33F 2.65V..3.6V */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {2700, 3600}, /* 2.35-3.6V for MX25V8005 */ }, { .vendor = "Macronix", - .name = "MX25L4005(A/C)/MX25L4006E", + .name = "MX25R1635F", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L4005, - .total_size = 512, - .page_size = 256, - .feature_bits = FEATURE_WRSR_WREN, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .model_id = MACRONIX_MX25R1635F, + .total_size = 2048, + .page_size = 256, + /* OTP: 1024B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_CFGR, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, - }, + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit 6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1650, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {CONFIG, 3, OTP} + }, + + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "Macronix", - .name = "MX25L512(E)/MX25V512(C)", + .name = "MX25R2035F", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L512, - .total_size = 64, + .model_id = MACRONIX_MX25R2035F, + .total_size = 256, .page_size = 256, - /* MX25L512E supports SFDP */ - .feature_bits = FEATURE_WRSR_WREN, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* OTP: 1024B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_CFGR, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 16} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 4} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {1 * 256 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, - }, + .eraseblocks = { {1 * 256 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported, MX25L512E supports dual I/O */ - .voltage = {2700, 3600}, /* 2.35-3.6V for MX25V512(C) */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit 6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1650, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {CONFIG, 3, OTP} + }, + + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "Macronix", - .name = "MX25L5121E", + .name = "MX25R3235F", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L5121E, - .total_size = 64, - .page_size = 32, - .feature_bits = FEATURE_WRSR_WREN, + .model_id = MACRONIX_MX25R3235F, + .total_size = 4096, + .page_size = 256, + /* OTP: 1024B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 16} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, - }, + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit 6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1650, 3600}, }, { .vendor = "Macronix", - .name = "MX25L6405", + .name = "MX25R4035F", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L6405, - .total_size = 8192, + .model_id = MACRONIX_MX25R4035F, + .total_size = 512, .page_size = 256, - /* Has an additional 512B EEPROM sector */ - .feature_bits = FEATURE_WRSR_WREN, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* OTP: 1024B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_CFGR, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {64 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {1 * 512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {1 * 512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6: error flag */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit 6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1650, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {CONFIG, 3, OTP} + }, + + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "Macronix", - .name = "MX25L6405D", + .name = "MX25R6435F", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L6405, + .model_id = MACRONIX_MX25R6435F, .total_size = 8192, .page_size = 256, - /* OTP: 64B total; enter 0xB1, exit 0xC1 */ + /* OTP: 1024B total; enter 0xB1, exit 0xC1 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6: continuously program mode */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O read (0xBB) supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1650, 3600}, }, { .vendor = "Macronix", - .name = "MX25L6406E/MX25L6408E", + .name = "MX25R8035F", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L6405, - .total_size = 8192, + .model_id = MACRONIX_MX25R8035F, + .total_size = 1024, .page_size = 256, - /* MX25L6406E supports SFDP */ - /* OTP: 06E 64B total; enter 0xB1, exit 0xC1 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* OTP: 1024B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_CFGR, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {1 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {1 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O read supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit 6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1650, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {CONFIG, 3, OTP} + }, + + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "Macronix", - .name = "MX25L6436E/MX25L6445E/MX25L6465E/MX25L6473E/MX25L6473F", + .name = "MX25V4035F", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L6405, - .total_size = 8192, + .model_id = MACRONIX_MX25V4035F, + .total_size = 512, .page_size = 256, - /* supports SFDP */ - /* OTP: 512B total; enter 0xB1, exit 0xC1 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* OTP: 8KiB total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_SCUR, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, - }, { - .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { { 4 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {64 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {512 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2300, 3600}, }, - { .vendor = "Macronix", - .name = "MX25L6495F", + .name = "MX25V8035F", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L6495F, - .total_size = 8192, + .model_id = MACRONIX_MX25V8035F, + .total_size = 1024, .page_size = 256, - /* OTP: 1024B total; enter 0xB1, exit 0xC1 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* OTP: 8KiB total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_SCUR, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, - }, { - .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { { 4 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {1 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {2700, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2300, 3600}, }, - { .vendor = "Macronix", - .name = "MX25L8005/MX25L8006E/MX25L8008E/MX25V8005", + .name = "MX25V1635F", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25L8005, - .total_size = 1024, + .model_id = MACRONIX_MX25V1635F, + .total_size = 2048, .page_size = 256, - /* MX25L8006E, MX25L8008E support SFDP */ - /* OTP: 64B total; enter 0xB1, exit 0xC1 (MX25L8006E, MX25L8008E only) */ - .feature_bits = FEATURE_WRSR_WREN, + /* OTP: 8KiB total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_SCUR, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, - }, { - .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { { 4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, - }, + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ - .voltage = {2700, 3600}, /* 2.35-3.6V for MX25V8005 */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {2300, 3600}, }, { .vendor = "Macronix", - .name = "MX25R3235F", + .name = "MX25U12835F", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25R3235F, - .total_size = 4096, + .model_id = MACRONIX_MX25U12835E, + .total_size = 16384, .page_size = 256, - /* OTP: 1024B total; enter 0xB1, exit 0xC1 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + /* OTP: 512B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit 6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {1650, 3600}, + /* TODO: security register */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1650, 2000}, }, { .vendor = "Macronix", - .name = "MX25R6435F", + .name = "MX25U1635E", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25R6435F, - .total_size = 8192, + .model_id = MACRONIX_MX25U1635E, + .total_size = 2048, .page_size = 256, - /* OTP: 1024B total; enter 0xB1, exit 0xC1 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* OTP: 512B total; enter 0xB1, exit 0xC1 */ + /* QPI enable 0x35, disable 0xF5 (0xFF et al. work too) */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PR, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {1650, 3600}, + /* TODO: security register */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1650, 2000}, }, { .vendor = "Macronix", - .name = "MX25U12835F", + .name = "MX25U25635F", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25U12835E, - .total_size = 16384, + .model_id = MACRONIX_MX25U25635F, + .total_size = 32768, .page_size = 256, /* OTP: 512B total; enter 0xB1, exit 0xC1 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_4BA, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_21, }, { - .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_5C, + }, { + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, /* TODO: security register */ - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1650, 2000}, }, { .vendor = "Macronix", - .name = "MX25U1635E", + .name = "MX25U25643G", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, - .model_id = MACRONIX_MX25U1635E, - .total_size = 2048, + .model_id = MACRONIX_MX25U25635F, + .total_size = 32768, .page_size = 256, /* OTP: 512B total; enter 0xB1, exit 0xC1 */ - /* QPI enable 0x35, disable 0xF5 (0xFF et al. work too) */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, - .tested = TEST_OK_PR, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_4BA | FEATURE_CFGR | FEATURE_SCUR, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_21, }, { - .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_5C, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, /* TODO: security register */ - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1650, 2000}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {CONFIG, 3, OTP}, + .wps = {SECURITY, 7, OTP}, /* This bit is set by WPSEL command */ + }, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "Macronix", - .name = "MX25U25635F", + .name = "MX25U25645G", .bustype = BUS_SPI, .manufacture_id = MACRONIX_ID, .model_id = MACRONIX_MX25U25635F, .total_size = 32768, .page_size = 256, - /* OTP: 512B total; enter 0xB1, exit 0xC1 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_4BA, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + /* OTP: 1024B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_4BA | FEATURE_CFGR | FEATURE_SCUR, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_5C, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - /* TODO: security register */ - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ - .voltage = {1650, 2000}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ + .voltage = {1700, 2000}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {CONFIG, 3, OTP}, + .wps = {SECURITY, 7, OTP}, /* This bit is set by WPSEL command */ + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -9492,32 +11677,32 @@ const struct flashchip flashchips[] = { /* QPI enable 0x35, disable 0xF5 (0xFF et al. work too) */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, /* TODO: security register */ - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1650, 2000}, }, @@ -9532,41 +11717,41 @@ const struct flashchip flashchips[] = { /* OTP: 512B factory programmed and 512B customer programmed; enter 0xB1, exit 0xC1 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_4BA, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 2048} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_5C, }, { .eraseblocks = { {32 * 1024, 2048} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {64 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, /* TODO: security register */ - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1650, 2000}, }, @@ -9583,32 +11768,32 @@ const struct flashchip flashchips[] = { /* QPI enable 0x35, disable 0xF5 (0xFF et al. work too) */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, /* TODO: security register */ - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1650, 2000}, }, @@ -9623,32 +11808,32 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0xB1, exit 0xC1 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, /* TODO: security register */ - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1650, 2000}, }, @@ -9662,7 +11847,7 @@ const struct flashchip flashchips[] = { .page_size = 32 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -9674,14 +11859,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -9695,7 +11880,7 @@ const struct flashchip flashchips[] = { .page_size = 32 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -9707,14 +11892,14 @@ const struct flashchip flashchips[] = { {4 * 1024, 2}, {8 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -9728,7 +11913,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -9739,14 +11924,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 3}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -9760,7 +11945,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -9771,14 +11956,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -9792,7 +11977,7 @@ const struct flashchip flashchips[] = { .page_size = 0, /* unused */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -9803,14 +11988,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 3}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -9824,7 +12009,7 @@ const struct flashchip flashchips[] = { .page_size = 0, /* unused */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -9835,14 +12020,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -9856,20 +12041,20 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -9883,20 +12068,20 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {128 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -9910,7 +12095,7 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -9919,14 +12104,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 8}, {64 * 1024, 63}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -9940,20 +12125,20 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -9967,7 +12152,7 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -9976,14 +12161,14 @@ const struct flashchip flashchips[] = { {64 * 1024, 63}, {8 * 1024, 8}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -9997,7 +12182,7 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -10006,14 +12191,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 8}, {64 * 1024, 127}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -10027,20 +12212,20 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -10054,7 +12239,7 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -10063,14 +12248,14 @@ const struct flashchip flashchips[] = { {64 * 1024, 127}, {8 * 1024, 8}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -10084,20 +12269,20 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -10112,41 +12297,41 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0xB1, exit 0xC1 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 2048} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_5C, }, { .eraseblocks = { {32 * 1024, 2048} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {64 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, /* TODO: security register and SBLK/SBULK; MX25L12835F: configuration register */ - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -10161,47 +12346,125 @@ const struct flashchip flashchips[] = { /* OTP: 512B total; enter 0xB1, exit 0xC1 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32768} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 32768} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 4096} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_5C, }, { .eraseblocks = { {32 * 1024, 4096} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 2048} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 2048} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {128 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, /* TODO: security register and SBLK/SBULK, configuration register */ - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {2700, 3600}, + }, + + { + .vendor = "Macronix", + .name = "MX77L25650F", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX77L25650F, + .total_size = 32768, + .page_size = 256, + /* OTP: 512B total; enter 0xB1, exit 0xC1 */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + /* TODO: block WP, security register, configuration register */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, + { + .vendor = "Macronix", + .name = "MX77U51250F", + .bustype = BUS_SPI, + .manufacture_id = MACRONIX_ID, + .model_id = MACRONIX_MX77U51250F, + .total_size = 65536, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_CFGR | FEATURE_4BA, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ + .voltage = {1650, 2000}, + }, + /* The ST M25P05 is a bit of a problem. It has the same ID as the * ST M25P05-A in RES mode, but supports only 128 byte writes instead - * of 256 byte writes. We rely heavily on the fact that probe_spi_res1 + * of 256 byte writes. We rely heavily on the fact that PROBE_SPI_RES1 * only is successful if RDID does not work. */ { @@ -10214,22 +12477,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_res1, + .probe = PROBE_SPI_RES1, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* TODO: check */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_1, /* 128 */ - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE1, /* 128 */ + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10243,22 +12506,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* TODO: check */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10273,22 +12536,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_res1, + .probe = PROBE_SPI_RES1, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* TODO: check */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_1, /* 128 */ - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE1, /* 128 */ + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10302,22 +12565,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* TODO: check */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10331,22 +12594,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* TODO: check */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10360,22 +12623,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* TODO: check */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10389,22 +12652,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -10418,22 +12681,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_res1, + .probe = PROBE_SPI_RES1, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -10447,22 +12710,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* TODO: check */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10476,22 +12739,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* TODO: check */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10505,22 +12768,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_res1, + .probe = PROBE_SPI_RES1, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* TODO: check */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, }, { @@ -10533,22 +12796,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* TODO: check */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10562,22 +12825,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* TODO: check */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10591,25 +12854,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 2} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10623,25 +12886,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10655,25 +12918,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10687,25 +12950,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10719,25 +12982,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10752,25 +13015,25 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B; write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 4 * 1024, 512 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, /* bit5: T/B */ - .unlock = spi_disable_blockprotect_bp2_srwd, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, /* bit5: T/B */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2300, 3600}, }, @@ -10785,25 +13048,25 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B; write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PRE, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 4 * 1024, 1024 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, /* bit5: T/B */ - .unlock = spi_disable_blockprotect_bp2_srwd, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, /* bit5: T/B */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10818,25 +13081,25 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B; write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 4 * 1024, 2048 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, /* bit5: T/B */ - .unlock = spi_disable_blockprotect_bp2_srwd, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, /* bit5: T/B */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10851,25 +13114,25 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 4 * 1024, 256 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, /* bit5: T/B */ - .unlock = spi_disable_blockprotect_bp2_srwd, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, /* bit5: T/B */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -10882,22 +13145,22 @@ const struct flashchip flashchips[] = { .total_size = 128, .page_size = 256, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256, 512} }, - .block_erase = spi_block_erase_db, + .block_erase = SPI_BLOCK_ERASE_DB, }, { .eraseblocks = { {64 * 1024, 2} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, } }, - .printlock = spi_prettyprint_status_register_default_welwip, - .unlock = NULL, /* #WP pin write-protects lower 64kB. */ - .write = spi_chip_write_256, /* Page write (similar to PP but allows 0->1 changes) */ - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_DEFAULT_WELWIP, + .unlock = NO_BLOCKPROTECT_FUNC, /* #WP pin write-protects lower 64kB. */ + .write = SPI_CHIP_WRITE256, /* Page write (similar to PP but allows 0->1 changes) */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -10910,22 +13173,22 @@ const struct flashchip flashchips[] = { .total_size = 2048, .page_size = 256, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256, 8192} }, - .block_erase = spi_block_erase_db, + .block_erase = SPI_BLOCK_ERASE_DB, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, } }, - .printlock = spi_prettyprint_status_register_default_welwip, - .unlock = NULL, /* #WP pin write-protects lower 64kB. */ - .write = spi_chip_write_256, /* Page write (similar to PP but allows 0->1 changes) */ - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_DEFAULT_WELWIP, + .unlock = NO_BLOCKPROTECT_FUNC, /* #WP pin write-protects lower 64kB. */ + .write = SPI_CHIP_WRITE256, /* Page write (similar to PP but allows 0->1 changes) */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -10938,22 +13201,22 @@ const struct flashchip flashchips[] = { .total_size = 256, .page_size = 256, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256, 1024} }, - .block_erase = spi_block_erase_db, + .block_erase = SPI_BLOCK_ERASE_DB, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, } }, - .printlock = spi_prettyprint_status_register_default_welwip, - .unlock = NULL, /* #WP pin write-protects lower 64kB. */ - .write = spi_chip_write_256, /* Page write (similar to PP but allows 0->1 changes) */ - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_DEFAULT_WELWIP, + .unlock = NO_BLOCKPROTECT_FUNC, /* #WP pin write-protects lower 64kB. */ + .write = SPI_CHIP_WRITE256, /* Page write (similar to PP but allows 0->1 changes) */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -10966,22 +13229,22 @@ const struct flashchip flashchips[] = { .total_size = 512, .page_size = 256, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256, 2048} }, - .block_erase = spi_block_erase_db, + .block_erase = SPI_BLOCK_ERASE_DB, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, } }, - .printlock = spi_prettyprint_status_register_default_welwip, - .unlock = NULL, /* #WP pin write-protects lower 64kB. */ - .write = spi_chip_write_256, /* Page write supported (similar to PP but allows 0->1 changes) */ - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_DEFAULT_WELWIP, + .unlock = NO_BLOCKPROTECT_FUNC, /* #WP pin write-protects lower 64kB. */ + .write = SPI_CHIP_WRITE256, /* Page write supported (similar to PP but allows 0->1 changes) */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -10994,22 +13257,22 @@ const struct flashchip flashchips[] = { .total_size = 1024, .page_size = 256, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256, 4096} }, - .block_erase = spi_block_erase_db, + .block_erase = SPI_BLOCK_ERASE_DB, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, } }, - .printlock = spi_prettyprint_status_register_default_welwip, - .unlock = NULL, /* #WP pin write-protects lower 64kB. */ - .write = spi_chip_write_256, /* Page write (similar to PP but allows 0->1 changes) */ - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_DEFAULT_WELWIP, + .unlock = NO_BLOCKPROTECT_FUNC, /* #WP pin write-protects lower 64kB. */ + .write = SPI_CHIP_WRITE256, /* Page write (similar to PP but allows 0->1 changes) */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -11025,31 +13288,31 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32768} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 32768} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 2048} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 2048} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32768 * 1024, 4} }, - .block_erase = spi_block_erase_c4, + .block_erase = SPI_BLOCK_ERASE_C4, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1700, 2000}, }, @@ -11065,31 +13328,31 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32768} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 32768} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 2048} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 2048} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32768 * 1024, 4} }, - .block_erase = spi_block_erase_c4, + .block_erase = SPI_BLOCK_ERASE_C4, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -11105,28 +13368,28 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1700, 2000}, }, @@ -11142,26 +13405,37 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1700, 2000}, + .reg_bits = + { + /* + * There is also a volatile lock register per 64KiB sector, which is not + * mutually exclusive with BP-based protection. + */ + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -11176,26 +13450,37 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, + .reg_bits = + { + /* + * There is also a volatile lock register per 64KiB sector, which is not + * mutually exclusive with BP-based protection. + */ + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -11210,26 +13495,37 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1700, 2000}, + .reg_bits = + { + /* + * There is also a volatile lock register per 64KiB sector, which is not + * mutually exclusive with BP-based protection. + */ + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 6, RW}}, + .tb = {STATUS1, 5, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -11244,26 +13540,37 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, + .reg_bits = + { + /* + * There is also a volatile lock register per 64KiB sector, which is not + * mutually exclusive with BP-based protection. + */ + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 6, RW}}, + .tb = {STATUS1, 5, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -11278,25 +13585,25 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16384 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1700, 2000}, }, @@ -11312,25 +13619,25 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096 } }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16384 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -11346,31 +13653,31 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32768 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1700, 2000}, }, @@ -11386,31 +13693,31 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32768 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -11426,31 +13733,31 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32768 * 1024, 2} }, - .block_erase = spi_block_erase_c4, + .block_erase = SPI_BLOCK_ERASE_C4, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1700, 2000}, }, @@ -11466,31 +13773,31 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32768 * 1024, 2} }, - .block_erase = spi_block_erase_c4, + .block_erase = SPI_BLOCK_ERASE_C4, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -11506,37 +13813,37 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32768} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 32768} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 4096} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_5C, }, { .eraseblocks = { {32 * 1024, 4096} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 2048} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 2048} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {65536 * 1024, 2} }, - .block_erase = spi_block_erase_c4, + .block_erase = SPI_BLOCK_ERASE_C4, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -11552,37 +13859,37 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32768} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 32768} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 4096} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_5C, }, { .eraseblocks = { {32 * 1024, 4096} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 2048} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 2048} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {65536 * 1024, 2} }, - .block_erase = spi_block_erase_c4, + .block_erase = SPI_BLOCK_ERASE_C4, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1700, 2000}, }, @@ -11598,37 +13905,37 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 65536} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 65536} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 8192} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_5C, }, { .eraseblocks = { {32 * 1024, 8192} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 4096} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 4096} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {65536 * 1024, 4} }, - .block_erase = spi_block_erase_c4, + .block_erase = SPI_BLOCK_ERASE_C4, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -11644,37 +13951,37 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 65536} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 65536} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 8192} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_5C, }, { .eraseblocks = { {32 * 1024, 8192} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 4096} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 4096} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {65536 * 1024, 4} }, - .block_erase = spi_block_erase_c4, + .block_erase = SPI_BLOCK_ERASE_C4, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1700, 2000}, }, @@ -11690,31 +13997,31 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16384 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, { .eraseblocks = { {16384 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1700, 2000}, }, @@ -11728,33 +14035,33 @@ const struct flashchip flashchips[] = { .page_size = 256, /* supports SFDP */ /* OTP: 64B total; read 0x4B, write 0x42 */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16384 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, { .eraseblocks = { {16384 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -11770,40 +14077,40 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_5C, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32768 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, { .eraseblocks = { {32768 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -11819,40 +14126,40 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_5C, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32768 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, { .eraseblocks = { {32768 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1700, 2000}, }, @@ -11868,41 +14175,48 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 2048} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_5C, }, { .eraseblocks = { {32 * 1024, 2048} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {65536 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, { .eraseblocks = { {65536 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 6, RW}}, + .tb = {STATUS1, 5, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -11917,40 +14231,40 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 2048} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_5C, }, { .eraseblocks = { {32 * 1024, 2048} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {65536 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, { .eraseblocks = { {65536 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, } }, - .printlock = spi_prettyprint_status_register_n25q, /* TODO: config, lock, flag regs */ - .unlock = spi_disable_blockprotect_n25q, /* TODO: per 64kB sector lock registers */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, /* TODO: config, lock, flag regs */ + .unlock = SPI_DISABLE_BLOCKPROTECT_N25Q, /* TODO: per 64kB sector lock registers */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {1700, 2000}, }, @@ -11964,20 +14278,20 @@ const struct flashchip flashchips[] = { .page_size = 512, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {512, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -11991,20 +14305,20 @@ const struct flashchip flashchips[] = { .page_size = 512, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {512, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -12018,20 +14332,20 @@ const struct flashchip flashchips[] = { .page_size = 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {1024, 512} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -12045,20 +14359,20 @@ const struct flashchip flashchips[] = { .page_size = 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {1024, 512} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -12072,20 +14386,20 @@ const struct flashchip flashchips[] = { .page_size = 512, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {512, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -12099,20 +14413,20 @@ const struct flashchip flashchips[] = { .page_size = 512, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {512, 256} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -12126,20 +14440,20 @@ const struct flashchip flashchips[] = { .page_size = 512, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {512, 512} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -12153,34 +14467,34 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 2} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O read (0x3B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O read (0x3B) supported */ .voltage = {2700, 3600}, }, @@ -12194,28 +14508,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O read (0x3B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O read (0x3B) supported */ .voltage = {2700, 3600}, }, @@ -12229,34 +14543,34 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {32 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O read (0x3B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O read (0x3B) supported */ .voltage = {2700, 3600}, }, @@ -12270,34 +14584,34 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O read (0x3B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O read (0x3B) supported */ .voltage = {2700, 3600}, }, @@ -12311,31 +14625,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O read (0x3B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O read (0x3B) supported */ .voltage = {2700, 3600}, }, @@ -12349,31 +14663,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, /* FIXME: C version supports "Safe Guard" */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, /* FIXME: C version supports "Safe Guard" */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O supported */ .voltage = {2700, 3600}, /* 2.3-3.6V for Pm25LD010 */ }, @@ -12387,31 +14701,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, /* FIXME: C version supports "Safe Guard" */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, /* FIXME: C version supports "Safe Guard" */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O supported */ .voltage = {2700, 3600}, /* 2.3-3.6V for Pm25LD020 */ }, @@ -12425,31 +14739,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O supported */ .voltage = {2700, 3600}, /* 2.3-3.6V for Pm25LD040 */ }, @@ -12463,31 +14777,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 8} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {32 * 1024, 1} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {32 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O supported */ .voltage = {2700, 3600}, }, @@ -12501,31 +14815,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 16} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, /* FIXME: C version supports "Safe Guard" */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, /* FIXME: C version supports "Safe Guard" */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual I/O supported */ .voltage = {2300, 3600}, }, @@ -12540,31 +14854,31 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; read 0x4B, write 0xB1 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2300, 3600}, }, @@ -12579,31 +14893,31 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; read 0x4B, write 0xB1 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2300, 3600}, }, @@ -12618,31 +14932,31 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0xB1 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4096 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4096 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -12657,31 +14971,31 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; read 0x4B, write 0xB1 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2300, 3600}, }, @@ -12696,31 +15010,31 @@ const struct flashchip flashchips[] = { /* OTP: 64B total; read 0x4B, write 0xB1 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, /* bit6 is quad enable */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, /* bit6 is quad enable */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2300, 3600}, }, @@ -12734,25 +15048,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_res2, /* The continuation code is transferred as the 3rd byte m( */ + .probe = PROBE_SPI_RES2, /* The continuation code is transferred as the 3rd byte m( */ .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -12766,25 +15080,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -12798,31 +15112,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -12836,25 +15150,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -12868,25 +15182,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -12900,31 +15214,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -12938,25 +15252,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_res2, /* The continuation code is transferred as the 3rd byte m( */ + .probe = PROBE_SPI_RES2, /* The continuation code is transferred as the 3rd byte m( */ .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -12970,7 +15284,7 @@ const struct flashchip flashchips[] = { .page_size = 8 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_FIXME, .block_erasers = { @@ -12981,14 +15295,14 @@ const struct flashchip flashchips[] = { {96 * 1024, 1}, {128 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -13002,7 +15316,7 @@ const struct flashchip flashchips[] = { .page_size = 8 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_FIXME, .block_erasers = { @@ -13013,14 +15327,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -13034,23 +15348,23 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 2} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -13064,23 +15378,23 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -13094,23 +15408,23 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_OK_PR, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -13124,23 +15438,23 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {4 * 1024, 16} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -13154,24 +15468,24 @@ const struct flashchip flashchips[] = { .page_size = 16 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_OK_PR, - .probe = probe_jedec, - .probe_timing = TIMING_ZERO, /* routine is wrapper to probe_jedec (pm49fl00x.c) */ + .probe = PROBE_JEDEC, + .probe_timing = TIMING_ZERO, /* routine is wrapper to JEDEC (pm49fl00x.c) */ .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {16 * 1024, 16} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .unlock = unlock_regspace2_uniform_32k, - .write = write_jedec_1, - .read = read_memmapped, + .unlock = UNLOCK_REGSPACE2_UNIFORM_32K, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -13185,27 +15499,156 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .unlock = unlock_regspace2_uniform_64k, - .write = write_jedec_1, - .read = read_memmapped, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, + { + .vendor = "PUYA", + .name = "P25Q06H", + .bustype = BUS_SPI, + .manufacture_id = PUYA_ID, + .model_id = PUYA_P25Q06H, + .total_size = 64, + .page_size = 256, + /* supports SFDP */ + /* OTP: 3 x 512 bytes */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {256, 256} }, + .block_erase = SPI_BLOCK_ERASE_81, + }, { + .eraseblocks = { {4 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 2} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {64 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2300, 3600}, + }, + + { + .vendor = "PUYA", + .name = "P25Q11H", + .bustype = BUS_SPI, + .manufacture_id = PUYA_ID, + .model_id = PUYA_P25Q11H, + .total_size = 128, + .page_size = 256, + /* supports SFDP */ + /* OTP: 3 x 512 bytes */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_UNTESTED, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {256, 512} }, + .block_erase = SPI_BLOCK_ERASE_81, + }, { + .eraseblocks = { {4 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 4} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 2} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {128 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {128 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2300, 3600}, + }, + + { + .vendor = "PUYA", + .name = "P25Q21H", + .bustype = BUS_SPI, + .manufacture_id = PUYA_ID, + .model_id = PUYA_P25Q21H, + .total_size = 256, + .page_size = 256, + /* supports SFDP */ + /* OTP: 3 x 512 bytes */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {256, 1024} }, + .block_erase = SPI_BLOCK_ERASE_81, + }, { + .eraseblocks = { {4 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 8} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 4} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2300, 3600}, + }, + { .vendor = "SST", .name = "SST25LF020A", @@ -13216,25 +15659,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EWSR, .tested = TEST_OK_PREW, - .probe = probe_spi_rems, + .probe = PROBE_SPI_REMS, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, }, - .printlock = spi_prettyprint_status_register_sst25, /* FIXME: No BP2 & 3 */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_1, /* AAI supported, but opcode is 0xAF */ - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* FIXME: No BP2 & 3 */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE1, /* AAI supported, but opcode is 0xAF */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -13248,25 +15691,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EWSR, .tested = TEST_OK_PREW, - .probe = probe_spi_res2, + .probe = PROBE_SPI_RES2, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, }, - .printlock = spi_prettyprint_status_register_sst25, /* TODO: check */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_1, /* AAI supported, but opcode is 0xAF */ - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE1, /* AAI supported, but opcode is 0xAF */ + .read = SPI_CHIP_READ, .voltage = {3000, 3600}, }, @@ -13280,25 +15723,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EITHER, .tested = TEST_UNTESTED, - .probe = probe_spi_res2, + .probe = PROBE_SPI_RES2, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, }, - .printlock = spi_prettyprint_status_register_sst25, /* TODO: check */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_1, /* AAI supported, but opcode is 0xAF */ - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE1, /* AAI supported, but opcode is 0xAF */ + .read = SPI_CHIP_READ, .voltage = {3000, 3600}, }, @@ -13312,31 +15755,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EWSR, .tested = TEST_OK_PREW, - .probe = probe_spi_rems, + .probe = PROBE_SPI_REMS, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_d8, /* Supported by SST25VF010A only */ + .block_erase = SPI_BLOCK_ERASE_D8, /* Supported by SST25VF010A only */ }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, /* Supported by SST25VF010A only */ + .block_erase = SPI_BLOCK_ERASE_C7, /* Supported by SST25VF010A only */ }, }, - .printlock = spi_prettyprint_status_register_sst25, /* FIXME: No BP2 & 3 */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_1, /* AAI supported, but opcode is 0xAF */ - .read = spi_chip_read, /* Fast read (0x0B) supported by SST25VF010A only */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* FIXME: No BP2 & 3 */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE1, /* AAI supported, but opcode is 0xAF */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported by SST25VF010A only */ .voltage = {2700, 3600}, }, @@ -13350,31 +15793,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EITHER, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_sst25vf016, - .unlock = spi_disable_blockprotect, - .write = spi_aai_write, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25VF016, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_WRITE_AAI, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -13388,25 +15831,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EWSR, .tested = TEST_UNTESTED, - .probe = probe_spi_rems, + .probe = PROBE_SPI_REMS, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, }, - .printlock = spi_prettyprint_status_register_sst25, /* FIXME: No BP2 & 3 */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_1, /* AAI supported, but opcode is 0xAF */ - .read = spi_chip_read, /* only */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* FIXME: No BP2 & 3 */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE1, /* AAI supported, but opcode is 0xAF */ + .read = SPI_CHIP_READ, /* only */ .voltage = {2700, 3600}, }, @@ -13420,31 +15863,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EWSR, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_sst25, /* FIXME: No BP2 & 3 and 2nd SR */ - .unlock = spi_disable_blockprotect, /* FIXME: 2nd SR */ - .write = spi_aai_write, /* AAI supported (0xAD) */ - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* FIXME: No BP2 & 3 and 2nd SR */ + .unlock = SPI_DISABLE_BLOCKPROTECT, /* FIXME: 2nd SR */ + .write = SPI_WRITE_AAI, /* AAI supported (0xAD) */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -13458,31 +15901,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EWSR, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_sst25, /* TODO: check */ - .unlock = spi_disable_blockprotect, - .write = spi_aai_write, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_WRITE_AAI, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -13496,25 +15939,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EWSR, .tested = TEST_OK_PR, - .probe = probe_spi_rems, + .probe = PROBE_SPI_REMS, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, }, - .printlock = spi_prettyprint_status_register_sst25, /* TODO: check */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_1, /* AAI supported, but opcode is 0xAF */ - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE1, /* AAI supported, but opcode is 0xAF */ + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -13528,31 +15971,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EWSR, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_sst25vf040b, - .unlock = spi_disable_blockprotect, - .write = spi_aai_write, /* AAI supported (0xAD) */ - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25VF040B, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_WRITE_AAI, /* AAI supported (0xAD) */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -13566,31 +16009,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EWSR, .tested = TEST_OK_PREW, - .probe = probe_spi_rems, + .probe = PROBE_SPI_REMS, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_sst25vf040b, - .unlock = spi_disable_blockprotect, - .write = spi_aai_write, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25VF040B, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_WRITE_AAI, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -13604,31 +16047,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EWSR, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_sst25, /* TODO: check */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -13642,31 +16085,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EWSR, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_sst25, /* TODO: check */ - .unlock = spi_disable_blockprotect, - .write = spi_aai_write, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* TODO: check */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_WRITE_AAI, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -13680,31 +16123,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EWSR, .tested = TEST_OK_PREW, - .probe = probe_spi_rems, + .probe = PROBE_SPI_REMS, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_d8, /* Supported by SST25VF512A only */ + .block_erase = SPI_BLOCK_ERASE_D8, /* Supported by SST25VF512A only */ }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_c7, /* Supported by SST25VF512A only */ + .block_erase = SPI_BLOCK_ERASE_C7, /* Supported by SST25VF512A only */ }, }, - .printlock = spi_prettyprint_status_register_sst25, /* FIXME: No BP2 & 3 */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_1, /* AAI supported, but opcode is 0xAF */ - .read = spi_chip_read, /* Fast read (0x0B) supported by SST25VF512A only */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* FIXME: No BP2 & 3 */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE1, /* AAI supported, but opcode is 0xAF */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported by SST25VF512A only */ .voltage = {2700, 3600}, }, @@ -13718,28 +16161,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EITHER, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {1024 * 128, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 128, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_sst25, /* FIXME: does not have a BP3 */ - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_aai_write, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* FIXME: does not have a BP3 */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_WRITE_AAI, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {1650, 1950}, }, @@ -13753,31 +16196,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EITHER, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 256, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 256, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_sst25, /* FIXME: does not have a BP3 */ - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_aai_write, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* FIXME: does not have a BP3 */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_WRITE_AAI, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {1650, 1950}, }, @@ -13791,28 +16234,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_bp2_tb_bpl, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {1650, 1950}, }, @@ -13826,31 +16269,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EITHER, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 512, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 512, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_sst25, /* FIXME: does not have a BP3 */ - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_aai_write, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* FIXME: does not have a BP3 */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_WRITE_AAI, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {1650, 1950}, }, @@ -13864,28 +16307,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_bp2_tb_bpl, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual O (0x3B), dual I/O read (0xBB) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual O (0x3B), dual I/O read (0xBB) supported */ .voltage = {1650, 1950}, }, @@ -13899,31 +16342,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EITHER, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_sst25, /* *does* have a BP3 but it is useless */ - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_aai_write, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* *does* have a BP3 but it is useless */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_WRITE_AAI, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {1650, 1950}, }, @@ -13937,28 +16380,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_bp2_tb_bpl, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual O (0x3B), dual I/O read (0xBB) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual O (0x3B), dual I/O read (0xBB) supported */ .voltage = {1650, 1950}, }, @@ -13972,28 +16415,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_EITHER, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {1024 * 64, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 64, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_sst25, /* FIXME: does not have a BP3 */ - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_aai_write, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SST25, /* FIXME: does not have a BP3 */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_WRITE_AAI, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {1650, 1950}, }, @@ -14007,13 +16450,13 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {8 * 1024, 4}, @@ -14022,16 +16465,16 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {8 * 1024, 4}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect_sst26_global_unprotect, - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT_SST26_GLOBAL_UNPROTECT, + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -14045,13 +16488,13 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {8 * 1024, 4}, @@ -14060,16 +16503,16 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {8 * 1024, 4}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect_sst26_global_unprotect, - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT_SST26_GLOBAL_UNPROTECT, + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -14083,13 +16526,13 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {8 * 1024, 4}, @@ -14098,16 +16541,16 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {8 * 1024, 4}, }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect_sst26_global_unprotect, - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT_SST26_GLOBAL_UNPROTECT, + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -14121,21 +16564,21 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = 0, .tested = TEST_UNTESTED, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (sst28sf040.c) */ .block_erasers = { { .eraseblocks = { {128, 4096} }, - .block_erase = erase_sector_28sf040, + .block_erase = ERASE_SECTOR_28SF040, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_28sf040, + .block_erase = ERASE_CHIP_28SF040, } }, - .unlock = unprotect_28sf040, - .write = write_28sf040, - .read = read_memmapped, + .unlock = UNPROTECT_28SF040, + .write = WRITE_28SF040, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -14149,17 +16592,17 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_LONG_RESET, .tested = TEST_OK_PR, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec, - .read = read_memmapped, + .write = WRITE_JEDEC, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -14173,17 +16616,17 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_LONG_RESET, .tested = TEST_OK_PRE, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec, - .read = read_memmapped, + .write = WRITE_JEDEC, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -14197,17 +16640,17 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_LONG_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec, - .read = read_memmapped, + .write = WRITE_JEDEC, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14221,17 +16664,17 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_LONG_RESET, .tested = TEST_OK_PRE, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec, - .read = read_memmapped, + .write = WRITE_JEDEC, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14245,20 +16688,20 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -14272,20 +16715,20 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -14299,20 +16742,20 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -14326,20 +16769,20 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 16} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -14353,20 +16796,20 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -14380,20 +16823,20 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -14407,20 +16850,20 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -14434,23 +16877,23 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -14464,20 +16907,20 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 16} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -14491,25 +16934,25 @@ const struct flashchip flashchips[] = { .page_size = 16 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {16 * 1024, 16} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = NULL, /* AA 55 80 AA 55 10, only in A/A mux mode */ + .block_erase = NO_BLOCK_ERASE_FUNC, /* AA 55 80 AA 55 10, only in A/A mux mode */ } }, - .printlock = printlock_sst_fwhub, - .unlock = unlock_sst_fwhub, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_SST_FWHUB, + .unlock = UNLOCK_SST_FWHUB, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14523,25 +16966,25 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 96} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 6} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {384 * 1024, 1} }, - .block_erase = NULL, /* AA 55 80 AA 55 10, only in A/A mux mode */ + .block_erase = NO_BLOCK_ERASE_FUNC, /* AA 55 80 AA 55 10, only in A/A mux mode */ } }, - .printlock = printlock_sst_fwhub, - .unlock = unlock_sst_fwhub, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_SST_FWHUB, + .unlock = UNLOCK_SST_FWHUB, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14558,25 +17001,25 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = NULL, /* AA 55 80 AA 55 10, only in A/A mux mode */ + .block_erase = NO_BLOCK_ERASE_FUNC, /* AA 55 80 AA 55 10, only in A/A mux mode */ }, }, - .printlock = printlock_sst_fwhub, - .unlock = unlock_sst_fwhub, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_SST_FWHUB, + .unlock = UNLOCK_SST_FWHUB, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14590,13 +17033,13 @@ const struct flashchip flashchips[] = { .page_size = 4 * 1024, .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_UNTESTED, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (sst49lfxxxc.c) */ .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = erase_sector_49lfxxxc, + .block_erase = ERASE_SECTOR_49LFXXXC, }, { .eraseblocks = { {64 * 1024, 7}, @@ -14604,13 +17047,13 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, } }, - .printlock = printlock_regspace2_block_eraser_1, - .unlock = unlock_regspace2_block_eraser_1, - .write = write_82802ab, - .read = read_memmapped, + .printlock = PRINTLOCK_REGSPACE2_BLOCK_ERASER_1, + .unlock = UNLOCK_REGSPACE2_BLOCK_ERASER_1, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14624,25 +17067,25 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = NULL, /* AA 55 80 AA 55 10, only in A/A mux mode */ + .block_erase = NO_BLOCK_ERASE_FUNC, /* AA 55 80 AA 55 10, only in A/A mux mode */ } }, - .printlock = printlock_sst_fwhub, - .unlock = unlock_sst_fwhub, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_SST_FWHUB, + .unlock = UNLOCK_SST_FWHUB, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14656,13 +17099,13 @@ const struct flashchip flashchips[] = { .page_size = 4 * 1024, .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_UNTESTED, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (sst49lfxxxc.c) */ .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = erase_sector_49lfxxxc, + .block_erase = ERASE_SECTOR_49LFXXXC, }, { .eraseblocks = { {64 * 1024, 15}, @@ -14670,13 +17113,13 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, } }, - .printlock = printlock_regspace2_block_eraser_1, - .unlock = unlock_regspace2_block_eraser_1, - .write = write_82802ab, - .read = read_memmapped, + .printlock = PRINTLOCK_REGSPACE2_BLOCK_ERASER_1, + .unlock = UNLOCK_REGSPACE2_BLOCK_ERASER_1, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14690,13 +17133,13 @@ const struct flashchip flashchips[] = { .page_size = 4 * 1024, .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_OK_PREW, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (sst49lfxxxc.c) */ .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = erase_sector_49lfxxxc, + .block_erase = ERASE_SECTOR_49LFXXXC, }, { .eraseblocks = { {64 * 1024, 31}, @@ -14704,13 +17147,13 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, } }, - .printlock = printlock_regspace2_block_eraser_1, - .unlock = unlock_regspace2_block_eraser_1, - .write = write_82802ab, - .read = read_memmapped, + .printlock = PRINTLOCK_REGSPACE2_BLOCK_ERASER_1, + .unlock = UNLOCK_REGSPACE2_BLOCK_ERASER_1, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14724,23 +17167,23 @@ const struct flashchip flashchips[] = { .page_size = 16 * 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {16 * 1024, 16} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = NULL, + .block_erase = NO_BLOCK_ERASE_FUNC, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14754,23 +17197,23 @@ const struct flashchip flashchips[] = { .page_size = 4 * 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PRE, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {16 * 1024, 16} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = NULL, + .block_erase = NO_BLOCK_ERASE_FUNC, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14784,23 +17227,23 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150 ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = NULL, + .block_erase = NO_BLOCK_ERASE_FUNC, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14814,24 +17257,24 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_EITHER_RESET | FEATURE_REGISTERMAP, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 1, /* 150ns */ .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = NULL, + .block_erase = NO_BLOCK_ERASE_FUNC, } }, - .unlock = unlock_regspace2_uniform_64k, - .write = write_jedec_1, - .read = read_memmapped, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14845,23 +17288,23 @@ const struct flashchip flashchips[] = { .page_size = 4096, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_FIXME, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = NULL, + .block_erase = NO_BLOCK_ERASE_FUNC, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14875,13 +17318,13 @@ const struct flashchip flashchips[] = { .page_size = 4 * 1024, .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_OK_PR, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (sst49lfxxxc.c) */ .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = erase_sector_49lfxxxc, + .block_erase = ERASE_SECTOR_49LFXXXC, }, { .eraseblocks = { {64 * 1024, 31}, @@ -14889,13 +17332,13 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, } }, - .printlock = printlock_regspace2_block_eraser_1, - .unlock = unlock_regspace2_block_eraser_1, - .write = write_82802ab, - .read = read_memmapped, + .printlock = PRINTLOCK_REGSPACE2_BLOCK_ERASER_1, + .unlock = UNLOCK_REGSPACE2_BLOCK_ERASER_1, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -14909,7 +17352,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_AAA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { @@ -14920,14 +17363,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 3}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4750, 5250}, /* 4.75-5.25V for type -X, others 4.5-5.5V */ }, @@ -14941,7 +17384,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_AAA | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { @@ -14952,14 +17395,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4750, 5250}, /* 4.75-5.25V for type -X, others 4.5-5.5V */ }, @@ -14973,20 +17416,20 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* datasheet specifies no timing */ .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -15001,7 +17444,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_SHIFTED | FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, // FIXME: check datasheet. Using the 10 us from probe_m29f400bt .block_erasers = { @@ -15012,14 +17455,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 7}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -15034,7 +17477,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_SHIFTED | FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, // FIXME: check datasheet. Using the 10 us from probe_m29f400bt .block_erasers = { @@ -15045,14 +17488,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -15066,20 +17509,20 @@ const struct flashchip flashchips[] = { .page_size = 16 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {16 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -15093,20 +17536,20 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -15120,17 +17563,17 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -15144,7 +17587,7 @@ const struct flashchip flashchips[] = { .page_size = 0, .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_UNTESTED, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_FIXME, .block_erasers = { @@ -15155,15 +17598,15 @@ const struct flashchip flashchips[] = { {4 * 1024, 16}, /* sector */ {4 * 1024, 16}, /* sector */ }, - .block_erase = erase_sector_stm50, + .block_erase = STM50_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, } }, - .unlock = unlock_regspace2_uniform_64k, - .write = write_82802ab, - .read = read_memmapped, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* Also has 12V fast program & erase */ }, @@ -15177,7 +17620,7 @@ const struct flashchip flashchips[] = { .page_size = 0, .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_UNTESTED, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_FIXME, .block_erasers = { @@ -15188,15 +17631,15 @@ const struct flashchip flashchips[] = { {64 * 1024, 5}, /* block */ {4 * 1024, 16}, /* sector */ }, - .block_erase = erase_sector_stm50, + .block_erase = STM50_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, } }, - .unlock = unlock_regspace2_uniform_64k, - .write = write_82802ab, - .read = read_memmapped, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* Also has 12V fast program & erase */ }, @@ -15210,7 +17653,7 @@ const struct flashchip flashchips[] = { .page_size = 0, .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_OK_PR, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_FIXME, .block_erasers = { @@ -15221,16 +17664,16 @@ const struct flashchip flashchips[] = { {4 * 1024, 16}, /* sector */ {4 * 1024, 16}, /* sector */ }, - .block_erase = erase_sector_stm50, + .block_erase = STM50_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, } }, - .printlock = printlock_regspace2_block_eraser_0, - .unlock = unlock_regspace2_block_eraser_0, - .write = write_82802ab, - .read = read_memmapped, + .printlock = PRINTLOCK_REGSPACE2_BLOCK_ERASER_0, + .unlock = UNLOCK_REGSPACE2_BLOCK_ERASER_0, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* Also has 12V fast program & erase */ }, @@ -15244,7 +17687,7 @@ const struct flashchip flashchips[] = { .page_size = 0, .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_UNTESTED, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_FIXME, .block_erasers = { @@ -15255,16 +17698,16 @@ const struct flashchip flashchips[] = { {64 * 1024, 13}, /* block */ {4 * 1024, 16}, /* sector */ }, - .block_erase = erase_sector_stm50, + .block_erase = STM50_SECTOR_ERASE, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, } }, - .printlock = printlock_regspace2_block_eraser_0, - .unlock = unlock_regspace2_block_eraser_0, - .write = write_82802ab, - .read = read_memmapped, + .printlock = PRINTLOCK_REGSPACE2_BLOCK_ERASER_0, + .unlock = UNLOCK_REGSPACE2_BLOCK_ERASER_0, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* Also has 12V fast program & erase */ }, @@ -15278,7 +17721,7 @@ const struct flashchip flashchips[] = { .page_size = 0, .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_OK_PR, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (82802ab.c) */ .block_erasers = { @@ -15289,16 +17732,16 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = NULL, /* Only in A/A mux mode */ + .block_erase = NO_BLOCK_ERASE_FUNC, /* Only in A/A mux mode */ } }, - .printlock = printlock_regspace2_block_eraser_0, - .unlock = unlock_regspace2_block_eraser_0, - .write = write_82802ab, - .read = read_memmapped, + .printlock = PRINTLOCK_REGSPACE2_BLOCK_ERASER_0, + .unlock = UNLOCK_REGSPACE2_BLOCK_ERASER_0, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* Also has 12V fast program & erase */ }, @@ -15312,18 +17755,18 @@ const struct flashchip flashchips[] = { .page_size = 0, .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_UNTESTED, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (82802ab.c) */ .block_erasers = { { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, } }, - .unlock = unlock_regspace2_uniform_64k, - .write = write_82802ab, - .read = read_memmapped, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* Also has 12V fast program & erase */ }, @@ -15337,18 +17780,18 @@ const struct flashchip flashchips[] = { .page_size = 0, .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_OK_PR, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (82802ab.c) */ .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, } }, - .unlock = unlock_regspace2_uniform_64k, - .write = write_82802ab, - .read = read_memmapped, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* Also has 12V fast program & erase */ }, @@ -15362,18 +17805,18 @@ const struct flashchip flashchips[] = { .page_size = 0, .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_OK_PR, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (82802ab.c) */ .block_erasers = { { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, } }, - .unlock = unlock_regspace2_uniform_64k, - .write = write_82802ab, - .read = read_memmapped, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* Also has 12V fast program & erase */ }, @@ -15387,18 +17830,18 @@ const struct flashchip flashchips[] = { .page_size = 0, .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_UNTESTED, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, } }, - .unlock = unlock_regspace2_uniform_64k, - .write = write_82802ab, - .read = read_memmapped, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* Also has 12V fast program & erase */ }, @@ -15412,7 +17855,7 @@ const struct flashchip flashchips[] = { .page_size = 0, .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_UNTESTED, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { @@ -15424,13 +17867,13 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, } }, - .printlock = printlock_regspace2_block_eraser_0, - .unlock = unlock_regspace2_block_eraser_0, - .write = write_82802ab, - .read = read_memmapped, + .printlock = PRINTLOCK_REGSPACE2_BLOCK_ERASER_0, + .unlock = UNLOCK_REGSPACE2_BLOCK_ERASER_0, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* Also has 12V fast program & erase */ }, @@ -15444,20 +17887,20 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN | FEATURE_NO_ERASE | FEATURE_ERASED_ZERO, .tested = TEST_OK_PREW, - .probe = probe_spi_st95, + .probe = PROBE_SPI_ST95, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_emulation, + .block_erase = SPI_BLOCK_ERASE_EMULATION, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect_bp1_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP1_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2500, 5500}, }, @@ -15471,27 +17914,27 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_res2, + .probe = PROBE_SPI_RES2, .probe_timing = TIMING_ZERO, .block_erasers = { /* FIXME: Is this correct? { .eraseblocks = { {2 * 1024, 64} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, },*/ { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect_bp1_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP1_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2300, 3600}, }, @@ -15505,25 +17948,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_res2, + .probe = PROBE_SPI_RES2, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, - .unlock = spi_disable_blockprotect_bp1_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP1_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2300, 3600}, }, @@ -15536,31 +17979,31 @@ const struct flashchip flashchips[] = { .total_size = 256, .page_size = 256, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, /* #WP pin write-protects SRWP bit. */ - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, /* #WP pin write-protects SRWP bit. */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2300, 3600}, }, @@ -15574,25 +18017,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_res2, + .probe = PROBE_SPI_RES2, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, /* #WP pin write-protects SRWP bit. */ - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, /* #WP pin write-protects SRWP bit. */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2300, 3600}, }, @@ -15606,31 +18049,31 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B), dual read (0x3B) and dual I/O (0xBB) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B), dual read (0x3B) and dual I/O (0xBB) supported */ .voltage = {2300, 3600}, }, @@ -15644,25 +18087,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_res2, + .probe = PROBE_SPI_RES2, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {2 * 1024, 64} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {32 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp1_srwd, /* FIXME: Add ERSER error flag. */ - .unlock = spi_disable_blockprotect_bp1_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, /* FIXME: Add ERSER error flag. */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP1_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -15675,25 +18118,25 @@ const struct flashchip flashchips[] = { .total_size = 256, .page_size = 256, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256, 1024} }, - .block_erase = spi_block_erase_db, + .block_erase = SPI_BLOCK_ERASE_DB, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_default_welwip, - .unlock = NULL, /* #WP pin write-protects lower 64kB. */ - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_DEFAULT_WELWIP, + .unlock = NO_BLOCKPROTECT_FUNC, /* #WP pin write-protects lower 64kB. */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -15706,25 +18149,25 @@ const struct flashchip flashchips[] = { .total_size = 512, .page_size = 256, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256, 2 * 1024} }, - .block_erase = spi_block_erase_db, + .block_erase = SPI_BLOCK_ERASE_DB, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_default_welwip, - .unlock = NULL, /* #WP pin write-protects lower 64kB. */ - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_DEFAULT_WELWIP, + .unlock = NO_BLOCKPROTECT_FUNC, /* #WP pin write-protects lower 64kB. */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -15738,25 +18181,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_res2, + .probe = PROBE_SPI_RES2, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -15770,25 +18213,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_res2, + .probe = PROBE_SPI_RES2, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, /* #WP pin write-protects SRWP bit. */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* some quad-read supported ("HD_READ mode") */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, /* #WP pin write-protects SRWP bit. */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* some quad-read supported ("HD_READ mode") */ .voltage = {2700, 3600}, }, @@ -15802,28 +18245,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_res2, + .probe = PROBE_SPI_RES2, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, /* #WP pin write-protects SRWP bit. */ - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, /* #WP pin write-protects SRWP bit. */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -15837,25 +18280,25 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_res2, + .probe = PROBE_SPI_RES2, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {8 * 1024, 128} }, - .block_erase = spi_block_erase_d7, + .block_erase = SPI_BLOCK_ERASE_D7, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect, /* #WP pin write-protects SRWP bit. */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* some quad-read supported ("HD_READ mode") */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, /* #WP pin write-protects SRWP bit. */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* some quad-read supported ("HD_READ mode") */ .voltage = {2700, 3600}, }, @@ -15868,7 +18311,7 @@ const struct flashchip flashchips[] = { .total_size = 1024, .page_size = 64 * 1024, .tested = TEST_OK_PREW, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -15877,15 +18320,15 @@ const struct flashchip flashchips[] = { {8 * 1024, 8}, {64 * 1024, 15} }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = erase_sector_49lfxxxc, + .block_erase = ERASE_SECTOR_49LFXXXC, } }, - .unlock = unlock_lh28f008bjt, - .write = write_82802ab, - .read = read_memmapped, + .unlock = UNLOCK_LH28F008BJT, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -15899,7 +18342,7 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_EITHER_RESET | FEATURE_REGISTERMAP, .tested = TEST_UNTESTED, - .probe = probe_82802ab, + .probe = PROBE_AT82802AB, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -15908,17 +18351,17 @@ const struct flashchip flashchips[] = { {64 * 1024, 15}, {8 * 1024, 8} }, - .block_erase = erase_block_82802ab, + .block_erase = ERASE_BLOCK_82802AB, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = NULL, /* 30 D0, only in A/A mux mode */ + .block_erase = NO_BLOCK_ERASE_FUNC, /* 30 D0, only in A/A mux mode */ }, }, - .unlock = unlock_regspace2_uniform_64k, - .write = write_82802ab, - .read = read_memmapped, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_82802AB, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -15932,22 +18375,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -15961,22 +18404,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PRE, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -15990,22 +18433,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -16019,22 +18462,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -16048,22 +18491,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -16078,28 +18521,28 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 (S25FL116K only) */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 2048 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 2048 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect_bp3_srwd, /* #WP pin write-protects SRWP bit. */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and dual I/O (0x3B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, /* #WP pin write-protects SRWP bit. */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and dual I/O (0x3B) supported */ .voltage = {2700, 3600}, }, @@ -16115,25 +18558,25 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total, 32B reserved; read 0x4B; write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect_bp2_srwd, /* #WP pin write-protects SRWP bit. */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* #WP pin write-protects SRWP bit. */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -16150,7 +18593,7 @@ const struct flashchip flashchips[] = { .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, /* FIXME: we should distinguish the configuration on probing time like we do for AT45DB chips */ - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -16163,22 +18606,22 @@ const struct flashchip flashchips[] = { {4 * 1024, 32}, {64 * 1024, 254} // inaccessible }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { */ .eraseblocks = { { 64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect_bp2_srwd, /* #WP pin write-protects SRWP bit. */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* #WP pin write-protects SRWP bit. */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -16192,32 +18635,32 @@ const struct flashchip flashchips[] = { .page_size = 256, /* 4 x 256B Security Region (OTP) */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_WRSR_EXT3 | FEATURE_OTP, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16384 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16384 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, .reg_bits = { @@ -16236,7 +18679,7 @@ const struct flashchip flashchips[] = { .cmp = {STATUS2, 6, RW}, .wps = {STATUS3, 2, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -16249,28 +18692,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -16284,22 +18727,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -16315,7 +18758,7 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total, 32B reserved; read 0x4B; write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -16327,22 +18770,22 @@ const struct flashchip flashchips[] = { {4 * 1024, 32}, {64 * 1024, 254} // inaccessible }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { */ .eraseblocks = { { 64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_ep_srwd, /* TODO: SR2 and many others */ - .unlock = spi_disable_blockprotect_bp2_srwd, /* TODO: various other locks */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD, /* TODO: SR2 and many others */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* TODO: various other locks */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -16358,25 +18801,25 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total, 32B reserved; read 0x4B; write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_ep_srwd, /* TODO: SR2 and many others */ - .unlock = spi_disable_blockprotect_bp2_srwd, /* TODO: various other locks */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD, /* TODO: SR2 and many others */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* TODO: various other locks */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -16390,24 +18833,24 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_big_spansion, + .probe = PROBE_SPI_BIG_SPANSION, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {128 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 2000}, }, @@ -16421,24 +18864,24 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_big_spansion, + .probe = PROBE_SPI_BIG_SPANSION, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 2000}, }, @@ -16453,7 +18896,7 @@ const struct flashchip flashchips[] = { /* OTP: 506B total, 16B reserved; read 0x4B; write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -16465,29 +18908,29 @@ const struct flashchip flashchips[] = { {4 * 1024, 32}, {64 * 1024, 254} // inaccessible }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { */ /* FIXME: Additionally it also supports erase opcode 40h for the respective 2*4 kB pairs .eraseblocks = { {8 * 1024, 16}, {64 * 1024, 254} // inaccessible }, - .block_erase = spi_block_erase_40, + .block_erase = SPI_BLOCK_ERASE_40, }, { */ .eraseblocks = { { 64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_ep_srwd, /* TODO: Configuration register */ - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD, /* TODO: Configuration register */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -16502,25 +18945,25 @@ const struct flashchip flashchips[] = { /* OTP: 506B total, 16B reserved; read 0x4B; write 0x42 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 16384 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_ep_srwd, /* TODO: Configuration register */ - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD, /* TODO: Configuration register */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -16535,28 +18978,28 @@ const struct flashchip flashchips[] = { /* OTP: 768B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 4096 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 4096 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, /* TODO: improve */ - .unlock = spi_disable_blockprotect_bp2_srwd, /* #WP pin write-protects SRWP bit. */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* #WP pin write-protects SRWP bit. */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -16571,28 +19014,28 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 8192 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 8192 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_srwd, /* TODO: improve */ - .unlock = spi_disable_blockprotect_bp2_srwd, /* #WP pin write-protects SRWP bit. */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* #WP pin write-protects SRWP bit. */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -16606,28 +19049,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PR, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect_bp3_srwd, /* #WP pin write-protects SRWP bit. */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and dual I/O (0x3B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, /* #WP pin write-protects SRWP bit. */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and dual I/O (0x3B) supported */ .voltage = {2700, 3600}, }, @@ -16641,28 +19084,28 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect_bp3_srwd, /* #WP pin write-protects SRWP bit. */ - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) and dual I/O (0x3B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, /* #WP pin write-protects SRWP bit. */ + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) and dual I/O (0x3B) supported */ .voltage = {2700, 3600}, }, @@ -16678,40 +19121,40 @@ const struct flashchip flashchips[] = { .feature_bits = FEATURE_WRSR_WREN | FEATURE_WRSR_EXT3 | FEATURE_OTP | FEATURE_4BA_ENTER | FEATURE_4BA_NATIVE, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_53, + .block_erase = SPI_BLOCK_ERASE_53, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32768 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {32768 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp3_srwd, - .unlock = spi_disable_blockprotect_bp3_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, .reg_bits = { @@ -16729,7 +19172,7 @@ const struct flashchip flashchips[] = { .cmp = {STATUS2, 6, RW}, .wps = {STATUS3, 2, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -16742,21 +19185,21 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_big_spansion, + .probe = PROBE_SPI_BIG_SPANSION, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {256 * 1024, 64} }, - .block_erase = s25fl_block_erase, + .block_erase = S25FL_BLOCK_ERASE, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 2000}, }, @@ -16770,21 +19213,21 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_big_spansion, + .probe = PROBE_SPI_BIG_SPANSION, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = s25fl_block_erase, + .block_erase = S25FL_BLOCK_ERASE, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 2000}, }, @@ -16800,7 +19243,7 @@ const struct flashchip flashchips[] = { .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_NATIVE | FEATURE_4BA_ENTER_EAR7 | FEATURE_4BA_EAR_1716, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -16812,25 +19255,25 @@ const struct flashchip flashchips[] = { {4 * 1024, 32}, {64 * 1024, 254} // inaccessible }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { */ .eraseblocks = { { 64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { { 64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 32768 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 32768 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_ep_srwd, /* TODO: SR2 and many others */ - .unlock = spi_disable_blockprotect_bp2_srwd, /* TODO: various other locks */ - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD, /* TODO: SR2 and many others */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* TODO: various other locks */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -16846,28 +19289,28 @@ const struct flashchip flashchips[] = { .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_NATIVE | FEATURE_4BA_ENTER_EAR7 | FEATURE_4BA_EAR_1716, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { { 256 * 1024, 256} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { { 256 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { { 65536 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { { 65536 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_ep_srwd, /* TODO: SR2 and many others */ - .unlock = spi_disable_blockprotect_bp2_srwd, /* TODO: various other locks */ - .write = spi_chip_write_256, /* Multi I/O supported, IGNORE for now */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD, /* TODO: SR2 and many others */ + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, /* TODO: various other locks */ + .write = SPI_CHIP_WRITE256, /* Multi I/O supported, IGNORE for now */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -16881,24 +19324,24 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_big_spansion, + .probe = PROBE_SPI_BIG_SPANSION, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = s25fs_block_erase_d8, + .block_erase = S25FS_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 2000}, }, @@ -16912,24 +19355,24 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_big_spansion, + .probe = PROBE_SPI_BIG_SPANSION, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = s25fs_block_erase_d8, + .block_erase = S25FS_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, }, }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 2000}, }, @@ -16943,20 +19386,20 @@ const struct flashchip flashchips[] = { .page_size = 512, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {512, 256} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -16970,20 +19413,20 @@ const struct flashchip flashchips[] = { .page_size = 512, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {512, 256} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -16997,20 +19440,20 @@ const struct flashchip flashchips[] = { .page_size = 512, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {512, 512} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, }, { @@ -17023,20 +19466,20 @@ const struct flashchip flashchips[] = { .page_size = 512, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {512, 512} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, }, { @@ -17049,20 +19492,20 @@ const struct flashchip flashchips[] = { .page_size = 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {1024, 512} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -17076,20 +19519,20 @@ const struct flashchip flashchips[] = { .page_size = 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {1024, 512} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -17103,20 +19546,20 @@ const struct flashchip flashchips[] = { .page_size = 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {1024, 512} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -17130,20 +19573,20 @@ const struct flashchip flashchips[] = { .page_size = 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {1024, 512} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -17157,7 +19600,7 @@ const struct flashchip flashchips[] = { .page_size = 16384, /* Non-uniform sectors */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { @@ -17168,14 +19611,14 @@ const struct flashchip flashchips[] = { {32 * 1024, 1}, {64 * 1024, 3}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -17189,7 +19632,7 @@ const struct flashchip flashchips[] = { .page_size = 16384, /* Non-uniform sectors */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { @@ -17200,14 +19643,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -17221,22 +19664,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2048 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -17250,22 +19693,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4096 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -17279,22 +19722,22 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, /* Fast read (0x0B) supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, /* Fast read (0x0B) supported */ .voltage = {2700, 3600}, }, @@ -17310,32 +19753,32 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2 | FEATURE_WRSR2 | FEATURE_WRSR3, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, .reg_bits = { @@ -17347,7 +19790,7 @@ const struct flashchip flashchips[] = { .cmp = {STATUS2, 6, RW}, .wps = {STATUS3, 2, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -17359,32 +19802,32 @@ const struct flashchip flashchips[] = { .total_size = 16384, .page_size = 256, .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_WRSR2, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, .reg_bits = { @@ -17395,7 +19838,7 @@ const struct flashchip flashchips[] = { .sec = {STATUS1, 6, RW}, .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -17410,31 +19853,31 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_WRSR2, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 1950}, .reg_bits = { @@ -17445,7 +19888,7 @@ const struct flashchip flashchips[] = { .sec = {STATUS1, 6, RW}, .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -17458,42 +19901,94 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_WRSR2, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + .sec = {STATUS1, 6, RW}, + .cmp = {STATUS2, 6, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, + }, + + { + .vendor = "Winbond", + .name = "W25Q16JV_M", + .bustype = BUS_SPI, + .manufacture_id = WINBOND_NEX_ID, + .model_id = WINBOND_NEX_W25Q16JV_M, + .total_size = 2048, + .page_size = 256, + /* supports SFDP */ + /* OTP: 3x 256B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | + FEATURE_WRSR2 | FEATURE_WRSR3, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .eraseblocks = { {32 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_52, }, { - .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, }, { - .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, - .voltage = {1650, 1950}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, .reg_bits = { .srp = {STATUS1, 7, RW}, - .srl = {STATUS2, 0, RW}, - .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, - .tb = {STATUS1, 5, RW}, .sec = {STATUS1, 6, RW}, + .tb = {STATUS1, 5, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, .cmp = {STATUS2, 6, RW}, + .srl = {STATUS2, 0, RW}, + .wps = {STATUS3, 2, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -17506,34 +20001,44 @@ const struct flashchip flashchips[] = { .page_size = 256, /* supports SFDP */ /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR2, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + .sec = {STATUS1, 6, RW}, + .cmp = {STATUS2, 6, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -17548,31 +20053,31 @@ const struct flashchip flashchips[] = { /* QPI enable 0x38, disable 0xFF */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 1950}, /* Fast read (0x0B) and multi I/O supported */ }, @@ -17587,31 +20092,31 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 1950}, /* Fast read (0x0B) and multi I/O supported */ }, @@ -17629,40 +20134,31 @@ const struct flashchip flashchips[] = { FEATURE_4BA_EAR_C5C8 | FEATURE_4BA_READ | FEATURE_4BA_FAST_READ | FEATURE_WRSR2, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, - }, { - .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, - }, { - .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_5c, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, - }, { - .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, .reg_bits = { @@ -17672,7 +20168,7 @@ const struct flashchip flashchips[] = { .tb = {STATUS1, 6, RW}, .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -17687,37 +20183,37 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA | FEATURE_WRSR2, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, .reg_bits = { @@ -17727,7 +20223,7 @@ const struct flashchip flashchips[] = { .tb = {STATUS1, 6, RW}, .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -17742,37 +20238,37 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA | FEATURE_WRSR2, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, .reg_bits = { @@ -17782,7 +20278,7 @@ const struct flashchip flashchips[] = { .tb = {STATUS1, 6, RW}, .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -17797,37 +20293,37 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 1950}, }, @@ -17841,45 +20337,56 @@ const struct flashchip flashchips[] = { .page_size = 256, /* supports SFDP */ /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA | FEATURE_WRSR2 + | FEATURE_WRSR3, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 1950}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {STATUS1, 6, RW}, + .cmp = {STATUS2, 6, RW}, + .wps = {STATUS3, 2, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "Winbond", - .name = "W25Q32.V", + .name = "W25Q32BV/W25Q32CV/W25Q32DV", .bustype = BUS_SPI, .manufacture_id = WINBOND_NEX_ID, .model_id = WINBOND_NEX_W25Q32_V, @@ -17887,74 +20394,354 @@ const struct flashchip flashchips[] = { .page_size = 256, /* supports SFDP */ /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + .sec = {STATUS1, 6, RW}, + .cmp = {STATUS2, 6, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, + }, + + { + .vendor = "Winbond", + .name = "W25Q32FV", + .bustype = BUS_SPI, + .manufacture_id = WINBOND_NEX_ID, + .model_id = WINBOND_NEX_W25Q32_V, + .total_size = 4096, + .page_size = 256, + /* supports SFDP */ + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | + FEATURE_WRSR_EXT2 | FEATURE_WRSR2 | FEATURE_WRSR3, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + .sec = {STATUS1, 6, RW}, + .cmp = {STATUS2, 6, RW}, + .wps = {STATUS3, 2, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, + }, + + { + .vendor = "Winbond", + .name = "W25Q32JV_M", + .bustype = BUS_SPI, + .manufacture_id = WINBOND_NEX_ID, + .model_id = WINBOND_NEX_W25Q32JV_M, + .total_size = 4096, + .page_size = 256, + /* supports SFDP */ + /* OTP: 3x 256B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | + FEATURE_WRSR2 | FEATURE_WRSR3, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .sec = {STATUS1, 6, RW}, + .tb = {STATUS1, 5, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .cmp = {STATUS2, 6, RW}, + .srl = {STATUS2, 0, RW}, + .wps = {STATUS3, 2, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, + }, + + { + .vendor = "Winbond", + .name = "W25Q32JV", + .bustype = BUS_SPI, + .manufacture_id = WINBOND_NEX_ID, + .model_id = WINBOND_NEX_W25Q32_V, + .total_size = 4096, + .page_size = 256, + /* supports SFDP */ + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | + FEATURE_WRSR_EXT2 | FEATURE_WRSR2 | FEATURE_WRSR3, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + .sec = {STATUS1, 6, RW}, + .cmp = {STATUS2, 6, RW}, + .wps = {STATUS3, 2, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "Winbond", - .name = "W25Q32.W", + .name = "W25Q32BW/W25Q32CW/W25Q32DW", .bustype = BUS_SPI, .manufacture_id = WINBOND_NEX_ID, .model_id = WINBOND_NEX_W25Q32_W, .total_size = 4096, .page_size = 256, - /* OTP: 256B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ + /* OTP: 1024B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ /* QPI enable 0x38, disable 0xFF */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_WRSR_EXT2, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1700, 1950}, /* Fast read (0x0B) and multi I/O supported */ + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + .sec = {STATUS1, 6, RW}, + .cmp = {STATUS2, 6, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, + }, + + { + .vendor = "Winbond", + .name = "W25Q32FW", + .bustype = BUS_SPI, + .manufacture_id = WINBOND_NEX_ID, + .model_id = WINBOND_NEX_W25Q32_W, + .total_size = 4096, + .page_size = 256, + /* OTP: 768B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ + /* QPI enable 0x38, disable 0xFF */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | + FEATURE_WRSR_EXT2 | FEATURE_WRSR2 | FEATURE_WRSR3, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1700, 1950}, /* Fast read (0x0B) and multi I/O supported */ + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + .sec = {STATUS1, 6, RW}, + .cmp = {STATUS2, 6, RW}, + .wps = {STATUS3, 2, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, + }, + + { + .vendor = "Winbond", + .name = "W25Q32JW...Q", + .bustype = BUS_SPI, + .manufacture_id = WINBOND_NEX_ID, + .model_id = WINBOND_NEX_W25Q32_W, + .total_size = 4096, + .page_size = 256, + /* OTP: 768B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ + /* QPI enable 0x38, disable 0xFF */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | + FEATURE_WRSR_EXT2 | FEATURE_WRSR2 | FEATURE_WRSR3, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 1950}, /* Fast read (0x0B) and multi I/O supported */ + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + .sec = {STATUS1, 6, RW}, + .cmp = {STATUS2, 6, RW}, + .wps = {STATUS3, 2, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -17965,34 +20752,48 @@ const struct flashchip flashchips[] = { .model_id = WINBOND_NEX_W25Q32JW_M, .total_size = 4096, .page_size = 256, - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, + /* OTP: 768B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ + /* QPI enable 0x38, disable 0xFF */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | + FEATURE_WRSR2 | FEATURE_WRSR3 | FEATURE_WRSR_EXT2, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_tb_bpl, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 1950}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + .sec = {STATUS1, 6, RW}, + .cmp = {STATUS2, 6, RW}, + .wps = {STATUS3, 2, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -18007,31 +20808,31 @@ const struct flashchip flashchips[] = { /* OTP: 756B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, /* Multi I/O supported */ - .read = spi_chip_read, /* Fast read (0x0B) and multi I/O supported */ + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, /* Multi I/O supported */ + .read = SPI_CHIP_READ, /* Fast read (0x0B) and multi I/O supported */ .voltage = {2700, 3600}, }, @@ -18046,31 +20847,31 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 1950}, /* Fast read (0x0B) and multi I/O supported */ }, @@ -18085,31 +20886,31 @@ const struct flashchip flashchips[] = { /* OTP: 3*256B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 1950}, /* Fast read (0x0B) and multi I/O supported */ }, @@ -18123,81 +20924,92 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_21, + .block_erase = SPI_BLOCK_ERASE_21, + }, { + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + }, + + { + .vendor = "Winbond", + .name = "W25Q512NW-IM", + .bustype = BUS_SPI, + .manufacture_id = WINBOND_NEX_ID, + .model_id = WINBOND_NEX_W25Q512NW_IM, + .total_size = 64 * 1024, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA | FEATURE_WRSR2 + | FEATURE_WRSR3, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_21, }, { .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 2048} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_dc, + .block_erase = SPI_BLOCK_ERASE_DC, }, { .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {64 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {64 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, - } - }, - .printlock = spi_prettyprint_status_register_plain, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, - .voltage = {2700, 3600}, - }, - - { - .vendor = "Winbond", - .name = "W25Q512NW-IM", - .bustype = BUS_SPI, - .manufacture_id = WINBOND_NEX_ID, - .model_id = WINBOND_NEX_W25Q512NW_IM, - .total_size = 64 * 1024, - .page_size = 256, - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, - .probe_timing = TIMING_ZERO, - .block_erasers = - { - { - .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_21, - }, { - .eraseblocks = { {4 * 1024, 16384} }, - .block_erase = spi_block_erase_20, - }, { - .eraseblocks = { {32 * 1024, 2048} }, - .block_erase = spi_block_erase_52, - }, { - .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_dc, - }, { - .eraseblocks = { {64 * 1024, 1024} }, - .block_erase = spi_block_erase_d8, - }, { - .eraseblocks = { {64 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, - }, { - .eraseblocks = { {64 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, - } - }, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, - .voltage = {1650, 1950}, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, + .tb = {STATUS1, 6, RW}, + .cmp = {STATUS2, 6, RW}, + .wps = {STATUS3, 2, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -18211,32 +21023,32 @@ const struct flashchip flashchips[] = { /* supports SFDP */ /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR2, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, .reg_bits = { @@ -18247,7 +21059,7 @@ const struct flashchip flashchips[] = { .sec = {STATUS1, 6, RW}, .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -18263,31 +21075,31 @@ const struct flashchip flashchips[] = { .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2 | FEATURE_WRSR2 | FEATURE_WRSR3, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, .reg_bits = { @@ -18299,7 +21111,7 @@ const struct flashchip flashchips[] = { .cmp = {STATUS2, 6, RW}, .wps = {STATUS3, 2, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -18314,31 +21126,31 @@ const struct flashchip flashchips[] = { /* QPI enable 0x38 */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_bp2_tb_bpl, - .unlock = spi_disable_blockprotect_bp2_srwd, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -18353,32 +21165,32 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ /* QPI enable 0x38, disable 0xFF */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_WRSR2, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 1950}, /* Fast read (0x0B) and multi I/O supported */ .reg_bits = { @@ -18389,7 +21201,7 @@ const struct flashchip flashchips[] = { .sec = {STATUS1, 6, RW}, .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -18402,34 +21214,45 @@ const struct flashchip flashchips[] = { .page_size = 256, /* OTP: 256B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ /* QPI enable 0x38, disable 0xFF */ - .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_WRSR2 | FEATURE_WRSR3, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 1950}, /* Fast read (0x0B) and multi I/O supported */ + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + .sec = {STATUS1, 6, RW}, + .cmp = {STATUS2, 6, RW}, + .wps = {STATUS3, 2, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -18444,31 +21267,31 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -18483,31 +21306,31 @@ const struct flashchip flashchips[] = { /* OTP: 256B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1700, 1950}, /* Fast read (0x0B) and multi I/O supported */ }, @@ -18522,31 +21345,31 @@ const struct flashchip flashchips[] = { /* OTP: 3*256B total; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 32} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {1 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 1950}, /* Fast read (0x0B) and multi I/O supported */ }, @@ -18560,26 +21383,34 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 16} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 2} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, } }, - .printlock = spi_prettyprint_status_register_plain, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2300, 3600}, + .reg_bits = + { + /* W25X05 is single 64KiB block without any smaller WP granularity */ + /* According to datasheet W25X05 has 2 BP bits, any non-zero value protects ALL.*/ + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -18592,26 +21423,33 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 2} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}}, + .tb = {STATUS1, 5, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -18624,32 +21462,39 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 64} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 32} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {2 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -18661,27 +21506,34 @@ const struct flashchip flashchips[] = { .total_size = 256, .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, - .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREWB, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}}, + .tb = {STATUS1, 5, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -18694,32 +21546,39 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 1024} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 128} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -18732,26 +21591,33 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -18764,32 +21630,39 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, { @@ -18802,26 +21675,33 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_OK_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 256} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, }, /* W29EE011, W29EE012, W29C010M, W29C011A do not support probe_jedec according to the datasheet, but it works for newer(?) steppings. */ @@ -18835,17 +21715,17 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_LONG_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, /* used datasheet for the W29C011A */ .block_erasers = { { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec, - .read = read_memmapped, + .write = WRITE_JEDEC, + .read = READ_MEMMAPPED, }, { @@ -18858,17 +21738,17 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_LONG_RESET, .tested = TEST_OK_PREW, - .probe = probe_w29ee011, + .probe = PROBE_W29EE011, .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (w29ee011.c) */ .block_erasers = { { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec, - .read = read_memmapped, + .write = WRITE_JEDEC, + .read = READ_MEMMAPPED, }, { @@ -18881,17 +21761,17 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_LONG_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec, - .read = read_memmapped, + .write = WRITE_JEDEC, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -18905,17 +21785,17 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_LONG_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec, - .read = read_memmapped, + .write = WRITE_JEDEC, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -18929,17 +21809,17 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_LONG_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {64 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec, - .read = read_memmapped, + .write = WRITE_JEDEC, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -18953,7 +21833,7 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -18962,14 +21842,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 8}, {64 * 1024, 63}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -18983,20 +21863,20 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 64} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -19010,7 +21890,7 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -19019,14 +21899,14 @@ const struct flashchip flashchips[] = { {64 * 1024, 63}, {8 * 1024, 8}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {4 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -19040,7 +21920,7 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -19049,14 +21929,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 8}, {64 * 1024, 127}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -19070,20 +21950,20 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -19097,7 +21977,7 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { @@ -19106,14 +21986,14 @@ const struct flashchip flashchips[] = { {64 * 1024, 127}, {8 * 1024, 8}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -19127,20 +22007,20 @@ const struct flashchip flashchips[] = { .page_size = 128 * 1024, /* actual page size is 16 */ .feature_bits = FEATURE_ADDR_2AA | FEATURE_SHORT_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec_29gl, + .probe = PROBE_JEDEC_29GL, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {128 * 1024, 128} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, }, }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {2700, 3600}, }, @@ -19154,21 +22034,21 @@ const struct flashchip flashchips[] = { .page_size = 4 * 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .printlock = printlock_w39f010, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_W39F010, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -19182,21 +22062,21 @@ const struct flashchip flashchips[] = { .page_size = 4 * 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {4 * 1024, 32} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {128 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .printlock = printlock_w39l010, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_W39L010, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -19210,24 +22090,24 @@ const struct flashchip flashchips[] = { .page_size = 4 * 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .printlock = printlock_w39l020, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_W39L020, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -19241,24 +22121,24 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PR, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .printlock = printlock_w39l040, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_W39L040, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -19272,21 +22152,21 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .printlock = printlock_w39v040a, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_W39V040A, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -19300,21 +22180,21 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .printlock = printlock_w39v040b, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_W39V040B, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -19328,21 +22208,21 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .printlock = printlock_w39v040c, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_W39V040C, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -19356,25 +22236,25 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = erase_block_jedec, + .block_erase = JEDEC_BLOCK_ERASE, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .printlock = printlock_w39v040fa, - .unlock = unlock_regspace2_uniform_64k, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_W39V040FA, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -19388,22 +22268,22 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .printlock = printlock_w39v040fb, - .unlock = unlock_regspace2_uniform_64k, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_W39V040FB, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* Also has 12V fast program */ }, @@ -19417,21 +22297,21 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .printlock = printlock_w39v040fc, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_W39V040FC, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* Also has 12V fast program */ }, @@ -19445,21 +22325,21 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .printlock = printlock_w39v080a, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_W39V080A, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -19473,22 +22353,22 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {64 * 1024, 16} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {1024 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .printlock = printlock_w39v080fa, - .unlock = unlock_regspace2_uniform_64k, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_W39V080FA, + .unlock = UNLOCK_REGSPACE2_UNIFORM_64K, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* Also has 12V fast program */ }, @@ -19502,21 +22382,21 @@ const struct flashchip flashchips[] = { .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .printlock = printlock_w39v080fa_dual, - .write = write_jedec_1, - .read = read_memmapped, + .printlock = PRINTLOCK_W39V080FA_DUAL, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, /* Also has 12V fast program */ }, @@ -19530,7 +22410,7 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { @@ -19541,14 +22421,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -19562,17 +22442,17 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PROBE, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {4500, 5500}, }, @@ -19586,7 +22466,7 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, + .probe = PROBE_JEDEC, .probe_timing = 10, .block_erasers = { @@ -19597,14 +22477,14 @@ const struct flashchip flashchips[] = { {8 * 1024, 2}, {16 * 1024, 1}, }, - .block_erase = erase_sector_jedec, + .block_erase = JEDEC_SECTOR_ERASE, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, } }, - .write = write_jedec_1, - .read = read_memmapped, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, .voltage = {3000, 3600}, }, @@ -19618,63 +22498,291 @@ const struct flashchip flashchips[] = { .page_size = 128, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_OK_PREW, - .probe = probe_jedec, - .probe_timing = 10, + .probe = PROBE_JEDEC, + .probe_timing = 10, + .block_erasers = + { + { + .eraseblocks = { + {64 * 1024, 3}, + {32 * 1024, 1}, + {8 * 1024, 2}, + {16 * 1024, 1}, + }, + .block_erase = JEDEC_SECTOR_ERASE, + }, { + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = JEDEC_CHIP_BLOCK_ERASE, + } + }, + .write = WRITE_JEDEC1, + .read = READ_MEMMAPPED, + .voltage = {3000, 3600}, + }, + + { + .vendor = "XMC", + .name = "XM25QH80B", + .bustype = BUS_SPI, + .manufacture_id = ST_ID, + .model_id = ST_M45PE80, + .total_size = 1024, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {1 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {1 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + }, + + { + .vendor = "XMC", + .name = "XM25QU80B", + .bustype = BUS_SPI, + .manufacture_id = ST_ID, + .model_id = XMC_XM25QU80B, + .total_size = 1024, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 256 } }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 16} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {1 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {1 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, + }, + + { + .vendor = "XMC", + .name = "XM25QH16C/XM25QH16D", + .bustype = BUS_SPI, + .manufacture_id = ST_ID, + .model_id = XMC_XM25QH16C, + .total_size = 2048, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + }, + + { + .vendor = "XMC", + .name = "XM25QU16C", + .bustype = BUS_SPI, + .manufacture_id = ST_ID, + .model_id = XMC_XM25QU16C, + .total_size = 2048, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 32} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {2 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, + }, + + { + .vendor = "XMC", + .name = "XM25QH32C/XM25QH32D", + .bustype = BUS_SPI, + .manufacture_id = ST_ID, + .model_id = XMC_XM25QH32C, + .total_size = 4096, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + }, + + { + .vendor = "XMC", + .name = "XM25QU32C", + .bustype = BUS_SPI, + .manufacture_id = ST_ID, + .model_id = XMC_XM25QU32C, + .total_size = 4096, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, .block_erasers = { { - .eraseblocks = { - {64 * 1024, 3}, - {32 * 1024, 1}, - {8 * 1024, 2}, - {16 * 1024, 1}, - }, - .block_erase = erase_sector_jedec, + .eraseblocks = { {4 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_20, }, { - .eraseblocks = { {256 * 1024, 1} }, - .block_erase = erase_chip_block_jedec, + .eraseblocks = { {32 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {4 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .write = write_jedec_1, - .read = read_memmapped, - .voltage = {3000, 3600}, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, }, { .vendor = "XMC", - .name = "XM25QH64C", + .name = "XM25QH64C/XM25QH64D", .bustype = BUS_SPI, .manufacture_id = ST_ID, .model_id = XMC_XM25QH64C, .total_size = 8192, .page_size = 256, .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -19688,69 +22796,117 @@ const struct flashchip flashchips[] = { .page_size = 256, .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 2048} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 256} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 128} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {8 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 1950}, }, { .vendor = "XMC", - .name = "XM25QH128C", + .name = "XM25QH128A", + .bustype = BUS_SPI, + .manufacture_id = ST_ID, + .model_id = XMC_XM25QH128A, + .total_size = 16384, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_WRSR2, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + .reg_bits = + { + .srp = {STATUS1, 7, RW}, + .srl = {STATUS2, 0, RW}, + .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}}, + .tb = {STATUS1, 5, RW}, + .sec = {STATUS1, 6, RW}, + .cmp = {STATUS2, 6, RW}, + }, + .decode_range = DECODE_RANGE_SPI25, + }, + + { + .vendor = "XMC", + .name = "XM25QH128C/XM25QH128D", .bustype = BUS_SPI, .manufacture_id = ST_ID, .model_id = XMC_XM25QH128C, .total_size = 16384, .page_size = 256, .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI | FEATURE_WRSR2, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, .reg_bits = { @@ -19761,12 +22917,12 @@ const struct flashchip flashchips[] = { .sec = {STATUS1, 6, RW}, .cmp = {STATUS2, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "XMC", - .name = "XM25QU128C", + .name = "XM25QU128C/XM25QU128D", .bustype = BUS_SPI, .manufacture_id = ST_ID, .model_id = XMC_XM25QU128C, @@ -19775,38 +22931,38 @@ const struct flashchip flashchips[] = { /* supports SFDP */ /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 1950}, }, { .vendor = "XMC", - .name = "XM25QH256C", + .name = "XM25QH256C/XM25QH256D", .bustype = BUS_SPI, .manufacture_id = ST_ID, .model_id = XMC_XM25QH256C, @@ -19816,33 +22972,33 @@ const struct flashchip flashchips[] = { /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_ENTER_WREN | FEATURE_4BA_EAR_C5C8 | FEATURE_4BA_READ | FEATURE_4BA_FAST_READ | - FEATURE_WRSR2, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + FEATURE_4BA_WRITE | FEATURE_WRSR2, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, .reg_bits = { @@ -19851,12 +23007,12 @@ const struct flashchip flashchips[] = { .bp = {{STATUS1, 2, RW}, {STATUS1, 3, RW}, {STATUS1, 4, RW}, {STATUS1, 5, RW}}, .tb = {STATUS1, 6, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }, { .vendor = "XMC", - .name = "XM25QU256C", + .name = "XM25QU256C/XM25QU256D", .bustype = BUS_SPI, .manufacture_id = ST_ID, .model_id = XMC_XM25QU256C, @@ -19865,71 +23021,325 @@ const struct flashchip flashchips[] = { /* supports SFDP */ /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_ENTER_WREN - | FEATURE_4BA_EAR_C5C8 | FEATURE_4BA_READ | FEATURE_4BA_FAST_READ, - .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + | FEATURE_4BA_EAR_C5C8 | FEATURE_4BA_READ | FEATURE_4BA_FAST_READ + | FEATURE_4BA_WRITE, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 8192} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {32 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, + }, + + { + .vendor = "XMC", + .name = "XM25RU256C", + .bustype = BUS_SPI, + .manufacture_id = ST_ID, + .model_id = XMC_XM25RU256C, + .total_size = 32768, + .page_size = 256, + /* supports SFDP */ + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_ENTER_WREN | + FEATURE_4BA_EAR_C5C8 | FEATURE_4BA_READ | FEATURE_4BA_FAST_READ | + FEATURE_4BA_WRITE, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 8192} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 1024} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 512} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {32 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, + }, + + { + .vendor = "XMC", + .name = "XM25QH512C/XM25QH512D", + .bustype = BUS_SPI, + .manufacture_id = ST_ID, + .model_id = XMC_XM25QH512C, + .total_size = 64 * 1024, + .page_size = 256, + /* supports SFDP */ + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ + /* FOUR_BYTE_ADDR: supports 4-bytes addressing mode */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_ENTER_WREN + | FEATURE_4BA_EAR_C5C8 | FEATURE_4BA_READ | FEATURE_4BA_FAST_READ, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_21, + }, { + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + }, + + { + .vendor = "XMC", + .name = "XM25QU512C/XM25QU512D", + .bustype = BUS_SPI, + .manufacture_id = ST_ID, + .model_id = XMC_XM25QU512C, + .total_size = 64 * 1024, + .page_size = 256, + /* supports SFDP */ + /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42, erase 0x44, read ID 0x4B */ + /* FOUR_BYTE_ADDR: supports 4-bytes addressing mode */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_4BA_ENTER_WREN + | FEATURE_4BA_EAR_C5C8 | FEATURE_4BA_READ | FEATURE_4BA_FAST_READ, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_21, + }, { + .eraseblocks = { {4 * 1024, 16384} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_DC, + }, { + .eraseblocks = { {64 * 1024, 1024} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {64 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {1650, 1950}, }, + { + .vendor = "XTX Technology Limited", + .name = "XT25F02E", + .bustype = BUS_SPI, + .manufacture_id = XTX_ID, + .model_id = XTX_XT25F02E, + .total_size = 256, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 64} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {64 * 1024, 4} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {256 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP1_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + }, + + { + .vendor = "XTX Technology Limited", + .name = "XT25F64B", + .bustype = BUS_SPI, + .manufacture_id = XTX_ID, + .model_id = XTX_XT25F64B, + .total_size = 8 * 1024, + .page_size = 256, + /* Supports SFDP */ + /* OTP: 4 x 256 bytes */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 2048} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 128} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {8 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + }, + + { + .vendor = "XTX Technology Limited", + .name = "XT25F128B", + .bustype = BUS_SPI, + .manufacture_id = XTX_ID, + .model_id = XTX_XT25F128B, + .total_size = 16 * 1024, + .page_size = 256, + /* Supports SFDP */ + /* OTP: 4 x 256 bytes */ + .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_QPI, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_RDID, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + .unlock = SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {2700, 3600}, + }, + { .vendor = "Zetta Device", .name = "ZD25D20", .bustype = BUS_SPI, - .manufacture_id = ZETTADEVICE_ID, - .model_id = ZETTADEVICE_ZD25D20, + .manufacture_id = ZETTA_ID, + .model_id = ZETTA_ZD25D20, .total_size = 256, .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 8} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 4} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {256 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, @@ -19937,40 +23347,78 @@ const struct flashchip flashchips[] = { .vendor = "Zetta Device", .name = "ZD25D40", .bustype = BUS_SPI, - .manufacture_id = ZETTADEVICE_ID, - .model_id = ZETTADEVICE_ZD25D40, + .manufacture_id = ZETTA_ID, + .model_id = ZETTA_ZD25D40, .total_size = 512, .page_size = 256, .feature_bits = FEATURE_WRSR_WREN, .tested = TEST_UNTESTED, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 16} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 8} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {512 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, - .printlock = spi_prettyprint_status_register_plain, /* TODO: improve */ - .unlock = spi_disable_blockprotect, - .write = spi_chip_write_256, - .read = spi_chip_read, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, .voltage = {2700, 3600}, }, + { + .vendor = "Zetta Device", + .name = "ZD25LQ128", + .bustype = BUS_SPI, + .manufacture_id = ZETTA_ID, + .model_id = ZETTA_ZD25LQ128_REMS, + .total_size = 16384, + .page_size = 256, + .feature_bits = FEATURE_WRSR_WREN, + .tested = TEST_OK_PREW, + .probe = PROBE_SPI_REMS, + .probe_timing = TIMING_ZERO, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = SPI_BLOCK_ERASE_20, + }, { + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = SPI_BLOCK_ERASE_52, + }, { + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = SPI_BLOCK_ERASE_D8, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_60, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = SPI_BLOCK_ERASE_C7, + } + }, + .printlock = SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, /* TODO: improve */ + .unlock = SPI_DISABLE_BLOCKPROTECT, + .write = SPI_CHIP_WRITE256, + .read = SPI_CHIP_READ, + .voltage = {1650, 1950}, + }, + { .vendor = "Unknown", .name = "SFDP-capable chip", @@ -19984,11 +23432,11 @@ const struct flashchip flashchips[] = { /* want the default "This flash part has status UNTESTED..." */ /* text to be printed. */ .tested = TEST_OK_PREW, - .probe = probe_spi_sfdp, + .probe = PROBE_SPI_SFDP, .block_erasers = {}, /* set by probing function */ - .unlock = spi_disable_blockprotect, /* is this safe? */ - .write = NULL, /* set by probing function */ - .read = spi_chip_read, + .unlock = SPI_DISABLE_BLOCKPROTECT, /* is this safe? */ + .write = 0, /* set by probing function */ + .read = SPI_CHIP_READ, /* FIXME: some vendor extensions define this */ .voltage = {0}, }, @@ -20003,16 +23451,16 @@ const struct flashchip flashchips[] = { .page_size = 256, /* probe is assumed to work, rest will be filled in by probe */ .tested = TEST_OK_PROBE, - .probe = probe_opaque, + .probe = PROBE_OPAQUE, /* eraseblock sizes will be set by the probing function */ .block_erasers = { { - .block_erase = erase_opaque, + .block_erase = OPAQUE_ERASE, } }, - .write = write_opaque, - .read = read_opaque, + .write = WRITE_OPAQUE, + .read = READ_OPAQUE, }, { @@ -20024,10 +23472,10 @@ const struct flashchip flashchips[] = { .total_size = 0, .page_size = 256, .tested = TEST_BAD_PREW, - .probe = probe_spi_rdid4, + .probe = PROBE_SPI_RDID4, .probe_timing = TIMING_ZERO, - .write = NULL, - .read = NULL, + .write = 0, + .read = 0, }, { @@ -20039,10 +23487,10 @@ const struct flashchip flashchips[] = { .total_size = 0, .page_size = 256, .tested = TEST_BAD_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, - .write = NULL, - .read = NULL, + .write = 0, + .read = 0, }, { @@ -20054,10 +23502,10 @@ const struct flashchip flashchips[] = { .total_size = 0, .page_size = 256, .tested = TEST_BAD_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, - .write = NULL, - .read = NULL, + .write = 0, + .read = 0, }, { @@ -20069,10 +23517,10 @@ const struct flashchip flashchips[] = { .total_size = 0, .page_size = 256, .tested = TEST_BAD_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, - .write = NULL, - .read = NULL, + .write = 0, + .read = 0, }, { @@ -20084,10 +23532,10 @@ const struct flashchip flashchips[] = { .total_size = 0, .page_size = 256, .tested = TEST_BAD_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, - .write = NULL, - .read = NULL, + .write = 0, + .read = 0, }, { @@ -20099,10 +23547,10 @@ const struct flashchip flashchips[] = { .total_size = 0, .page_size = 256, .tested = TEST_BAD_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, - .write = NULL, - .read = NULL, + .write = 0, + .read = 0, }, { @@ -20114,10 +23562,10 @@ const struct flashchip flashchips[] = { .total_size = 0, .page_size = 256, .tested = TEST_BAD_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, - .write = NULL, - .read = NULL, + .write = 0, + .read = 0, }, { @@ -20129,10 +23577,10 @@ const struct flashchip flashchips[] = { .total_size = 0, .page_size = 256, .tested = TEST_BAD_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, - .write = NULL, - .read = NULL, + .write = 0, + .read = 0, }, { @@ -20144,10 +23592,10 @@ const struct flashchip flashchips[] = { .total_size = 0, .page_size = 256, .tested = TEST_BAD_PREW, - .probe = probe_spi_rdid, + .probe = PROBE_SPI_RDID, .probe_timing = TIMING_ZERO, - .write = NULL, - .read = NULL, + .write = 0, + .read = 0, }, { @@ -20159,8 +23607,8 @@ const struct flashchip flashchips[] = { .total_size = 0, .page_size = 256, .tested = TEST_BAD_PREW, - .probe = probe_spi_rdid, - .write = NULL, + .probe = PROBE_SPI_RDID, + .write = 0, }, { @@ -20172,8 +23620,8 @@ const struct flashchip flashchips[] = { .total_size = 0, .page_size = 256, .tested = TEST_BAD_PREW, - .probe = probe_spi_rems, - .write = NULL, + .probe = PROBE_SPI_REMS, + .write = 0, }, {0} diff --git a/flashrom.c b/flashrom.c index 36a04345c..fc52046c0 100644 --- a/flashrom.c +++ b/flashrom.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -33,9 +34,9 @@ #include "programmer.h" #include "hwaccess_physmap.h" #include "chipdrivers.h" +#include "erasure_layout.h" const char flashrom_version[] = FLASHROM_VERSION; -const char *chip_to_probe = NULL; static const struct programmer_entry *programmer = NULL; @@ -46,7 +47,7 @@ static const struct programmer_entry *programmer = NULL; struct decode_sizes max_rom_decode; /* If nonzero, used as the start address of bottom-aligned flash. */ -unsigned long flashbase; +uintptr_t flashbase; /* Is writing allowed with this programmer? */ bool programmer_may_write; @@ -63,11 +64,15 @@ static struct shutdown_func_data { */ static bool may_register_shutdown = false; -/* Did we change something or was every erase/write skipped (if any)? */ -static bool all_skipped = true; - -struct programmer_cfg { - char *params; +static struct bus_type_info { + enum chipbustype type; + const char *name; +} bustypes[] = { + { BUS_PARALLEL, "Parallel, " }, + { BUS_LPC, "LPC, " }, + { BUS_FWH, "FWH, " }, + { BUS_SPI, "SPI, " }, + { BUS_PROG, "Programmer-specific, " }, }; /* Register a function to be executed on programmer shutdown. @@ -98,7 +103,7 @@ int register_shutdown(int (*function) (void *data), void *data) } int register_chip_restore(chip_restore_fn_cb_t func, - struct flashctx *flash, uint8_t status) + struct flashctx *flash, void *data) { if (flash->chip_restore_fn_count >= MAX_CHIP_RESTORE_FUNCTIONS) { msg_perr("Tried to register more than %i chip restore" @@ -106,7 +111,7 @@ int register_chip_restore(chip_restore_fn_cb_t func, return 1; } flash->chip_restore_fn[flash->chip_restore_fn_count].func = func; - flash->chip_restore_fn[flash->chip_restore_fn_count].status = status; + flash->chip_restore_fn[flash->chip_restore_fn_count].data = data; flash->chip_restore_fn_count++; return 0; @@ -119,7 +124,7 @@ static int deregister_chip_restore(struct flashctx *flash) while (flash->chip_restore_fn_count > 0) { int i = --flash->chip_restore_fn_count; rc |= flash->chip_restore_fn[i].func( - flash, flash->chip_restore_fn[i].status); + flash, flash->chip_restore_fn[i].data); } return rc; @@ -155,14 +160,14 @@ int programmer_init(const struct programmer_entry *prog, const char *param) cfg.params = strdup(param); if (!cfg.params) { msg_perr("Out of memory!\n"); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } } else { cfg.params = NULL; } - msg_pdbg("Initializing %s programmer\n", programmer->name); - ret = programmer->init(&cfg); + msg_pdbg("Initializing %s programmer\n", prog->name); + ret = prog->init(&cfg); if (cfg.params && strlen(cfg.params)) { if (ret != 0) { /* It is quite possible that any unhandled programmer parameter would have been valid, @@ -176,7 +181,7 @@ int programmer_init(const struct programmer_entry *prog, const char *param) */ msg_perr("Unhandled programmer parameters: %s\n", cfg.params); msg_perr("Aborting.\n"); - ret = ERROR_FATAL; + ret = ERROR_FLASHROM_FATAL; } } free(cfg.params); @@ -216,11 +221,15 @@ void *master_map_flash_region(const struct registered_master *mst, else if (mst->buses_supported & BUS_NONSPI) map_flash_region = mst->par.map_flash_region; - void *ret; + /* A result of NULL causes mapped addresses to be chip physical + * addresses, assuming only a single region is mapped (the entire flash + * space). Chips with a second region (like a register map) require a + * real memory mapping to distinguish the different ranges. Those chips + * are FWH/LPC, so the bus master provides a real mapping. + */ + void *ret = NULL; if (map_flash_region) ret = map_flash_region(descr, phys_addr, len); - else - ret = fallback_map(descr, phys_addr, len); msg_gspew("%s: mapping %s from 0x%0*" PRIxPTR " to 0x%0*" PRIxPTR "\n", __func__, descr, PRIxPTR_WIDTH, phys_addr, PRIxPTR_WIDTH, (uintptr_t) ret); return ret; @@ -237,8 +246,6 @@ void master_unmap_flash_region(const struct registered_master *mst, if (unmap_flash_region) unmap_flash_region(virt_addr, len); - else - fallback_unmap(virt_addr, len); msg_gspew("%s: unmapped 0x%0*" PRIxPTR "\n", __func__, PRIxPTR_WIDTH, (uintptr_t)virt_addr); } @@ -253,14 +260,38 @@ static bool master_uses_physmap(const struct registered_master *mst) return false; } -void programmer_delay(unsigned int usecs) +void programmer_delay(const struct flashctx *flash, unsigned int usecs) { - if (usecs > 0) { - if (programmer->delay) - programmer->delay(usecs); - else - internal_delay(usecs); + if (usecs == 0) + return; + + /** + * Drivers should either use default_delay() directly or their + * own custom delay. Only core flashrom logic calls programmer_delay() + * which should always have a valid flash context. A NULL context + * more than likely indicates a layering violation or BUG however + * for now dispatch a default_delay() as a safe default for the NULL + * base case. + */ + if (!flash) { + msg_perr("%s called with NULL flash context. " + "Please report a bug at flashrom@flashrom.org\n", + __func__); + return default_delay(usecs); + } + + if (flash->mst->buses_supported & BUS_SPI) { + if (flash->mst->spi.delay) + return flash->mst->spi.delay(flash, usecs); + } else if (flash->mst->buses_supported & BUS_PARALLEL) { + if (flash->mst->par.delay) + return flash->mst->par.delay(flash, usecs); + } else if (flash->mst->buses_supported & BUS_PROG) { + if (flash->mst->opaque.delay) + return flash->mst->opaque.delay(flash, usecs); } + + return default_delay(usecs); } int read_memmapped(struct flashctx *flash, uint8_t *buf, unsigned int start, @@ -318,7 +349,7 @@ static char *extract_param(char *const *haystack, const char *needle, const char opt = malloc(optlen + 1); if (!opt) { msg_gerr("Out of memory!\n"); - exit(1); + return NULL; } strncpy(opt, opt_pos, optlen); opt[optlen] = '\0'; @@ -337,33 +368,138 @@ char *extract_programmer_param_str(const struct programmer_cfg *cfg, const char return extract_param(&cfg->params, param_name, ","); } -static int check_block_eraser(const struct flashctx *flash, int k, int log) +void get_flash_region(const struct flashctx *flash, int addr, struct flash_region *region) +{ + if ((flash->mst->buses_supported & BUS_PROG) && flash->mst->opaque.get_region) { + flash->mst->opaque.get_region(flash, addr, region); + } else if (flash->mst->buses_supported & BUS_SPI && flash->mst->spi.get_region) { + flash->mst->spi.get_region(flash, addr, region); + } else { + region->name = strdup(""); + region->start = 0; + region->end = flashrom_flash_getsize(flash) - 1; + region->read_prot = false; + region->write_prot = false; + } +} + +int check_for_unwritable_regions(const struct flashctx *flash, unsigned int start, unsigned int len) +{ + struct flash_region region; + for (unsigned int addr = start; addr < start + len; addr = region.end + 1) { + get_flash_region(flash, addr, ®ion); + + if (region.write_prot) { + msg_gerr("%s: cannot write/erase inside %s region (%#08"PRIx32"..%#08"PRIx32").\n", + __func__, region.name, region.start, region.end); + free(region.name); + return -1; + } + free(region.name); + } + return 0; +} + +#ifdef FLASHROM_TEST +/* special unit-test hooks */ +erasefunc_t *g_test_erase_injector[NUM_TEST_ERASE_INJECTORS]; +#endif + +erasefunc_t *lookup_erase_func_ptr(const struct block_eraser *const eraser) +{ + switch (eraser->block_erase) { + case SPI_BLOCK_ERASE_EMULATION: return &spi_block_erase_emulation; + case SPI_BLOCK_ERASE_20: return &spi_block_erase_20; + case SPI_BLOCK_ERASE_21: return &spi_block_erase_21; + case SPI_BLOCK_ERASE_40: return NULL; // FIXME unhandled &spi_block_erase_40; + case SPI_BLOCK_ERASE_50: return &spi_block_erase_50; + case SPI_BLOCK_ERASE_52: return &spi_block_erase_52; + case SPI_BLOCK_ERASE_53: return &spi_block_erase_53; + case SPI_BLOCK_ERASE_5C: return &spi_block_erase_5c; + case SPI_BLOCK_ERASE_60: return &spi_block_erase_60; + case SPI_BLOCK_ERASE_62: return &spi_block_erase_62; + case SPI_BLOCK_ERASE_81: return &spi_block_erase_81; + case SPI_BLOCK_ERASE_C4: return &spi_block_erase_c4; + case SPI_BLOCK_ERASE_C7: return &spi_block_erase_c7; + case SPI_BLOCK_ERASE_D7: return &spi_block_erase_d7; + case SPI_BLOCK_ERASE_D8: return &spi_block_erase_d8; + case SPI_BLOCK_ERASE_DB: return &spi_block_erase_db; + case SPI_BLOCK_ERASE_DC: return &spi_block_erase_dc; + case S25FL_BLOCK_ERASE: return &s25fl_block_erase; + case S25FS_BLOCK_ERASE_D8: return &s25fs_block_erase_d8; + case JEDEC_SECTOR_ERASE: return &erase_sector_jedec; // TODO rename to &jedec_sector_erase; + case JEDEC_BLOCK_ERASE: return &erase_block_jedec; // TODO rename to &jedec_block_erase; + case JEDEC_CHIP_BLOCK_ERASE: return &erase_chip_block_jedec; // TODO rename to &jedec_chip_block_erase; + case OPAQUE_ERASE: return &erase_opaque; // TODO rename to &opqaue_erase; + case SPI_ERASE_AT45CS_SECTOR: return &spi_erase_at45cs_sector; + case SPI_ERASE_AT45DB_BLOCK: return &spi_erase_at45db_block; + case SPI_ERASE_AT45DB_CHIP: return &spi_erase_at45db_chip; + case SPI_ERASE_AT45DB_PAGE: return &spi_erase_at45db_page; + case SPI_ERASE_AT45DB_SECTOR: return &spi_erase_at45db_sector; + case ERASE_CHIP_28SF040: return &erase_chip_28sf040; + case ERASE_SECTOR_28SF040: return &erase_sector_28sf040; + case ERASE_BLOCK_82802AB: return &erase_block_82802ab; + case ERASE_SECTOR_49LFXXXC: return &erase_sector_49lfxxxc; + case STM50_SECTOR_ERASE: return &erase_sector_stm50; // TODO rename to &stm50_sector_erase; + case EDI_CHIP_BLOCK_ERASE: return &edi_chip_block_erase; +#ifdef FLASHROM_TEST + case TEST_ERASE_INJECTOR_1: + case TEST_ERASE_INJECTOR_2: + case TEST_ERASE_INJECTOR_3: + case TEST_ERASE_INJECTOR_4: + case TEST_ERASE_INJECTOR_5: + return g_test_erase_injector[eraser->block_erase - TEST_ERASE_INJECTOR_1]; +#endif + /* default: total function, 0 indicates no erase function set. + * We explicitly do not want a default catch-all case in the switch + * to ensure unhandled enum's are compiler warnings. + */ + case NO_BLOCK_ERASE_FUNC: return NULL; + }; + + return NULL; +} + +int check_block_eraser(const struct flashctx *flash, int k, int log) { struct block_eraser eraser = flash->chip->block_erasers[k]; - if (!eraser.block_erase && !eraser.eraseblocks[0].count) { + if (eraser.block_erase == NO_BLOCK_ERASE_FUNC && !eraser.eraseblocks[0].count) { if (log) msg_cdbg("not defined. "); return 1; } - if (!eraser.block_erase && eraser.eraseblocks[0].count) { + if (eraser.block_erase == NO_BLOCK_ERASE_FUNC && eraser.eraseblocks[0].count) { if (log) msg_cdbg("eraseblock layout is known, but matching " "block erase function is not implemented. "); return 1; } - if (eraser.block_erase && !eraser.eraseblocks[0].count) { + if (eraser.block_erase != NO_BLOCK_ERASE_FUNC && !eraser.eraseblocks[0].count) { if (log) msg_cdbg("block erase function found, but " "eraseblock layout is not defined. "); return 1; } + + if (flash->mst->buses_supported & BUS_SPI) { + const uint8_t *opcode = spi_get_opcode_from_erasefn(eraser.block_erase); + if (opcode) + for (int i = 0; opcode[i]; i++) { + if (!spi_probe_opcode(flash, opcode[i])) { + if (log) + msg_cdbg("block erase function and layout found " + "but SPI master doesn't support the function. "); + return 1; + } + } + } // TODO: Once erase functions are annotated with allowed buses, check that as well. return 0; } /* Returns the number of well-defined erasers for a chip. */ -static unsigned int count_usable_erasers(const struct flashctx *flash) +unsigned int count_usable_erasers(const struct flashctx *flash) { unsigned int usable_erasefunctions = 0; int k; @@ -395,22 +531,106 @@ static int compare_range(const uint8_t *wantbuf, const uint8_t *havebuf, unsigne } /* start is an offset to the base address of the flash chip */ -static int check_erased_range(struct flashctx *flash, unsigned int start, unsigned int len) +int check_erased_range(struct flashctx *flash, unsigned int start, unsigned int len) { int ret; - uint8_t *cmpbuf = malloc(len); const uint8_t erased_value = ERASED_VALUE(flash); + uint8_t *cmpbuf = malloc(len); if (!cmpbuf) { - msg_gerr("Could not allocate memory!\n"); - exit(1); + msg_gerr("Out of memory!\n"); + return -1; } memset(cmpbuf, erased_value, len); ret = verify_range(flash, cmpbuf, start, len); + free(cmpbuf); return ret; } +#ifdef FLASHROM_TEST +/* special unit-test hook */ +read_func_t *g_test_read_injector; +#endif + +static read_func_t *lookup_read_func_ptr(const struct flashchip *chip) +{ + switch (chip->read) { + case SPI_CHIP_READ: return &spi_chip_read; + case READ_OPAQUE: return &read_opaque; + case READ_MEMMAPPED: return &read_memmapped; + case EDI_CHIP_READ: return &edi_chip_read; + case SPI_READ_AT45DB: return spi_read_at45db; + case SPI_READ_AT45DB_E8: return spi_read_at45db_e8; +#ifdef FLASHROM_TEST + case TEST_READ_INJECTOR: return g_test_read_injector; +#endif + /* default: total function, 0 indicates no read function set. + * We explicitly do not want a default catch-all case in the switch + * to ensure unhandled enum's are compiler warnings. + */ + case NO_READ_FUNC: return NULL; + }; + + return NULL; +} + +/* + * @brief Wrapper for flash->read() with additional high-level policy. + * + * @param flash flash chip + * @param buf buffer to store data in + * @param start start address + * @param len number of bytes to read + * @return 0 on success, + * -1 if any read fails. + * + * This wrapper simplifies most cases when the flash chip needs to be read + * since policy decisions such as non-fatal error handling is centralized. + */ +int read_flash(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len) +{ + unsigned int read_len; + for (unsigned int addr = start; addr < start + len; addr += read_len) { + struct flash_region region; + get_flash_region(flash, addr, ®ion); + + read_len = min(start + len, region.end + 1) - addr; + uint8_t *rbuf = buf + addr - start; + + if (region.read_prot) { + if (flash->flags.skip_unreadable_regions) { + msg_gdbg("%s: cannot read inside %s region (%#08"PRIx32"..%#08"PRIx32"), " + "filling (%#08x..%#08x) with erased value instead.\n", + __func__, region.name, region.start, region.end, + addr, addr + read_len - 1); + free(region.name); + + memset(rbuf, ERASED_VALUE(flash), read_len); + continue; + } + + msg_gerr("%s: cannot read inside %s region (%#08"PRIx32"..%#08"PRIx32").\n", + __func__, region.name, region.start, region.end); + free(region.name); + return -1; + } + msg_gdbg("%s: %s region (%#08"PRIx32"..%#08"PRIx32") is readable, reading range (%#08x..%#08x).\n", + __func__, region.name, region.start, region.end, addr, addr + read_len - 1); + free(region.name); + + read_func_t *read_func = lookup_read_func_ptr(flash->chip); + int ret = read_func(flash, rbuf, addr, read_len); + if (ret) { + msg_gerr("%s: failed to read (%#08x..%#08x).\n", __func__, addr, addr + read_len - 1); + return -1; + } + + } + + return 0; +} + /* * @cmpbuf buffer to compare against, cmpbuf[0] is expected to match the * flash content at location start @@ -430,26 +650,55 @@ int verify_range(struct flashctx *flash, const uint8_t *cmpbuf, unsigned int sta return -1; } - if (!flash->chip->read) { - msg_cerr("ERROR: flashrom has no read function for this flash chip.\n"); - return -1; - } - uint8_t *readbuf = malloc(len); if (!readbuf) { - msg_gerr("Could not allocate memory!\n"); + msg_gerr("Out of memory!\n"); return -1; } - int ret = flash->chip->read(flash, readbuf, start, len); - if (ret) { - msg_gerr("Verification impossible because read failed " - "at 0x%x (len 0x%x)\n", start, len); - ret = -1; - goto out_free; + int ret = 0; + + msg_gdbg("%#06x..%#06x ", start, start + len - 1); + + unsigned int read_len; + for (size_t addr = start; addr < start + len; addr += read_len) { + struct flash_region region; + get_flash_region(flash, addr, ®ion); + read_len = min(start + len, region.end + 1) - addr; + + if ((region.write_prot && flash->flags.skip_unwritable_regions) || + (region.read_prot && flash->flags.skip_unreadable_regions)) { + msg_gdbg("%s: Skipping verification of %s region (%#08"PRIx32"..%#08"PRIx32")\n", + __func__, region.name, region.start, region.end); + free(region.name); + continue; + } + + if (region.read_prot) { + msg_gerr("%s: Verification imposible because %s region (%#08"PRIx32"..%#08"PRIx32") is unreadable.\n", + __func__, region.name, region.start, region.end); + free(region.name); + goto out_free; + } + + msg_gdbg("%s: Verifying %s region (%#08"PRIx32"..%#08"PRIx32")\n", + __func__, region.name, region.start, region.end); + free(region.name); + + ret = read_flash(flash, readbuf, addr, read_len); + if (ret) { + msg_gerr("Verification impossible because read failed " + "at 0x%x (len 0x%x)\n", start, len); + ret = -1; + goto out_free; + } + + ret = compare_range(cmpbuf + (addr - start), readbuf, addr, read_len); + if (ret) + goto out_free; + } - ret = compare_range(cmpbuf, readbuf, start, len); out_free: free(readbuf); return ret; @@ -487,52 +736,49 @@ static int need_erase_gran_bytes(const uint8_t *have, const uint8_t *want, unsig * @gran write granularity (enum, not count) * @return 0 if no erase is needed, 1 otherwise */ -static int need_erase(const uint8_t *have, const uint8_t *want, unsigned int len, +int need_erase(const uint8_t *have, const uint8_t *want, unsigned int len, enum write_granularity gran, const uint8_t erased_value) { int result = 0; unsigned int i; switch (gran) { - case write_gran_1bit: + case WRITE_GRAN_1BIT: for (i = 0; i < len; i++) if ((have[i] & want[i]) != want[i]) { result = 1; break; } break; - case write_gran_1byte: + case WRITE_GRAN_1BYTE: for (i = 0; i < len; i++) if ((have[i] != want[i]) && (have[i] != erased_value)) { result = 1; break; } break; - case write_gran_128bytes: + case WRITE_GRAN_128BYTES: result = need_erase_gran_bytes(have, want, len, 128, erased_value); break; - case write_gran_256bytes: + case WRITE_GRAN_256BYTES: result = need_erase_gran_bytes(have, want, len, 256, erased_value); break; - case write_gran_264bytes: + case WRITE_GRAN_264BYTES: result = need_erase_gran_bytes(have, want, len, 264, erased_value); break; - case write_gran_512bytes: + case WRITE_GRAN_512BYTES: result = need_erase_gran_bytes(have, want, len, 512, erased_value); break; - case write_gran_528bytes: + case WRITE_GRAN_528BYTES: result = need_erase_gran_bytes(have, want, len, 528, erased_value); break; - case write_gran_1024bytes: + case WRITE_GRAN_1024BYTES: result = need_erase_gran_bytes(have, want, len, 1024, erased_value); break; - case write_gran_1056bytes: + case WRITE_GRAN_1056BYTES: result = need_erase_gran_bytes(have, want, len, 1056, erased_value); break; - case write_gran_64kbytes: - result = need_erase_gran_bytes(have, want, len, 64*KiB, erased_value); - break; - case write_gran_1byte_implicit_erase: + case WRITE_GRAN_1BYTE_IMPLICIT_ERASE: /* Do not erase, handle content changes from anything->0xff by writing 0xff. */ result = 0; break; @@ -566,7 +812,7 @@ static int need_erase(const uint8_t *have, const uint8_t *want, unsigned int len * in relation to the max write length of the programmer and the max write * length of the chip. */ -static unsigned int get_next_write(const uint8_t *have, const uint8_t *want, unsigned int len, +unsigned int get_next_write(const uint8_t *have, const uint8_t *want, unsigned int len, unsigned int *first_start, enum write_granularity gran) { @@ -575,33 +821,33 @@ static unsigned int get_next_write(const uint8_t *have, const uint8_t *want, uns unsigned int i, limit, stride; switch (gran) { - case write_gran_1bit: - case write_gran_1byte: - case write_gran_1byte_implicit_erase: + case WRITE_GRAN_1BIT: + case WRITE_GRAN_1BYTE: + case WRITE_GRAN_1BYTE_IMPLICIT_ERASE: stride = 1; break; - case write_gran_128bytes: + case WRITE_GRAN_128BYTES: stride = 128; break; - case write_gran_256bytes: + case WRITE_GRAN_256BYTES: stride = 256; break; - case write_gran_264bytes: + case WRITE_GRAN_264BYTES: stride = 264; break; - case write_gran_512bytes: + case WRITE_GRAN_512BYTES: stride = 512; break; - case write_gran_528bytes: + case WRITE_GRAN_528BYTES: stride = 528; break; - case write_gran_1024bytes: + case WRITE_GRAN_1024BYTES: stride = 1024; break; - case write_gran_1056bytes: + case WRITE_GRAN_1056BYTES: stride = 1056; break; - case write_gran_64kbytes: + case WRITE_GRAN_64KBYTES: stride = 64*KiB; break; default: @@ -636,49 +882,6 @@ static unsigned int get_next_write(const uint8_t *have, const uint8_t *want, uns return first_len; } -/* Returns the number of buses commonly supported by the current programmer and flash chip where the latter - * can not be completely accessed due to size/address limits of the programmer. */ -unsigned int count_max_decode_exceedings(const struct flashctx *flash) -{ - unsigned int limitexceeded = 0; - uint32_t size = flash->chip->total_size * 1024; - enum chipbustype buses = flash->mst->buses_supported & flash->chip->bustype; - - if ((buses & BUS_PARALLEL) && (max_rom_decode.parallel < size)) { - limitexceeded++; - msg_pdbg("Chip size %u kB is bigger than supported " - "size %u kB of chipset/board/programmer " - "for %s interface, " - "probe/read/erase/write may fail. ", size / 1024, - max_rom_decode.parallel / 1024, "Parallel"); - } - if ((buses & BUS_LPC) && (max_rom_decode.lpc < size)) { - limitexceeded++; - msg_pdbg("Chip size %u kB is bigger than supported " - "size %u kB of chipset/board/programmer " - "for %s interface, " - "probe/read/erase/write may fail. ", size / 1024, - max_rom_decode.lpc / 1024, "LPC"); - } - if ((buses & BUS_FWH) && (max_rom_decode.fwh < size)) { - limitexceeded++; - msg_pdbg("Chip size %u kB is bigger than supported " - "size %u kB of chipset/board/programmer " - "for %s interface, " - "probe/read/erase/write may fail. ", size / 1024, - max_rom_decode.fwh / 1024, "FWH"); - } - if ((buses & BUS_SPI) && (max_rom_decode.spi < size)) { - limitexceeded++; - msg_pdbg("Chip size %u kB is bigger than supported " - "size %u kB of chipset/board/programmer " - "for %s interface, " - "probe/read/erase/write may fail. ", size / 1024, - max_rom_decode.spi / 1024, "SPI"); - } - return limitexceeded; -} - void unmap_flash(struct flashctx *flash) { if (flash->virtual_registers != (chipaddr)ERROR_PTR) { @@ -736,38 +939,175 @@ int map_flash(struct flashctx *flash) /* * Return a string corresponding to the bustype parameter. - * Memory is obtained with malloc() and must be freed with free() by the caller. + * Memory to store the string is allocated. The caller is responsible to free memory. + * If there is not enough memory remaining, then NULL is returned. */ char *flashbuses_to_text(enum chipbustype bustype) { - char *ret = calloc(1, 1); + char *ret, *ptr; + /* * FIXME: Once all chipsets and flash chips have been updated, NONSPI * will cease to exist and should be eliminated here as well. */ - if (bustype == BUS_NONSPI) { - ret = strcat_realloc(ret, "Non-SPI, "); - } else { - if (bustype & BUS_PARALLEL) - ret = strcat_realloc(ret, "Parallel, "); - if (bustype & BUS_LPC) - ret = strcat_realloc(ret, "LPC, "); - if (bustype & BUS_FWH) - ret = strcat_realloc(ret, "FWH, "); - if (bustype & BUS_SPI) - ret = strcat_realloc(ret, "SPI, "); - if (bustype & BUS_PROG) - ret = strcat_realloc(ret, "Programmer-specific, "); - if (bustype == BUS_NONE) - ret = strcat_realloc(ret, "None, "); + if (bustype == BUS_NONSPI) + return strdup("Non-SPI"); + if (bustype == BUS_NONE) + return strdup("None"); + + ret = calloc(1, 1); + if (!ret) + return NULL; + + for (unsigned int i = 0; i < ARRAY_SIZE(bustypes); i++) + { + if (bustype & bustypes[i].type) { + ptr = strcat_realloc(ret, bustypes[i].name); + if (!ptr) { + free(ret); + return NULL; + } + ret = ptr; + } } + /* Kill last comma. */ ret[strlen(ret) - 2] = '\0'; - ret = realloc(ret, strlen(ret) + 1); - return ret; + ptr = realloc(ret, strlen(ret) + 1); + if (!ptr) + free(ret); + return ptr; } -int probe_flash(struct registered_master *mst, int startchip, struct flashctx *flash, int force) +static int init_default_layout(struct flashctx *flash) +{ + /* Fill default layout covering the whole chip. */ + if (flashrom_layout_new(&flash->default_layout) || + flashrom_layout_add_region(flash->default_layout, + 0, flash->chip->total_size * 1024 - 1, "complete flash") || + flashrom_layout_include_region(flash->default_layout, "complete flash")) + return -1; + return 0; +} + +/* special unit-test hook */ +#ifdef FLASHROM_TEST +write_func_t *g_test_write_injector; +#endif + +static write_func_t *lookup_write_func_ptr(const struct flashchip *chip) +{ + switch (chip->write) { + case WRITE_JEDEC: return &write_jedec; + case WRITE_JEDEC1: return &write_jedec_1; + case WRITE_OPAQUE: return &write_opaque; + case SPI_CHIP_WRITE1: return &spi_chip_write_1; + case SPI_CHIP_WRITE256: return &spi_chip_write_256; + case SPI_WRITE_AAI: return &spi_aai_write; + case SPI_WRITE_AT45DB: return &spi_write_at45db; + case WRITE_28SF040: return &write_28sf040; + case WRITE_82802AB: return &write_82802ab; + case WRITE_EN29LV640B: return &write_en29lv640b; + case EDI_CHIP_WRITE: return &edi_chip_write; +#ifdef FLASHROM_TEST + case TEST_WRITE_INJECTOR: return g_test_write_injector; +#endif + /* default: total function, 0 indicates no write function set. + * We explicitly do not want a default catch-all case in the switch + * to ensure unhandled enum's are compiler warnings. + */ + case NO_WRITE_FUNC: return NULL; + }; + + return NULL; +} + +/* + * write_flash - wrapper for flash->write() with additional high-level policy + * + * @param flash flash chip + * @param buf buffer to write to flash + * @param start start address in flash + * @param len number of bytes to write + * @return 0 on success, + * -1 if any write fails. + * + * This wrapper simplifies most cases when the flash chip needs to be written + * since policy decisions such as non-fatal error handling is centralized. + */ +int write_flash(struct flashctx *flash, const uint8_t *buf, + unsigned int start, unsigned int len) +{ + if (!flash->flags.skip_unwritable_regions) { + if (check_for_unwritable_regions(flash, start, len)) + return -1; + } + + unsigned int write_len; + for (unsigned int addr = start; addr < start + len; addr += write_len) { + struct flash_region region; + get_flash_region(flash, addr, ®ion); + + write_len = min(start + len, region.end + 1) - addr; + const uint8_t *rbuf = buf + addr - start; + + if (region.write_prot) { + msg_gdbg("%s: cannot write inside %s region (%#08"PRIx32"..%#08"PRIx32"), skipping (%#08x..%#08x).\n", + __func__, region.name, region.start, region.end, addr, addr + write_len - 1); + free(region.name); + continue; + } + + msg_gdbg("%s: %s region (%#08"PRIx32"..%#08"PRIx32") is writable, writing range (%#08x..%#08x).\n", + __func__, region.name, region.start, region.end, addr, addr + write_len - 1); + + write_func_t *write_func = lookup_write_func_ptr(flash->chip); + int ret = write_func(flash, rbuf, addr, write_len); + if (ret) { + msg_gerr("%s: failed to write (%#08x..%#08x).\n", __func__, addr, addr + write_len - 1); + free(region.name); + return -1; + } + + free(region.name); + } + + return 0; +} + +typedef int (probe_func_t)(struct flashctx *flash); + +static probe_func_t *lookup_probe_func_ptr(const struct flashchip *chip) +{ + switch (chip->probe) { + case PROBE_JEDEC: return &probe_jedec; + case PROBE_JEDEC_29GL: return &probe_jedec_29gl; + case PROBE_OPAQUE: return &probe_opaque; + case PROBE_EDI_KB9012: return &edi_probe_kb9012; + case PROBE_AT82802AB: return &probe_82802ab; + case PROBE_W29EE011: return &probe_w29ee011; + case PROBE_EN29LV640B: return &probe_en29lv640b; + case PROBE_SPI_AT25F: return &probe_spi_at25f; + case PROBE_SPI_AT45DB: return &probe_spi_at45db; + case PROBE_SPI_BIG_SPANSION: return &probe_spi_big_spansion; + case PROBE_SPI_RDID: return &probe_spi_rdid; + case PROBE_SPI_RDID4: return &probe_spi_rdid4; + case PROBE_SPI_REMS: return &probe_spi_rems; + case PROBE_SPI_RES1: return &probe_spi_res1; + case PROBE_SPI_RES2: return &probe_spi_res2; + case PROBE_SPI_SFDP: return &probe_spi_sfdp; + case PROBE_SPI_ST95: return &probe_spi_st95; + /* default: total function, 0 indicates no probe function set. + * We explicitly do not want a default catch-all case in the switch + * to ensure unhandled enum's are compiler warnings. + */ + case NO_PROBE_FUNC: return NULL; + }; + + return NULL; +} + +int probe_flash(struct registered_master *mst, int startchip, struct flashctx *flash, int force, const char *const chip_to_probe) { const struct flashchip *chip; enum chipbustype buses_common; @@ -783,7 +1123,8 @@ int probe_flash(struct registered_master *mst, int startchip, struct flashctx *f if (chip->bustype == BUS_SPI && !chip_to_probe && chip->spi_cmd_set != SPI25) continue; msg_gdbg("Probing for %s %s, %d kB: ", chip->vendor, chip->name, chip->total_size); - if (!chip->probe && !force) { + probe_func_t *probe_func = lookup_probe_func_ptr(chip); + if (!probe_func && !force) { msg_gdbg("failed! flashrom has no probe function for this flash chip.\n"); continue; } @@ -792,7 +1133,7 @@ int probe_flash(struct registered_master *mst, int startchip, struct flashctx *f flash->chip = calloc(1, sizeof(*flash->chip)); if (!flash->chip) { msg_gerr("Out of memory!\n"); - exit(1); + return -1; } *flash->chip = *chip; flash->mst = mst; @@ -806,7 +1147,11 @@ int probe_flash(struct registered_master *mst, int startchip, struct flashctx *f if (force) break; - if (flash->chip->probe(flash) != 1) + if (probe_func == &probe_w29ee011) + if (!w29ee011_can_override(flash->chip->name, chip_to_probe)) + goto notfound; + + if (probe_func(flash) != 1) goto notfound; /* If this is the first chip found, accept it. @@ -855,16 +1200,12 @@ int probe_flash(struct registered_master *mst, int startchip, struct flashctx *f if (!flash->chip) return -1; - /* Fill default layout covering the whole chip. */ - if (flashrom_layout_new(&flash->default_layout) || - flashrom_layout_add_region(flash->default_layout, - 0, flash->chip->total_size * 1024 - 1, "complete flash") || - flashrom_layout_include_region(flash->default_layout, "complete flash")) - return -1; + if (init_default_layout(flash) < 0) + return -1; tmp = flashbuses_to_text(flash->chip->bustype); msg_cinfo("%s %s flash chip \"%s\" (%d kB, %s) ", force ? "Assuming" : "Found", - flash->chip->vendor, flash->chip->name, flash->chip->total_size, tmp); + flash->chip->vendor, flash->chip->name, flash->chip->total_size, tmp ? tmp : "?"); free(tmp); if (master_uses_physmap(mst)) msg_cinfo("mapped at physical address 0x%0*" PRIxPTR ".\n", @@ -874,9 +1215,11 @@ int probe_flash(struct registered_master *mst, int startchip, struct flashctx *f /* Flash registers may more likely not be mapped if the chip was forced. * Lock info may be stored in registers, so avoid lock info printing. */ - if (!force) - if (flash->chip->printlock) - flash->chip->printlock(flash); + if (!force) { + printlockfunc_t *printlock = lookup_printlock_func_ptr(flash); + if (printlock) + printlock(flash); + } /* Get out of the way for later runs. */ unmap_flash(flash); @@ -902,10 +1245,11 @@ static int read_by_layout(struct flashctx *const flashctx, uint8_t *const buffer const struct romentry *entry = NULL; while ((entry = layout_next_included(layout, entry))) { - const chipoff_t region_start = entry->start; - const chipsize_t region_len = entry->end - entry->start + 1; + const struct flash_region *region = &entry->region; + const chipoff_t region_start = region->start; + const chipsize_t region_len = region->end - region->start + 1; - if (flashctx->chip->read(flashctx, buffer + region_start, region_start, region_len)) + if (read_flash(flashctx, buffer + region_start, region_start, region_len)) return 1; } return 0; @@ -976,8 +1320,7 @@ static int selfcheck_eraseblocks(const struct flashchip *chip) ret = 1; } } - if(curr_eraseblock_count > prev_eraseblock_count) - { + if (curr_eraseblock_count > prev_eraseblock_count) { msg_gerr("ERROR: Flash chip %s erase function %i is not " "in order. Please report a bug at flashrom@flashrom.org\n", chip->name, k); @@ -988,335 +1331,84 @@ static int selfcheck_eraseblocks(const struct flashchip *chip) return ret; } -typedef int (*erasefn_t)(struct flashctx *, unsigned int addr, unsigned int len); -/** - * @private - * - * For read-erase-write, `curcontents` and `newcontents` shall point - * to buffers of the chip's size. Both are supposed to be prefilled - * with at least the included layout regions of the current flash - * contents (`curcontents`) and the data to be written to the flash - * (`newcontents`). - * - * For erase, `curcontents` and `newcontents` shall be NULL-pointers. - * - * The `chipoff_t` values are used internally by `walk_by_layout()`. - */ -struct walk_info { - uint8_t *curcontents; - const uint8_t *newcontents; - chipoff_t region_start; - chipoff_t region_end; - chipoff_t erase_start; - chipoff_t erase_end; -}; -/* returns 0 on success, 1 to retry with another erase function, 2 for immediate abort */ -typedef int (*per_blockfn_t)(struct flashctx *, const struct walk_info *, erasefn_t); - -static int walk_eraseblocks(struct flashctx *const flashctx, - struct walk_info *const info, - const size_t erasefunction, const per_blockfn_t per_blockfn) +static int erase_by_layout(struct flashctx *const flashctx) { - int ret; - size_t i, j; - bool first = true; - struct block_eraser *const eraser = &flashctx->chip->block_erasers[erasefunction]; - - info->erase_start = 0; - for (i = 0; i < NUM_ERASEREGIONS; ++i) { - /* count==0 for all automatically initialized array - members so the loop below won't be executed for them. */ - for (j = 0; j < eraser->eraseblocks[i].count; ++j, info->erase_start = info->erase_end + 1) { - info->erase_end = info->erase_start + eraser->eraseblocks[i].size - 1; - - /* Skip any eraseblock that is completely outside the current region. */ - if (info->erase_end < info->region_start) - continue; - if (info->region_end < info->erase_start) - break; - - /* Print this for every block except the first one. */ - if (first) - first = false; - else - msg_cdbg(", "); - msg_cdbg("0x%06x-0x%06x:", info->erase_start, info->erase_end); + bool all_skipped = true; + const uint32_t flash_size = flashctx->chip->total_size * 1024; + uint8_t* curcontents = malloc(flash_size); + uint8_t* newcontents = malloc(flash_size); + struct erase_layout *erase_layout; + create_erase_layout(flashctx, &erase_layout); + int ret = 0; - ret = per_blockfn(flashctx, info, eraser->block_erase); - if (ret) - return ret; - } - if (info->region_end < info->erase_start) - break; + //erase layout creation failed + if (!erase_layout) { + ret = 1; + goto _ret; } - msg_cdbg("\n"); - return 0; -} - -static int walk_by_layout(struct flashctx *const flashctx, struct walk_info *const info, - const per_blockfn_t per_blockfn) -{ - const struct flashrom_layout *const layout = get_layout(flashctx); - const struct romentry *entry = NULL; - - all_skipped = true; - msg_cinfo("Erasing and writing flash chip... "); - while ((entry = layout_next_included(layout, entry))) { - info->region_start = entry->start; - info->region_end = entry->end; - - size_t j; - int error = 1; /* retry as long as it's 1 */ - for (j = 0; j < NUM_ERASEFUNCTIONS; ++j) { - if (j != 0) - msg_cinfo("Looking for another erase function.\n"); - msg_cdbg("Trying erase function %zi... ", j); - if (check_block_eraser(flashctx, j, 1)) - continue; - - error = walk_eraseblocks(flashctx, info, j, per_blockfn); - if (error != 1) - break; - - if (info->curcontents) { - msg_cinfo("Reading current flash chip contents... "); - if (read_by_layout(flashctx, info->curcontents)) { - /* Now we are truly screwed. Read failed as well. */ - msg_cerr("Can't read anymore! Aborting.\n"); - /* We have no idea about the flash chip contents, so - retrying with another erase function is pointless. */ - error = 2; - break; - } - msg_cinfo("done. "); - } - } - if (error == 1) - msg_cinfo("No usable erase functions left.\n"); - if (error) { - msg_cerr("FAILED!\n"); - return 1; - } + //not enough memory + if (!curcontents || !newcontents) { + ret = 1; + goto _ret; } - if (all_skipped) - msg_cinfo("\nWarning: Chip content is identical to the requested image.\n"); - msg_cinfo("Erase/write done.\n"); - return 0; -} -static int erase_block(struct flashctx *const flashctx, - const struct walk_info *const info, const erasefn_t erasefn) -{ - const unsigned int erase_len = info->erase_end + 1 - info->erase_start; - const bool region_unaligned = info->region_start > info->erase_start || - info->erase_end > info->region_end; - uint8_t *backup_contents = NULL, *erased_contents = NULL; - int ret = 2; + memset(curcontents, ~ERASED_VALUE(flashctx), flash_size); + memset(newcontents, ERASED_VALUE(flashctx), flash_size); - /* - * If the region is not erase-block aligned, merge current flash con- - * tents into a new buffer `backup_contents`. - */ - if (region_unaligned) { - backup_contents = malloc(erase_len); - erased_contents = malloc(erase_len); - if (!backup_contents || !erased_contents) { - msg_cerr("Out of memory!\n"); + const struct flashrom_layout *const flash_layout = get_layout(flashctx); + const struct romentry *entry = NULL; + while ((entry = layout_next_included(flash_layout, entry))) { + ret = erase_write(flashctx, entry->region.start, entry->region.end, curcontents, newcontents, erase_layout, &all_skipped); + if (ret) { ret = 1; - goto _free_ret; - } - memset(backup_contents, ERASED_VALUE(flashctx), erase_len); - memset(erased_contents, ERASED_VALUE(flashctx), erase_len); - - msg_cdbg("R"); - /* Merge data preceding the current region. */ - if (info->region_start > info->erase_start) { - const chipoff_t start = info->erase_start; - const chipsize_t len = info->region_start - info->erase_start; - if (flashctx->chip->read(flashctx, backup_contents, start, len)) { - msg_cerr("Can't read! Aborting.\n"); - goto _free_ret; - } - } - /* Merge data following the current region. */ - if (info->erase_end > info->region_end) { - const chipoff_t start = info->region_end + 1; - const chipoff_t rel_start = start - info->erase_start; /* within this erase block */ - const chipsize_t len = info->erase_end - info->region_end; - if (flashctx->chip->read(flashctx, backup_contents + rel_start, start, len)) { - msg_cerr("Can't read! Aborting.\n"); - goto _free_ret; - } - } - } - - ret = 1; - all_skipped = false; - - msg_cdbg("E"); - if (erasefn(flashctx, info->erase_start, erase_len)) - goto _free_ret; - if (check_erased_range(flashctx, info->erase_start, erase_len)) { - msg_cerr("ERASE FAILED!\n"); - goto _free_ret; - } - - if (region_unaligned) { - unsigned int starthere = 0, lenhere = 0, writecount = 0; - /* get_next_write() sets starthere to a new value after the call. */ - while ((lenhere = get_next_write(erased_contents + starthere, backup_contents + starthere, - erase_len - starthere, &starthere, flashctx->chip->gran))) { - if (!writecount++) - msg_cdbg("W"); - /* Needs the partial write function signature. */ - if (flashctx->chip->write(flashctx, backup_contents + starthere, - info->erase_start + starthere, lenhere)) - goto _free_ret; - starthere += lenhere; + msg_cerr("Erase Failed"); + goto _ret; } } - ret = 0; - -_free_ret: - free(erased_contents); - free(backup_contents); +_ret: + free(curcontents); + free(newcontents); + free_erase_layout(erase_layout, count_usable_erasers(flashctx)); return ret; } -/** - * @brief Erases the included layout regions. - * - * If there is no layout set in the given flash context, the whole chip will - * be erased. - * - * @param flashctx Flash context to be used. - * @return 0 on success, - * 1 if all available erase functions failed. - */ -static int erase_by_layout(struct flashctx *const flashctx) -{ - struct walk_info info = { 0 }; - return walk_by_layout(flashctx, &info, &erase_block); -} - -static int read_erase_write_block(struct flashctx *const flashctx, - const struct walk_info *const info, const erasefn_t erasefn) +static int write_by_layout(struct flashctx *const flashctx, + void *const curcontents, const void *const newcontents, + bool *all_skipped) { - const chipsize_t erase_len = info->erase_end + 1 - info->erase_start; - const bool region_unaligned = info->region_start > info->erase_start || - info->erase_end > info->region_end; - const uint8_t *newcontents = NULL; - int ret = 2; + const int erasefn_count = count_usable_erasers(flashctx); + int ret = 1; - /* - * If the region is not erase-block aligned, merge current flash con- - * tents into `info->curcontents` and a new buffer `newc`. The former - * is necessary since we have no guarantee that the full erase block - * was already read into `info->curcontents`. For the latter a new - * buffer is used since `info->newcontents` might contain data for - * other unaligned regions that touch this erase block too. - */ - if (region_unaligned) { - msg_cdbg("R"); - uint8_t *const newc = malloc(erase_len); - if (!newc) { - msg_cerr("Out of memory!\n"); - return 1; - } - memcpy(newc, info->newcontents + info->erase_start, erase_len); - - /* Merge data preceding the current region. */ - if (info->region_start > info->erase_start) { - const chipoff_t start = info->erase_start; - const chipsize_t len = info->region_start - info->erase_start; - if (flashctx->chip->read(flashctx, newc, start, len)) { - msg_cerr("Can't read! Aborting.\n"); - goto _free_ret; - } - memcpy(info->curcontents + start, newc, len); - } - /* Merge data following the current region. */ - if (info->erase_end > info->region_end) { - const chipoff_t start = info->region_end + 1; - const chipoff_t rel_start = start - info->erase_start; /* within this erase block */ - const chipsize_t len = info->erase_end - info->region_end; - if (flashctx->chip->read(flashctx, newc + rel_start, start, len)) { - msg_cerr("Can't read! Aborting.\n"); - goto _free_ret; - } - memcpy(info->curcontents + start, newc + rel_start, len); - } + const struct flashrom_layout *const flash_layout = get_layout(flashctx); + struct erase_layout *erase_layout; + create_erase_layout(flashctx, &erase_layout); - newcontents = newc; - } else { - newcontents = info->newcontents + info->erase_start; + if (!flash_layout) { + goto _ret; } - - ret = 1; - bool skipped = true; - uint8_t *const curcontents = info->curcontents + info->erase_start; - const uint8_t erased_value = ERASED_VALUE(flashctx); - if (!(flashctx->chip->feature_bits & FEATURE_NO_ERASE) && - need_erase(curcontents, newcontents, erase_len, flashctx->chip->gran, erased_value)) { - if (erase_block(flashctx, info, erasefn)) - goto _free_ret; - /* Erase was successful. Adjust curcontents. */ - memset(curcontents, erased_value, erase_len); - skipped = false; - } - - unsigned int starthere = 0, lenhere = 0, writecount = 0; - /* get_next_write() sets starthere to a new value after the call. */ - while ((lenhere = get_next_write(curcontents + starthere, newcontents + starthere, - erase_len - starthere, &starthere, flashctx->chip->gran))) { - if (!writecount++) - msg_cdbg("W"); - /* Needs the partial write function signature. */ - if (flashctx->chip->write(flashctx, newcontents + starthere, - info->erase_start + starthere, lenhere)) - goto _free_ret; - starthere += lenhere; - skipped = false; + if (!erase_layout) { + goto _ret; } - if (skipped) - msg_cdbg("S"); - else - all_skipped = false; - /* Update curcontents, other regions with overlapping erase blocks - might rely on this. */ - memcpy(curcontents, newcontents, erase_len); - ret = 0; - -_free_ret: - if (region_unaligned) - free((void *)newcontents); + const struct romentry *entry = NULL; + while ((entry = layout_next_included(flash_layout, entry))) { + ret = erase_write(flashctx, entry->region.start, + entry->region.end, + curcontents, + (uint8_t *)newcontents, + erase_layout, all_skipped); + if (ret) { + msg_cerr("Write Failed!"); + goto _ret; + } + } +_ret: + free_erase_layout(erase_layout, erasefn_count); return ret; } -/** - * @brief Writes the included layout regions from a given image. - * - * If there is no layout set in the given flash context, the whole image - * will be written. - * - * @param flashctx Flash context to be used. - * @param curcontents A buffer of full chip size with current chip contents of included regions. - * @param newcontents The new image to be written. - * @return 0 on success, - * 1 if anything has gone wrong. - */ -static int write_by_layout(struct flashctx *const flashctx, - void *const curcontents, const void *const newcontents) -{ - struct walk_info info; - info.curcontents = curcontents; - info.newcontents = newcontents; - return walk_by_layout(flashctx, &info, read_erase_write_block); -} - /** * @brief Compares the included layout regions with content from a buffer. * @@ -1339,10 +1431,11 @@ static int verify_by_layout( const struct romentry *entry = NULL; while ((entry = layout_next_included(layout, entry))) { - const chipoff_t region_start = entry->start; - const chipsize_t region_len = entry->end - entry->start + 1; + const struct flash_region *region = &entry->region; + const chipoff_t region_start = region->start; + const chipsize_t region_len = region->end - region->start + 1; - if (flashctx->chip->read(flashctx, curcontents + region_start, region_start, region_len)) + if (read_flash(flashctx, curcontents + region_start, region_start, region_len)) return 1; if (compare_range(newcontents + region_start, curcontents + region_start, region_start, region_len)) @@ -1529,7 +1622,7 @@ static int chip_safety_check(const struct flashctx *flash, int force, return 1; msg_cerr("Continuing anyway.\n"); } - if (!chip->read) { + if (!lookup_read_func_ptr(chip)) { msg_cerr("flashrom has no read function for this " "flash chip.\n"); return 1; @@ -1564,7 +1657,7 @@ static int chip_safety_check(const struct flashctx *flash, int force, return 1; msg_cerr("Continuing anyway.\n"); } - if (!chip->write) { + if (!lookup_write_func_ptr(chip)) { msg_cerr("flashrom has no write function for this " "flash chip.\n"); return 1; @@ -1573,6 +1666,78 @@ static int chip_safety_check(const struct flashctx *flash, int force, return 0; } +static int restore_flash_wp(struct flashctx *const flash, void *data) +{ + struct flashrom_wp_cfg *wp_cfg = data; + enum flashrom_wp_result ret = flashrom_wp_write_cfg(flash, wp_cfg); + flashrom_wp_cfg_release(wp_cfg); + + return (ret == FLASHROM_WP_OK) ? 0 : -1; +} + +static int save_initial_flash_wp(struct flashctx *const flash) +{ + struct flashrom_wp_cfg *initial_wp_cfg; + if (flashrom_wp_cfg_new(&initial_wp_cfg) != FLASHROM_WP_OK) + return -1; + + if (flashrom_wp_read_cfg(initial_wp_cfg, flash) != FLASHROM_WP_OK) { + flashrom_wp_cfg_release(initial_wp_cfg); + return -1; + } + + if (register_chip_restore(restore_flash_wp, flash, initial_wp_cfg)) { + flashrom_wp_cfg_release(initial_wp_cfg); + return -1; + } + return 0; +} + +static int unlock_flash_wp(struct flashctx *const flash, + const bool write_it, const bool erase_it) + +{ + int ret = 0; + + /* WP only disables write protection, so only use WP to unlock + * for write/erase operations. + * + * For read/verify operations, we still call the chip's unlock + * function, which may disable read locks if the chip has them. + */ + if (!write_it && !erase_it) { + msg_cdbg("Skipping writeprotect-based unlocking for read/verify operations.\n"); + return -1; + } + + /* Save original WP state to be restored later */ + if (save_initial_flash_wp(flash)) { + ret = -1; + goto warn_out; + } + + /* Disable WP */ + struct flashrom_wp_cfg *unlocked_wp_cfg; + if (flashrom_wp_cfg_new(&unlocked_wp_cfg) != FLASHROM_WP_OK) { + ret = -1; + goto warn_out; + } + + flashrom_wp_set_range(unlocked_wp_cfg, 0, 0); + flashrom_wp_set_mode(unlocked_wp_cfg, FLASHROM_WP_MODE_DISABLED); + if (flashrom_wp_write_cfg(flash, unlocked_wp_cfg) != FLASHROM_WP_OK) { + ret = -1; + } + + flashrom_wp_cfg_release(unlocked_wp_cfg); + +warn_out: + if (ret) + msg_cwarn("Failed to unlock flash status reg with wp support.\n"); + + return ret; +} + int prepare_flash_access(struct flashctx *const flash, const bool read_it, const bool write_it, const bool erase_it, const bool verify_it) @@ -1593,10 +1758,22 @@ int prepare_flash_access(struct flashctx *const flash, /* Initialize chip_restore_fn_count before chip unlock calls. */ flash->chip_restore_fn_count = 0; - /* Given the existence of read locks, we want to unlock for read, - erase and write. */ - if (flash->chip->unlock) - flash->chip->unlock(flash); + int ret = 1; + if (flash->chip->decode_range != NO_DECODE_RANGE_FUNC || + (flash->mst->buses_supported & BUS_PROG && flash->mst->opaque.wp_write_cfg)) { + ret = unlock_flash_wp(flash, write_it, erase_it); + } + /* + * Fall back to chip unlock function if we haven't already successfully + * unlocked using WP (e.g. WP unlocking failed, chip had no WP support, + * WP was skipped for read/verify ops). + * + * Given the existence of read locks, we want to unlock for read, + * erase, write, and verify. + */ + blockprotect_func_t *bp_func = lookup_blockprotect_func_ptr(flash->chip); + if (ret && bp_func) + bp_func(flash); flash->address_high_byte = -1; flash->in_4ba_mode = false; @@ -1612,8 +1789,7 @@ int prepare_flash_access(struct flashctx *const flash, } /* Enable/disable 4-byte addressing mode if flash chip supports it */ - if (flash->chip->feature_bits & (FEATURE_4BA_ENTER | FEATURE_4BA_ENTER_WREN | FEATURE_4BA_ENTER_EAR7)) { - int ret; + if (spi_chip_4ba(flash)) { if (spi_master_4ba(flash)) ret = spi_enter_4ba(flash); else @@ -1679,12 +1855,13 @@ static void combine_image_by_layout(const struct flashctx *const flashctx, chipoff_t start = 0; while ((included = layout_next_included_region(layout, start))) { - if (included->start > start) { + const struct flash_region *region = &included->region; + if (region->start > start) { /* copy everything up to the start of this included region */ - memcpy(newcontents + start, oldcontents + start, included->start - start); + memcpy(newcontents + start, oldcontents + start, region->start - start); } /* skip this included region */ - start = included->end + 1; + start = region->end + 1; if (start == 0) return; } @@ -1750,7 +1927,7 @@ int flashrom_image_write(struct flashctx *const flashctx, void *const buffer, co */ msg_cinfo("Reading old flash chip contents... "); if (verify_all) { - if (flashctx->chip->read(flashctx, oldcontents, 0, flash_size)) { + if (read_flash(flashctx, oldcontents, 0, flash_size)) { msg_cinfo("FAILED.\n"); goto _finalize_ret; } @@ -1764,13 +1941,15 @@ int flashrom_image_write(struct flashctx *const flashctx, void *const buffer, co msg_cinfo("done.\n"); } - if (write_by_layout(flashctx, curcontents, newcontents)) { + bool all_skipped = true; + + if (write_by_layout(flashctx, curcontents, newcontents, &all_skipped)) { msg_cerr("Uh oh. Erase/write failed. "); ret = 2; if (verify_all) { msg_cerr("Checking if anything has changed.\n"); msg_cinfo("Reading current flash chip contents... "); - if (!flashctx->chip->read(flashctx, curcontents, 0, flash_size)) { + if (!read_flash(flashctx, curcontents, 0, flash_size)) { msg_cinfo("done.\n"); if (!memcmp(oldcontents, curcontents, flash_size)) { nonfatal_help_message(); @@ -1792,8 +1971,31 @@ int flashrom_image_write(struct flashctx *const flashctx, void *const buffer, co if (verify && !all_skipped) { msg_cinfo("Verifying flash... "); - /* Work around chips which need some time to calm down. */ - programmer_delay(1000*1000); + /* + * Work around chips which "need some time to calm down." + * + * Frankly, it's not 100% clear why this delay is here at all, + * except for a terse message from 2009 of "a few reports where + * verify directly after erase had unpleasant side effects like + * corrupting flash or at least getting incorrect verify + * results". Ideally, if there were a few known problematic + * chips or programmers, we could add quirks flags for those + * specific implementations without penalizing all other + * flashrom users. But alas, we don't know which systems + * experienced those issues. + * + * Out of an extreme abundance of caution, we retain this + * delay, but only for a few non-SPI bus types that were the + * likely prevalent targets at the time. This is a complete + * guess, which conveniently avoids wasting time on common + * BUS_SPI and BUS_PROG systems. + * + * Background thread: + * Subject: RFC: removing 1 second verification delay + * https://mail.coreboot.org/hyperkitty/list/flashrom@flashrom.org/thread/SFV3OJBVVMDKRLI3FQA3DDDGEXJ7W4ED/ + */ + if (flashctx->chip->bustype & (BUS_PARALLEL | BUS_LPC | BUS_FWH)) + programmer_delay(flashctx, 1000*1000); if (verify_all) combine_image_by_layout(flashctx, newcontents, oldcontents); diff --git a/fmap.c b/fmap.c index 69824ea82..50cb96900 100644 --- a/fmap.c +++ b/fmap.c @@ -47,14 +47,13 @@ static size_t fmap_size(const struct fmap *fmap) return sizeof(*fmap) + (fmap->nareas * sizeof(struct fmap_area)); } +/* Make a best-effort assessment if the given fmap is real */ static int is_valid_fmap(const struct fmap *fmap) { if (memcmp(fmap, FMAP_SIGNATURE, strlen(FMAP_SIGNATURE)) != 0) return 0; /* strings containing the magic tend to fail here */ - if (fmap->ver_major > FMAP_VER_MAJOR) - return 0; - if (fmap->ver_minor > FMAP_VER_MINOR) + if (fmap->ver_major != FMAP_VER_MAJOR) return 0; /* a basic consistency check: flash address space size should be larger * than the size of the fmap data structure */ @@ -167,7 +166,7 @@ static int fmap_lsearch_rom(struct fmap **fmap_out, goto _finalize_ret; } - ret = flashctx->chip->read(flashctx, buf + rom_offset, rom_offset, len); + ret = read_flash(flashctx, buf + rom_offset, rom_offset, len); if (ret) { msg_pdbg("Cannot read ROM contents.\n"); goto _free_ret; @@ -232,7 +231,7 @@ static int fmap_bsearch_rom(struct fmap **fmap_out, struct flashctx *const flash /* Read errors are considered non-fatal since we may * encounter locked regions and want to continue. */ - if (flashctx->chip->read(flashctx, (uint8_t *)fmap, offset, sig_len)) { + if (read_flash(flashctx, (uint8_t *)fmap, offset, sig_len)) { /* * Print in verbose mode only to avoid excessive * messages for benign errors. Subsequent error @@ -245,7 +244,7 @@ static int fmap_bsearch_rom(struct fmap **fmap_out, struct flashctx *const flash if (memcmp(fmap, FMAP_SIGNATURE, sig_len) != 0) continue; - if (flashctx->chip->read(flashctx, (uint8_t *)fmap + sig_len, + if (read_flash(flashctx, (uint8_t *)fmap + sig_len, offset + sig_len, sizeof(*fmap) - sig_len)) { msg_cerr("Cannot read %zu bytes at offset %06zx\n", sizeof(*fmap) - sig_len, offset + sig_len); @@ -277,7 +276,7 @@ static int fmap_bsearch_rom(struct fmap **fmap_out, struct flashctx *const flash goto _free_ret; } - if (flashctx->chip->read(flashctx, (uint8_t *)fmap + sizeof(*fmap), + if (read_flash(flashctx, (uint8_t *)fmap + sizeof(*fmap), offset + sizeof(*fmap), fmap_len - sizeof(*fmap))) { msg_cerr("Cannot read %zu bytes at offset %06zx\n", fmap_len - sizeof(*fmap), offset + sizeof(*fmap)); diff --git a/ft2232_spi.c b/ft2232_spi.c index aec21bc9d..7d7283bc9 100644 --- a/ft2232_spi.c +++ b/ft2232_spi.c @@ -295,13 +295,10 @@ static const struct spi_master spi_master_ft2232 = { .features = SPI_MASTER_4BA, .max_data_read = 64 * 1024, .max_data_write = 256, - .command = default_spi_send_command, .multicommand = ft2232_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = ft2232_shutdown, - .probe_opcode = default_spi_probe_opcode, }; /* Returns 0 upon success, a negative number upon errors. */ diff --git a/gfxnvidia.c b/gfxnvidia.c index 1d484ead6..080c88546 100644 --- a/gfxnvidia.c +++ b/gfxnvidia.c @@ -96,13 +96,7 @@ static int gfxnvidia_shutdown(void *par_data) static const struct par_master par_master_gfxnvidia = { .chip_readb = gfxnvidia_chip_readb, - .chip_readw = fallback_chip_readw, - .chip_readl = fallback_chip_readl, - .chip_readn = fallback_chip_readn, .chip_writeb = gfxnvidia_chip_writeb, - .chip_writew = fallback_chip_writew, - .chip_writel = fallback_chip_writel, - .chip_writen = fallback_chip_writen, .shutdown = gfxnvidia_shutdown, }; @@ -121,7 +115,7 @@ static int gfxnvidia_init(const struct programmer_cfg *cfg) return 1; io_base_addr += 0x300000; - msg_pinfo("Detected NVIDIA I/O base address: 0x%x.\n", io_base_addr); + msg_pinfo("Detected NVIDIA I/O base address: 0x%"PRIx32".\n", io_base_addr); bar = rphysmap("NVIDIA", io_base_addr, GFXNVIDIA_MEMMAP_SIZE); if (bar == ERROR_PTR) diff --git a/hwaccess_physmap.c b/hwaccess_physmap.c index 81adf18e9..f95b5f647 100644 --- a/hwaccess_physmap.c +++ b/hwaccess_physmap.c @@ -121,7 +121,7 @@ static void sys_physunmap_unaligned(void *virt_addr, size_t len) #define MEM_DEV "" -void *sys_physmap(uintptr_t phys_addr, size_t len) +static void *sys_physmap(uintptr_t phys_addr, size_t len) { return (void *)phys_to_virt(phys_addr); } diff --git a/hwaccess_x86_io.c b/hwaccess_x86_io.c index c3ad31396..70b743959 100644 --- a/hwaccess_x86_io.c +++ b/hwaccess_x86_io.c @@ -58,14 +58,16 @@ #define USE_IOPERM 9 #if defined(__ANDROID__) -#include +#include +#include -#define IO_PORT_PERMISSION USE_IOPL -#define IO_PORT_FUNCTION USE_LIBC_TARGET_LAST +#define IO_PORT_PERMISSION USE_IOPERM +#define IO_PORT_FUNCTION USE_ASM #endif #if defined(__linux__) && !defined(__ANDROID__) #include +#include #define IO_PORT_PERMISSION USE_IOPL #define IO_PORT_FUNCTION USE_LIBC_TARGET_LAST @@ -134,6 +136,8 @@ #endif #if defined(__LIBPAYLOAD__) +#include + #define IO_PORT_PERMISSION USE_DUMMY #define IO_PORT_FUNCTION USE_LIBC_TARGET_LAST #endif @@ -261,13 +265,24 @@ int rget_io_perms(void) register_shutdown(platform_release_io_perms, NULL); return 0; } + msg_perr("ERROR: Could not get I/O privileges (%s).\n", strerror(errno)); - msg_perr("Make sure you are root. If you are root, your kernel may still\n" - "prevent access based on security policies.\n"); +#if defined(__linux__) && !defined(__ANDROID__) + if (getuid() != 0) { + msg_perr("Make sure you are running flashrom with root privileges.\n"); + } else { + msg_perr("Your kernel may prevent access based on security policies.\n" + "Issue a 'dmesg | grep flashrom' for further information\n"); + } +#elif defined(__OpenBSD__) msg_perr("On OpenBSD set securelevel=-1 in /etc/rc.securelevel and\n" "reboot, or reboot into single user mode.\n"); +#elif defined(__NetBSD__) msg_perr("On NetBSD reboot into single user mode or make sure\n" "that your kernel configuration has the option INSECURE enabled.\n"); +#else + msg_perr("Make sure you are running flashrom with root privileges.\n"); +#endif return 1; } diff --git a/ich_descriptors.c b/ich_descriptors.c index 416b610cc..c436fabd3 100644 --- a/ich_descriptors.c +++ b/ich_descriptors.c @@ -44,12 +44,14 @@ ssize_t ich_number_of_regions(const enum ich_chipset cs, const struct ich_desc_c case CHIPSET_GEMINI_LAKE: return 6; case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_300_SERIES_CANNON_POINT: case CHIPSET_400_SERIES_COMET_POINT: case CHIPSET_500_SERIES_TIGER_POINT: case CHIPSET_600_SERIES_ALDER_POINT: case CHIPSET_700_SERIES_RAPTOR_POINT: case CHIPSET_METEOR_LAKE: + case CHIPSET_PANTHER_LAKE: case CHIPSET_ELKHART_LAKE: case CHIPSET_JASPER_LAKE: return 16; @@ -76,10 +78,12 @@ ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_c { switch (cs) { case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_APOLLO_LAKE: case CHIPSET_600_SERIES_ALDER_POINT: case CHIPSET_700_SERIES_RAPTOR_POINT: case CHIPSET_METEOR_LAKE: + case CHIPSET_PANTHER_LAKE: case CHIPSET_GEMINI_LAKE: case CHIPSET_JASPER_LAKE: case CHIPSET_ELKHART_LAKE: @@ -96,13 +100,13 @@ ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_c void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl) { - print(verbosity, "BES=0x%x, ", (reg_val & VSCC_BES) >> VSCC_BES_OFF); - print(verbosity, "WG=%d, ", (reg_val & VSCC_WG) >> VSCC_WG_OFF); - print(verbosity, "WSR=%d, ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF); - print(verbosity, "WEWS=%d, ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF); - print(verbosity, "EO=0x%x", (reg_val & VSCC_EO) >> VSCC_EO_OFF); + print(verbosity, "BES=0x%"PRIx32", ", (reg_val & VSCC_BES) >> VSCC_BES_OFF); + print(verbosity, "WG=%"PRId32", ", (reg_val & VSCC_WG) >> VSCC_WG_OFF); + print(verbosity, "WSR=%"PRId32", ", (reg_val & VSCC_WSR) >> VSCC_WSR_OFF); + print(verbosity, "WEWS=%"PRId32", ", (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF); + print(verbosity, "EO=0x%"PRIx32"", (reg_val & VSCC_EO) >> VSCC_EO_OFF); if (print_vcl) - print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF); + print(verbosity, ", VCL=%"PRId32"", (reg_val & VSCC_VCL) >> VSCC_VCL_OFF); print(verbosity, "\n"); } @@ -119,9 +123,10 @@ void prettyprint_ich_chipset(enum ich_chipset cs) "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point", "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg", "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point", - "C620 series Lewisburg", "300 series Cannon Point", "400 series Comet Point", - "500 series Tiger Point", "600 series Alder Point", "Meteor Lake", + "C620 series Lewisburg", "C740 series Emmitsburg", "300 series Cannon Point", + "400 series Comet Point", "500 series Tiger Point", "600 series Alder Point", "Apollo Lake", "Gemini Lake", "Jasper Lake", "Elkhart Lake", + "Meteor Lake", "Panther Lake", }; if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names)) cs = 0; @@ -147,23 +152,23 @@ void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descripto void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_desc_content *cont) { msg_pdbg2("=== Content Section ===\n"); - msg_pdbg2("FLVALSIG 0x%08x\n", cont->FLVALSIG); - msg_pdbg2("FLMAP0 0x%08x\n", cont->FLMAP0); - msg_pdbg2("FLMAP1 0x%08x\n", cont->FLMAP1); - msg_pdbg2("FLMAP2 0x%08x\n", cont->FLMAP2); + msg_pdbg2("FLVALSIG 0x%08"PRIx32"\n", cont->FLVALSIG); + msg_pdbg2("FLMAP0 0x%08"PRIx32"\n", cont->FLMAP0); + msg_pdbg2("FLMAP1 0x%08"PRIx32"\n", cont->FLMAP1); + msg_pdbg2("FLMAP2 0x%08"PRIx32"\n", cont->FLMAP2); msg_pdbg2("\n"); msg_pdbg2("--- Details ---\n"); msg_pdbg2("NR (Number of Regions): %5zd\n", ich_number_of_regions(cs, cont)); - msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont)); + msg_pdbg2("FRBA (Flash Region Base Address): 0x%03"PRIx32"\n", getFRBA(cont)); msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1); - msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont)); + msg_pdbg2("FCBA (Flash Component Base Address): 0x%03"PRIx32"\n", getFCBA(cont)); msg_pdbg2("ISL (ICH/PCH/SoC Strap Length): %5d\n", cont->ISL); - msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH/SoC Strap Base Addr): 0x%03x\n", getFISBA(cont)); + msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH/SoC Strap Base Addr): 0x%03"PRIx32"\n", getFISBA(cont)); msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont)); - msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont)); + msg_pdbg2("FMBA (Flash Master Base Address): 0x%03"PRIx32"\n", getFMBA(cont)); msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL); - msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03x\n", getFMSBA(cont)); + msg_pdbg2("FMSBA (Flash MCH/PROC Strap Base Address): 0x%03"PRIx32"\n", getFMSBA(cont)); msg_pdbg2("\n"); } @@ -213,12 +218,14 @@ static const char *pprint_density(enum ich_chipset cs, const struct ich_descript case CHIPSET_9_SERIES_WILDCAT_POINT_LP: case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_300_SERIES_CANNON_POINT: case CHIPSET_400_SERIES_COMET_POINT: case CHIPSET_500_SERIES_TIGER_POINT: case CHIPSET_600_SERIES_ALDER_POINT: case CHIPSET_700_SERIES_RAPTOR_POINT: case CHIPSET_METEOR_LAKE: + case CHIPSET_PANTHER_LAKE: case CHIPSET_APOLLO_LAKE: case CHIPSET_GEMINI_LAKE: case CHIPSET_JASPER_LAKE: @@ -317,7 +324,9 @@ static const char *pprint_freq(enum ich_chipset cs, uint8_t value) case CHIPSET_500_SERIES_TIGER_POINT: case CHIPSET_600_SERIES_ALDER_POINT: case CHIPSET_700_SERIES_RAPTOR_POINT: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_METEOR_LAKE: + case CHIPSET_PANTHER_LAKE: return freq_str[3][value]; case CHIPSET_ELKHART_LAKE: return freq_str[4][value]; @@ -361,12 +370,14 @@ void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_ switch (cs) { case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_300_SERIES_CANNON_POINT: case CHIPSET_400_SERIES_COMET_POINT: case CHIPSET_500_SERIES_TIGER_POINT: case CHIPSET_600_SERIES_ALDER_POINT: case CHIPSET_700_SERIES_RAPTOR_POINT: case CHIPSET_METEOR_LAKE: + case CHIPSET_PANTHER_LAKE: case CHIPSET_APOLLO_LAKE: case CHIPSET_GEMINI_LAKE: case CHIPSET_JASPER_LAKE: @@ -379,10 +390,10 @@ void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_ } msg_pdbg2("=== Component Section ===\n"); - msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP); - msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL ); + msg_pdbg2("FLCOMP 0x%08"PRIx32"\n", desc->component.FLCOMP); + msg_pdbg2("FLILL 0x%08"PRIx32"\n", desc->component.FLILL ); if (has_flill1) - msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1); + msg_pdbg2("FLILL1 0x%08"PRIx32"\n", desc->component.FLILL1); msg_pdbg2("\n"); msg_pdbg2("--- Details ---\n"); @@ -439,7 +450,7 @@ static void pprint_freg(const struct ich_desc_region *reg, uint32_t i) { static const char *const region_names[] = { "Descr.", "BIOS", "ME", "GbE", "Platf.", "DevExp", "BIOS2", "unknown", - "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown" + "EC/BMC", "unknown", "IE", "10GbE0", "10GbE1", "unknown", "unknown", "PTT" }; if (i >= ARRAY_SIZE(region_names)) { msg_pdbg2("%s: region index too high.\n", __func__); @@ -447,11 +458,11 @@ static void pprint_freg(const struct ich_desc_region *reg, uint32_t i) } uint32_t base = ICH_FREG_BASE(reg->FLREGs[i]); uint32_t limit = ICH_FREG_LIMIT(reg->FLREGs[i]); - msg_pdbg2("Region %d (%-7s) ", i, region_names[i]); + msg_pdbg2("Region %"PRId32" (%-7s) ", i, region_names[i]); if (base > limit) msg_pdbg2("is unused.\n"); else - msg_pdbg2("0x%08x - 0x%08x\n", base, limit); + msg_pdbg2("0x%08"PRIx32" - 0x%08"PRIx32"\n", base, limit); } void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct ich_descriptors *const desc) @@ -465,7 +476,7 @@ void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct i return; } for (i = 0; i < nr; i++) - msg_pdbg2("FLREG%zd 0x%08x\n", i, desc->region.FLREGs[i]); + msg_pdbg2("FLREG%zd 0x%08"PRIx32"\n", i, desc->region.FLREGs[i]); msg_pdbg2("\n"); msg_pdbg2("--- Details ---\n"); @@ -477,15 +488,27 @@ void prettyprint_ich_descriptor_region(const enum ich_chipset cs, const struct i void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct ich_descriptors *const desc) { ssize_t i; - const ssize_t nm = ich_number_of_masters(cs, &desc->content); + ssize_t nm = ich_number_of_masters(cs, &desc->content); msg_pdbg2("=== Master Section ===\n"); if (nm < 0) { msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM + 1); return; } + if (cs == CHIPSET_C740_SERIES_EMMITSBURG) { + /* + * The SPI programming guide says there are 6 masters (thus NM=6), but it + * can only name 5. If there's a 6th then it's undocumented. + * However the first 5 are matching '500 Series PCH' and since C740 is a + * 500 Series clone, this field probably was not updated when writing the + * document. + * Hardcode to 5 to be compatible with '500 Series PCH' below. + */ + nm = 5; + } for (i = 0; i < nm; i++) - msg_pdbg2("FLMSTR%zd 0x%08x\n", i + 1, desc->master.FLMSTRs[i]); + msg_pdbg2("FLMSTR%zd 0x%08"PRIx32"\n", i + 1, desc->master.FLMSTRs[i]); + msg_pdbg2("\n"); msg_pdbg2("--- Details ---\n"); @@ -495,35 +518,38 @@ void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct i cs == CHIPSET_500_SERIES_TIGER_POINT || cs == CHIPSET_600_SERIES_ALDER_POINT || cs == CHIPSET_700_SERIES_RAPTOR_POINT || - cs == CHIPSET_JASPER_LAKE || cs == CHIPSET_METEOR_LAKE) { + cs == CHIPSET_C740_SERIES_EMMITSBURG || + cs == CHIPSET_JASPER_LAKE || + cs == CHIPSET_METEOR_LAKE || + cs == CHIPSET_PANTHER_LAKE) { const char *const master_names[] = { - "BIOS", "ME", "GbE", "unknown", "EC", + "BIOS", "ME", "GbE", "DevE", "EC", }; - if (nm >= (ssize_t)ARRAY_SIZE(master_names)) { - msg_pdbg2("%s: number of masters too high (%d).\n", __func__, - desc->content.NM + 1); + + if (nm > (ssize_t)ARRAY_SIZE(master_names)) { + msg_pdbg2("%s: number of masters too high (%zd).\n", __func__, nm); return; } size_t num_regions; - msg_pdbg2(" FD BIOS ME GbE Pltf Reg5 Reg6 Reg7 EC Reg9"); + msg_pdbg2(" FD BIOS ME GbE Pltf DE BIOS2 Reg7 EC DE2 "); if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) { num_regions = 10; msg_pdbg2("\n"); } else { num_regions = 16; - msg_pdbg2(" RegA RegB RegC RegD RegE RegF\n"); + msg_pdbg2(" IE 10GbE0 10GbE1 RegD RegE PTT \n"); } for (i = 0; i < nm; i++) { const unsigned int ext_region_start = 12; size_t j; msg_pdbg2("%-4s", master_names[i]); for (j = 0; j < (size_t)min(num_regions, ext_region_start); j++) - msg_pdbg2(" %c%c ", + msg_pdbg2(" %c%c ", desc->master.mstr[i].read & (1 << j) ? 'r' : ' ', desc->master.mstr[i].write & (1 << j) ? 'w' : ' '); for (j = ext_region_start; j < num_regions; j++) - msg_pdbg2(" %c%c ", + msg_pdbg2(" %c%c ", desc->master.mstr[i].ext_read & (1 << (j - ext_region_start)) ? 'r' : ' ', desc->master.mstr[i].ext_write & (1 << (j - ext_region_start)) ? 'w' : ' '); msg_pdbg2("\n"); @@ -918,7 +944,7 @@ void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_des msg_pdbg2("--- North/MCH/PROC (%d entries) ---\n", max_count); for (i = 0; i < max_count; i++) - msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->north.STRPs[i]); + msg_pdbg2("STRP%-2d = 0x%08"PRIx32"\n", i, desc->north.STRPs[i]); msg_pdbg2("\n"); max_count = MIN(ARRAY_SIZE(desc->south.STRPs), desc->content.ISL); @@ -930,7 +956,7 @@ void prettyprint_ich_descriptor_straps(enum ich_chipset cs, const struct ich_des msg_pdbg2("--- South/ICH/PCH (%d entries) ---\n", max_count); for (i = 0; i < max_count; i++) - msg_pdbg2("STRP%-2d = 0x%08x\n", i, desc->south.STRPs[i]); + msg_pdbg2("STRP%-2d = 0x%08"PRIx32"\n", i, desc->south.STRPs[i]); msg_pdbg2("\n"); switch (cs) { @@ -976,20 +1002,20 @@ void prettyprint_ich_descriptor_upper_map(const struct ich_desc_upper_map *umap) { int i; msg_pdbg2("=== Upper Map Section ===\n"); - msg_pdbg2("FLUMAP1 0x%08x\n", umap->FLUMAP1); + msg_pdbg2("FLUMAP1 0x%08"PRIx32"\n", umap->FLUMAP1); msg_pdbg2("\n"); msg_pdbg2("--- Details ---\n"); msg_pdbg2("VTL (length in DWORDS) = %d\n", umap->VTL); - msg_pdbg2("VTBA (base address) = 0x%6.6x\n", getVTBA(umap)); + msg_pdbg2("VTBA (base address) = 0x%6.6"PRIx32"\n", getVTBA(umap)); msg_pdbg2("\n"); msg_pdbg2("VSCC Table: %d entries\n", umap->VTL/2); for (i = 0; i < umap->VTL/2; i++) { uint32_t jid = umap->vscc_table[i].JID; uint32_t vscc = umap->vscc_table[i].VSCC; - msg_pdbg2(" JID%d = 0x%08x\n", i, jid); - msg_pdbg2(" VSCC%d = 0x%08x\n", i, vscc); + msg_pdbg2(" JID%d = 0x%08"PRIx32"\n", i, jid); + msg_pdbg2(" VSCC%d = 0x%08"PRIx32"\n", i, vscc); msg_pdbg2(" "); /* indentation */ prettyprint_rdid(jid); msg_pdbg2(" "); /* indentation */ @@ -1027,8 +1053,8 @@ static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_con warn_peculiar_desc("Gemini Lake"); return CHIPSET_GEMINI_LAKE; } - if (content->ISL <= 80) - return CHIPSET_C620_SERIES_LEWISBURG; + if (content->ISL == 0x50) + return CHIPSET_C740_SERIES_EMMITSBURG; warn_peculiar_desc("Ibex Peak"); return CHIPSET_5_SERIES_IBEX_PEAK; } else if (upper->MDTBA == 0x00) { @@ -1070,6 +1096,8 @@ static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_con return CHIPSET_JASPER_LAKE; else if (content->CSSO == 0x70) return CHIPSET_METEOR_LAKE; + else if (content->CSSO == 0x60) + return CHIPSET_PANTHER_LAKE; } msg_pwarn("Unknown flash descriptor, assuming 500 series compatibility.\n"); return CHIPSET_500_SERIES_TIGER_POINT; @@ -1095,6 +1123,7 @@ static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const c case CHIPSET_600_SERIES_ALDER_POINT: case CHIPSET_700_SERIES_RAPTOR_POINT: case CHIPSET_METEOR_LAKE: + case CHIPSET_PANTHER_LAKE: case CHIPSET_GEMINI_LAKE: case CHIPSET_JASPER_LAKE: case CHIPSET_ELKHART_LAKE: @@ -1102,6 +1131,7 @@ static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const c break; case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_APOLLO_LAKE: if (component->modes.freq_read != 6) { msg_pwarn("\nThe flash descriptor looks like a Skylake/Sunrise Point descriptor.\n" @@ -1249,12 +1279,14 @@ int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors case CHIPSET_9_SERIES_WILDCAT_POINT_LP: case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_300_SERIES_CANNON_POINT: case CHIPSET_400_SERIES_COMET_POINT: case CHIPSET_500_SERIES_TIGER_POINT: case CHIPSET_600_SERIES_ALDER_POINT: case CHIPSET_700_SERIES_RAPTOR_POINT: case CHIPSET_METEOR_LAKE: + case CHIPSET_PANTHER_LAKE: case CHIPSET_APOLLO_LAKE: case CHIPSET_GEMINI_LAKE: case CHIPSET_JASPER_LAKE: @@ -1295,12 +1327,14 @@ static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16 switch (cs) { case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_300_SERIES_CANNON_POINT: case CHIPSET_400_SERIES_COMET_POINT: case CHIPSET_500_SERIES_TIGER_POINT: case CHIPSET_600_SERIES_ALDER_POINT: case CHIPSET_700_SERIES_RAPTOR_POINT: case CHIPSET_METEOR_LAKE: + case CHIPSET_PANTHER_LAKE: case CHIPSET_APOLLO_LAKE: case CHIPSET_GEMINI_LAKE: case CHIPSET_JASPER_LAKE: diff --git a/ichspi.c b/ichspi.c index f50654784..591884e0d 100644 --- a/ichspi.c +++ b/ichspi.c @@ -46,9 +46,15 @@ * however we still treat them separately in order to reuse code. */ -/* Changed HSFC Control bits */ /* - * 4 bits to represents the FCYCLE operation for PCH as: + * HSFC Control bits + * + * FCYCLE is a 2 bit field (HSFC bits 1-2) on ICH9 and 4 bit field + * (HSFC bits 1-4) on PCH100. + * + * ICH9 and PCH100 use the same FCYCLE values for flash operations, + * however FCYCLE values above 3 are only supported by PCH100. + * * 0: SPI Read * 2: SPI Write * 3: SPI Erase 4K @@ -56,9 +62,21 @@ * 6: SPI RDID * 7: SPI Write Status * 8: SPI Read Status - */ + */ +#define HSFC_FGO_OFF 0 +#define HSFC_FGO (0x1 << HSFC_FGO_OFF) +#define HSFC_FCYCLE_MASK(n) ((n) << HSFC_FCYCLE_OFF) +#define HSFC_FCYCLE_OFF 1 +#define HSFC_CYCLE_READ HSFC_FCYCLE_MASK(0x0) +#define HSFC_CYCLE_WRITE HSFC_FCYCLE_MASK(0x2) +#define HSFC_CYCLE_BLOCK_ERASE HSFC_FCYCLE_MASK(0x3) +#define HSFC_CYCLE_RDID HSFC_FCYCLE_MASK(0x6) +#define HSFC_CYCLE_WR_STATUS HSFC_FCYCLE_MASK(0x7) +#define HSFC_CYCLE_RD_STATUS HSFC_FCYCLE_MASK(0x8) + +/* PCH100 controller register definition */ +#define PCH100_HSFC_FCYCLE_OFF 1 #define PCH100_HSFC_FCYCLE_BIT_WIDTH 0xf -#define PCH100_HSFC_FCYCLE_OFF (17 - 16) /* 1-4: FLASH Cycle */ #define PCH100_HSFC_FCYCLE HSFC_FCYCLE_MASK(PCH100_HSFC_FCYCLE_BIT_WIDTH) /* New HSFC Control bit */ #define PCH100_HSFC_WET_OFF (21 - 16) /* 5: Write Enable Type */ @@ -117,23 +135,12 @@ #define HSFS_FLOCKDN (0x1 << HSFS_FLOCKDN_OFF) #define ICH9_REG_HSFC 0x06 /* 16 Bits Hardware Sequencing Flash Control */ -#define HSFC_FGO_OFF 0 /* 0: Flash Cycle Go */ -#define HSFC_FGO (0x1 << HSFC_FGO_OFF) -/* - * 2 bits to represents the FCYCLE operation for ICH9 as: - * 0: SPI Read - * 2: SPI Write - * 3: SPI Block Erase - */ + + /* 0: Flash Cycle Go */ + /* 1-2: FLASH Cycle */ +#define ICH9_HSFC_FCYCLE_OFF 1 #define ICH9_HSFC_FCYCLE_BIT_WIDTH 3 -#define HSFC_FCYCLE_OFF 1 /* 1-2: FLASH Cycle */ -#define HSFC_FCYCLE_MASK(n) ((n) << HSFC_FCYCLE_OFF) -#define HSFC_FCYCLE HSFC_FCYCLE_MASK(ICH9_HSFC_FCYCLE_BIT_WIDTH) -#define HSFC_CYCLE_READ HSFC_FCYCLE_MASK(0) -#define HSFC_CYCLE_WRITE HSFC_FCYCLE_MASK(2) -#define HSFC_CYCLE_BLOCK_ERASE HSFC_FCYCLE_MASK(3) -#define HSFC_CYCLE_WR_STATUS HSFC_FCYCLE_MASK(7) -#define HSFC_CYCLE_RD_STATUS HSFC_FCYCLE_MASK(8) +#define ICH9_HSFC_FCYCLE HSFC_FCYCLE_MASK(ICH9_HSFC_FCYCLE_BIT_WIDTH) /* 3-7: reserved */ #define HSFC_FDBC_OFF 8 /* 8-13: Flash Data Byte Count */ #define HSFC_FDBC (0x3f << HSFC_FDBC_OFF) @@ -146,6 +153,9 @@ #define ICH9_FADDR_FLA 0x01ffffff #define ICH9_REG_FDATA0 0x10 /* 64 Bytes */ +#define ICH_REG_BIOS_BM_RAP 0x118 /* 16 Bits BIOS Master Read Access Permissions */ +#define ICH_REG_BIOS_BM_WAP 0x11c /* 16 Bits BIOS Master Write Access Permissions */ + #define ICH9_REG_FRAP 0x50 /* 32 Bytes Flash Region Access Permissions */ #define ICH9_REG_FREG0 0x54 /* 32 Bytes Flash Region 0 */ @@ -389,7 +399,7 @@ static OPCODES O_ST_M25P = { * It is used to reprogram the chipset OPCODE table on-the-fly if an opcode * is needed which is currently not in the chipset OPCODE table */ -static OPCODE POSSIBLE_OPCODES[] = { +static const OPCODE POSSIBLE_OPCODES[] = { {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Write Byte {JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Data {JEDEC_BE_D8, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Erase Sector @@ -438,62 +448,66 @@ static void prettyprint_opcodes(OPCODES *ops) ops->preop[1]); } -#define pprint_reg(reg, bit, val, sep) msg_pdbg("%s=%d" sep, #bit, (val & reg##_##bit) >> reg##_##bit##_OFF) +#define pprint_reg16(reg, bit, val, sep) msg_pdbg("%s=%"PRId16"" sep, #bit, (val & reg##_##bit) >> reg##_##bit##_OFF) +#define pprint_reg32(reg, bit, val, sep) msg_pdbg("%s=%"PRId32"" sep, #bit, (val & reg##_##bit) >> reg##_##bit##_OFF) static void prettyprint_ich9_reg_hsfs(uint16_t reg_val, enum ich_chipset ich_gen) { msg_pdbg("HSFS: "); - pprint_reg(HSFS, FDONE, reg_val, ", "); - pprint_reg(HSFS, FCERR, reg_val, ", "); - pprint_reg(HSFS, AEL, reg_val, ", "); + pprint_reg16(HSFS, FDONE, reg_val, ", "); + pprint_reg16(HSFS, FCERR, reg_val, ", "); + pprint_reg16(HSFS, AEL, reg_val, ", "); switch (ich_gen) { case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_300_SERIES_CANNON_POINT: case CHIPSET_400_SERIES_COMET_POINT: case CHIPSET_500_SERIES_TIGER_POINT: case CHIPSET_ELKHART_LAKE: break; default: - pprint_reg(HSFS, BERASE, reg_val, ", "); + pprint_reg16(HSFS, BERASE, reg_val, ", "); break; } - pprint_reg(HSFS, SCIP, reg_val, ", "); + pprint_reg16(HSFS, SCIP, reg_val, ", "); switch (ich_gen) { case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_300_SERIES_CANNON_POINT: case CHIPSET_400_SERIES_COMET_POINT: case CHIPSET_500_SERIES_TIGER_POINT: case CHIPSET_ELKHART_LAKE: - pprint_reg(HSFS, PRR34_LOCKDN, reg_val, ", "); - pprint_reg(HSFS, WRSDIS, reg_val, ", "); + pprint_reg16(HSFS, PRR34_LOCKDN, reg_val, ", "); + pprint_reg16(HSFS, WRSDIS, reg_val, ", "); break; default: break; } - pprint_reg(HSFS, FDOPSS, reg_val, ", "); - pprint_reg(HSFS, FDV, reg_val, ", "); - pprint_reg(HSFS, FLOCKDN, reg_val, "\n"); + pprint_reg16(HSFS, FDOPSS, reg_val, ", "); + pprint_reg16(HSFS, FDV, reg_val, ", "); + pprint_reg16(HSFS, FLOCKDN, reg_val, "\n"); } static void prettyprint_ich9_reg_hsfc(uint16_t reg_val, enum ich_chipset ich_gen) { #if 0 msg_pdbg("HSFC: "); - pprint_reg(HSFC, FGO, reg_val, ", "); + pprint_reg16(HSFC, FGO, reg_val, ", "); switch (ich_gen) { case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_300_SERIES_CANNON_POINT: case CHIPSET_400_SERIES_COMET_POINT: case CHIPSET_500_SERIES_TIGER_POINT: case CHIPSET_ELKHART_LAKE: - pprint_reg(PCH100_HSFC, FCYCLE, reg_val, ", "); - pprint_reg(PCH100_HSFC, WET, reg_val, ", "); + pprint_reg16(PCH100_HSFC, FCYCLE, reg_val, ", "); + pprint_reg16(PCH100_HSFC, WET, reg_val, ", "); break; default: - pprint_reg(HSFC, FCYCLE, reg_val, ", "); + pprint_reg16(ICH9_HSFC, FCYCLE, reg_val, ", "); break; } pprint_reg(HSFC, FDBC, reg_val, ", "); @@ -504,37 +518,37 @@ static void prettyprint_ich9_reg_hsfc(uint16_t reg_val, enum ich_chipset ich_gen static void prettyprint_ich9_reg_ssfs(uint32_t reg_val) { msg_pdbg("SSFS: "); - pprint_reg(SSFS, SCIP, reg_val, ", "); - pprint_reg(SSFS, FDONE, reg_val, ", "); - pprint_reg(SSFS, FCERR, reg_val, ", "); - pprint_reg(SSFS, AEL, reg_val, "\n"); + pprint_reg32(SSFS, SCIP, reg_val, ", "); + pprint_reg32(SSFS, FDONE, reg_val, ", "); + pprint_reg32(SSFS, FCERR, reg_val, ", "); + pprint_reg32(SSFS, AEL, reg_val, "\n"); } static void prettyprint_ich9_reg_ssfc(uint32_t reg_val) { msg_pdbg("SSFC: "); - pprint_reg(SSFC, SCGO, reg_val, ", "); - pprint_reg(SSFC, ACS, reg_val, ", "); - pprint_reg(SSFC, SPOP, reg_val, ", "); - pprint_reg(SSFC, COP, reg_val, ", "); - pprint_reg(SSFC, DBC, reg_val, ", "); - pprint_reg(SSFC, SME, reg_val, ", "); - pprint_reg(SSFC, SCF, reg_val, "\n"); + pprint_reg32(SSFC, SCGO, reg_val, ", "); + pprint_reg32(SSFC, ACS, reg_val, ", "); + pprint_reg32(SSFC, SPOP, reg_val, ", "); + pprint_reg32(SSFC, COP, reg_val, ", "); + pprint_reg32(SSFC, DBC, reg_val, ", "); + pprint_reg32(SSFC, SME, reg_val, ", "); + pprint_reg32(SSFC, SCF, reg_val, "\n"); } static void prettyprint_pch100_reg_dlock(const uint32_t reg_val) { msg_pdbg("DLOCK: "); - pprint_reg(DLOCK, BMWAG_LOCKDN, reg_val, ", "); - pprint_reg(DLOCK, BMRAG_LOCKDN, reg_val, ", "); - pprint_reg(DLOCK, SBMWAG_LOCKDN, reg_val, ", "); - pprint_reg(DLOCK, SBMRAG_LOCKDN, reg_val, ",\n "); - pprint_reg(DLOCK, PR0_LOCKDN, reg_val, ", "); - pprint_reg(DLOCK, PR1_LOCKDN, reg_val, ", "); - pprint_reg(DLOCK, PR2_LOCKDN, reg_val, ", "); - pprint_reg(DLOCK, PR3_LOCKDN, reg_val, ", "); - pprint_reg(DLOCK, PR4_LOCKDN, reg_val, ",\n "); - pprint_reg(DLOCK, SSEQ_LOCKDN, reg_val, "\n"); + pprint_reg32(DLOCK, BMWAG_LOCKDN, reg_val, ", "); + pprint_reg32(DLOCK, BMRAG_LOCKDN, reg_val, ", "); + pprint_reg32(DLOCK, SBMWAG_LOCKDN, reg_val, ", "); + pprint_reg32(DLOCK, SBMRAG_LOCKDN, reg_val, ",\n "); + pprint_reg32(DLOCK, PR0_LOCKDN, reg_val, ", "); + pprint_reg32(DLOCK, PR1_LOCKDN, reg_val, ", "); + pprint_reg32(DLOCK, PR2_LOCKDN, reg_val, ", "); + pprint_reg32(DLOCK, PR3_LOCKDN, reg_val, ", "); + pprint_reg32(DLOCK, PR4_LOCKDN, reg_val, ",\n "); + pprint_reg32(DLOCK, SSEQ_LOCKDN, reg_val, "\n"); } static struct swseq_data { @@ -586,7 +600,7 @@ static int program_opcodes(OPCODES *op, int enable_undo, enum ich_chipset ich_ge opmenu[1] |= ((uint32_t) op->opcode[a].opcode) << ((a - 4) * 8); } - msg_pdbg2("\n%s: preop=%04x optype=%04x opmenu=%08x%08x\n", __func__, preop, optype, opmenu[0], opmenu[1]); + msg_pdbg2("\n%s: preop=%04x optype=%04x opmenu=%08"PRIx32"%08"PRIx32"\n", __func__, preop, optype, opmenu[0], opmenu[1]); switch (ich_gen) { case CHIPSET_ICH7: case CHIPSET_TUNNEL_CREEK: @@ -649,7 +663,7 @@ static int reprogram_opcode_on_the_fly(uint8_t opcode, unsigned int writecnt, un else // we have an invalid case return SPI_INVALID_LENGTH; } - int oppos = 2; // use original JEDEC_BE_D8 offset + int oppos = 4; // use the original position of JEDEC_REMS curopcodes->opcode[oppos].opcode = opcode; curopcodes->opcode[oppos].spi_type = spi_type; program_opcodes(curopcodes, 0, ich_generation); @@ -708,7 +722,7 @@ static void ich_set_bbar(uint32_t min_addr, enum ich_chipset ich_gen) ichspi_bbar = mmio_readl(ich_spibar + bbar_off) & ~BBAR_MASK; if (ichspi_bbar) { - msg_pdbg("Reserved bits in BBAR not zero: 0x%08x\n", + msg_pdbg("Reserved bits in BBAR not zero: 0x%08"PRIx32"\n", ichspi_bbar); } min_addr &= BBAR_MASK; @@ -720,7 +734,7 @@ static void ich_set_bbar(uint32_t min_addr, enum ich_chipset ich_gen) * failed, the restore will fail as well, so no problem there. */ if (ichspi_bbar != min_addr) - msg_perr("Setting BBAR to 0x%08x failed! New value: 0x%08x.\n", + msg_perr("Setting BBAR to 0x%08"PRIx32" failed! New value: 0x%08"PRIx32".\n", min_addr, ichspi_bbar); } @@ -877,7 +891,7 @@ static int ich7_run_opcode(OPCODE op, uint32_t offset, timeout = 100 * 60; /* 60 ms are 9.6 million cycles at 16 MHz. */ while ((REGREAD16(ICH7_REG_SPIS) & SPIS_SCIP) && --timeout) { - programmer_delay(10); + default_delay(10); } if (!timeout) { msg_perr("Error: SCIP never cleared!\n"); @@ -953,7 +967,7 @@ static int ich7_run_opcode(OPCODE op, uint32_t offset, /* Wait for Cycle Done Status or Flash Cycle Error. */ while (((REGREAD16(ICH7_REG_SPIS) & (SPIS_CDS | SPIS_FCERR)) == 0) && --timeout) { - programmer_delay(10); + default_delay(10); } if (!timeout) { msg_perr("timeout, ICH7_REG_SPIS=0x%04x\n", REGREAD16(ICH7_REG_SPIS)); @@ -993,7 +1007,7 @@ static int ich9_run_opcode(OPCODE op, uint32_t offset, timeout = 100 * 60; /* 60 ms are 9.6 million cycles at 16 MHz. */ while ((REGREAD8(swseq_data.reg_ssfsc) & SSFS_SCIP) && --timeout) { - programmer_delay(10); + default_delay(10); } if (!timeout) { msg_perr("Error: SCIP never cleared!\n"); @@ -1073,10 +1087,10 @@ static int ich9_run_opcode(OPCODE op, uint32_t offset, /* Wait for Cycle Done Status or Flash Cycle Error. */ while (((REGREAD32(swseq_data.reg_ssfsc) & (SSFS_FDONE | SSFS_FCERR)) == 0) && --timeout) { - programmer_delay(10); + default_delay(10); } if (!timeout) { - msg_perr("timeout, REG_SSFS=0x%08x\n", REGREAD32(swseq_data.reg_ssfsc)); + msg_perr("timeout, REG_SSFS=0x%08"PRIx32"\n", REGREAD32(swseq_data.reg_ssfsc)); return 1; } @@ -1225,7 +1239,7 @@ static int ich_spi_send_command(const struct flashctx *flash, unsigned int write if (addr < valid_base || addr_end < addr || /* integer overflow check */ addr_end > valid_end) { - msg_perr("%s: Addressed region 0x%06x-0x%06x not in allowed range 0x%06x-0x%06x\n", + msg_perr("%s: Addressed region 0x%06"PRIx32"-0x%06"PRIx32" not in allowed range 0x%06"PRIx32"-0x%06"PRIx32"\n", __func__, addr, addr_end - 1, valid_base, valid_end - 1); return SPI_INVALID_ADDRESS; } @@ -1237,7 +1251,7 @@ static int ich_spi_send_command(const struct flashctx *flash, unsigned int write msg_pdbg("Running OPCODE 0x%02x failed ", opcode->opcode); if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) || (opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS)) { - msg_pdbg("at address 0x%06x ", addr); + msg_pdbg("at address 0x%06"PRIx32" ", addr); } msg_pdbg("(payload length was %d).\n", count); @@ -1249,7 +1263,7 @@ static int ich_spi_send_command(const struct flashctx *flash, unsigned int write int i; msg_pspew("The data was:\n"); for (i = 0; i < count; i++){ - msg_pspew("%3d: 0x%02x\n", i, data[i]); + msg_pspew("%3d: 0x%02"PRIx8"\n", i, data[i]); } } } @@ -1257,13 +1271,23 @@ static int ich_spi_send_command(const struct flashctx *flash, unsigned int write return result; } -static struct hwseq_data { +#define MAX_FD_REGIONS 16 +struct fd_region { + const char* name; + enum ich_access_protection level; + uint32_t base; + uint32_t limit; +}; + +struct hwseq_data { uint32_t size_comp0; uint32_t size_comp1; uint32_t addr_mask; bool only_4k; uint32_t hsfc_fcycle; -} g_hwseq_data; + + struct fd_region fd_regions[MAX_FD_REGIONS]; +}; static struct hwseq_data *get_hwseq_data_from_context(const struct flashctx *flash) { @@ -1321,13 +1345,13 @@ static int ich_hwseq_wait_for_cycle_complete(unsigned int len, enum ich_chipset while ((((hsfs = REGREAD16(ICH9_REG_HSFS)) & (HSFS_FDONE | HSFS_FCERR)) == 0) && --timeout_us) { - programmer_delay(8); + default_delay(8); } REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS)); if (!timeout_us) { addr = REGREAD32(ICH9_REG_FADDR) & addr_mask; - msg_perr("Timeout error between offset 0x%08x and " - "0x%08x (= 0x%08x + %d)!\n", + msg_perr("Timeout error between offset 0x%08"PRIx32" and " + "0x%08"PRIx32" (= 0x%08"PRIx32" + %d)!\n", addr, addr + len - 1, addr, len - 1); prettyprint_ich9_reg_hsfs(hsfs, ich_gen); prettyprint_ich9_reg_hsfc(REGREAD16(ICH9_REG_HSFC), ich_gen); @@ -1336,8 +1360,8 @@ static int ich_hwseq_wait_for_cycle_complete(unsigned int len, enum ich_chipset if (hsfs & HSFS_FCERR) { addr = REGREAD32(ICH9_REG_FADDR) & addr_mask; - msg_perr("Transaction error between offset 0x%08x and " - "0x%08x (= 0x%08x + %d)!\n", + msg_perr("Transaction error between offset 0x%08"PRIx32" and " + "0x%08"PRIx32" (= 0x%08"PRIx32" + %d)!\n", addr, addr + len - 1, addr, len - 1); prettyprint_ich9_reg_hsfs(hsfs, ich_gen); prettyprint_ich9_reg_hsfc(REGREAD16(ICH9_REG_HSFC), ich_gen); @@ -1347,10 +1371,12 @@ static int ich_hwseq_wait_for_cycle_complete(unsigned int len, enum ich_chipset } /* Fire up a transfer using the hardware sequencer. */ -static void ich_start_hwseq_xfer(uint32_t hsfc_cycle, uint32_t flash_addr, size_t len, +static void ich_start_hwseq_xfer(const struct flashctx *flash, + uint32_t hsfc_cycle, uint32_t flash_addr, size_t len, uint32_t addr_mask) { - uint16_t hsfc; + /* make sure HSFC register is cleared before initiate any operation */ + uint16_t hsfc = 0; /* Sets flash_addr in FADDR */ ich_hwseq_set_addr(flash_addr, addr_mask); @@ -1359,9 +1385,13 @@ static void ich_start_hwseq_xfer(uint32_t hsfc_cycle, uint32_t flash_addr, size_ REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS)); /* Set up transaction parameters. */ - hsfc = REGREAD16(ICH9_REG_HSFC); - hsfc &= ~g_hwseq_data.hsfc_fcycle; /* clear operation */ hsfc |= hsfc_cycle; + /* + * The number of bytes transferred is the value of `FDBC` plus 1, hence, + * subtracted 1 from the length field. + * As per Intel EDS, `0b` in the FDBC represents 1 byte while `0x3f` + * represents 64-bytes to be transferred. + */ hsfc |= HSFC_FDBC_VAL(len - 1); hsfc |= HSFC_FGO; /* start */ prettyprint_ich9_reg_hsfc(hsfc, ich_generation); @@ -1378,7 +1408,7 @@ static int ich_wait_for_hwseq_spi_cycle_complete(void) } /* Execute SPI flash transfer */ -static int ich_exec_sync_hwseq_xfer(uint32_t hsfc_cycle, uint32_t flash_addr, +static int ich_exec_sync_hwseq_xfer(const struct flashctx *flash, uint32_t hsfc_cycle, uint32_t flash_addr, size_t len, enum ich_chipset ich_gen, uint32_t addr_mask) { if (ich_wait_for_hwseq_spi_cycle_complete()) { @@ -1386,22 +1416,93 @@ static int ich_exec_sync_hwseq_xfer(uint32_t hsfc_cycle, uint32_t flash_addr, return 1; } - ich_start_hwseq_xfer(hsfc_cycle, flash_addr, len, addr_mask); + ich_start_hwseq_xfer(flash, hsfc_cycle, flash_addr, len, addr_mask); return ich_hwseq_wait_for_cycle_complete(len, ich_gen, addr_mask); } +static void ich_get_region(const struct flashctx *flash, unsigned int addr, struct flash_region *region) +{ + struct ich_descriptors desc = { 0 }; + const ssize_t nr = ich_number_of_regions(ich_generation, &desc.content); + const struct hwseq_data *hwseq_data = get_hwseq_data_from_context(flash); + const struct fd_region *fd_regions = hwseq_data->fd_regions; + + /* + * Set default values for the region. If no flash descriptor containing + * addr is found, these values will be used instead. + * + * The region start and end are constrained so that they do not overlap + * any flash descriptor regions. + */ + const char *name = ""; + region->read_prot = false; + region->write_prot = false; + region->start = 0; + region->end = flashrom_flash_getsize(flash) - 1; + + for (ssize_t i = 0; i < nr; i++) { + uint32_t base = fd_regions[i].base; + uint32_t limit = fd_regions[i].limit; + enum ich_access_protection level = fd_regions[i].level; + + if (addr < base) { + /* + * fd_regions[i] starts after addr, constrain + * region->end so that it does not overlap. + */ + region->end = min(region->end, base); + } else if (addr > limit) { + /* + * fd_regions[i] ends before addr, constrain + * region->start so that it does not overlap. + */ + region->start = max(region->start, limit + 1); + } else { + /* fd_regions[i] contains addr, copy to *region. */ + name = fd_regions[i].name; + region->start = base; + region->end = limit; + region->read_prot = (level == LOCKED) || (level == READ_PROT); + region->write_prot = (level == LOCKED) || (level == WRITE_PROT); + break; + } + } + + region->name = strdup(name); +} + +/* Given RDID info, return pointer to entry in flashchips[] */ +static const struct flashchip *flash_id_to_entry(uint32_t mfg_id, uint32_t model_id) +{ + const struct flashchip *chip; + + for (chip = &flashchips[0]; chip->vendor; chip++) { + if ((chip->manufacture_id == mfg_id) && + (chip->model_id == model_id) && + (chip->probe == PROBE_SPI_RDID) && + ((chip->bustype & BUS_SPI) == BUS_SPI)) + return chip; + } + + return NULL; +} + static int ich_hwseq_read_status(const struct flashctx *flash, enum flash_reg reg, uint8_t *value) { const int len = 1; const struct hwseq_data *hwseq_data = get_hwseq_data_from_context(flash); if (reg != STATUS1) { - msg_perr("%s: only supports STATUS1\n", __func__); - return -1; + msg_pdbg("%s: only supports STATUS1\n", __func__); + /* + * Return SPI_INVALID_OPCODE to be consistent with spi_read_register() + * and make error handling simpler even though this isn't a SPI master. + */ + return SPI_INVALID_OPCODE; } msg_pdbg("Reading Status register\n"); - if (ich_exec_sync_hwseq_xfer(HSFC_CYCLE_RD_STATUS, 0, len, ich_generation, + if (ich_exec_sync_hwseq_xfer(flash, HSFC_CYCLE_RD_STATUS, 1, len, ich_generation, hwseq_data->addr_mask)) { msg_perr("Reading Status register failed\n!!"); return -1; @@ -1417,14 +1518,18 @@ static int ich_hwseq_write_status(const struct flashctx *flash, enum flash_reg r const struct hwseq_data *hwseq_data = get_hwseq_data_from_context(flash); if (reg != STATUS1) { - msg_perr("%s: only supports STATUS1\n", __func__); - return -1; + msg_pdbg("%s: only supports STATUS1\n", __func__); + /* + * Return SPI_INVALID_OPCODE to be consistent with spi_write_register() + * and make error handling simpler even though this isn't a SPI master. + */ + return SPI_INVALID_OPCODE; } msg_pdbg("Writing status register\n"); ich_fill_data(&value, len, ICH9_REG_FDATA0); - if (ich_exec_sync_hwseq_xfer(HSFC_CYCLE_WR_STATUS, 0, len, ich_generation, + if (ich_exec_sync_hwseq_xfer(flash, HSFC_CYCLE_WR_STATUS, 1, len, ich_generation, hwseq_data->addr_mask)) { msg_perr("Writing Status register failed\n!!"); return -1; @@ -1433,6 +1538,61 @@ static int ich_hwseq_write_status(const struct flashctx *flash, enum flash_reg r return 0; } +static void ich_hwseq_get_flash_id(struct flashctx *flash, enum ich_chipset ich_gen) +{ + const struct hwseq_data *hwseq_data = get_hwseq_data_from_context(flash); + if (hwseq_data->size_comp1 != 0) { + msg_pinfo("Multiple flash components detected, skipping flash identification.\n"); + return; + } + + /* PCH100 or above is required for RDID, ICH9 does not support it. */ + if (hwseq_data->hsfc_fcycle != PCH100_HSFC_FCYCLE) { + msg_pinfo("RDID cycle not supported, skipping flash identification.\n"); + return; + } + + /* + * RDID gives 3 byte output: + * Byte 0: Manufacturer ID + * Byte 1: Model ID (MSB) + * Byte 2: Model ID (LSB) + */ + const int len = 3; + uint8_t data[len]; + + if (ich_exec_sync_hwseq_xfer(flash, HSFC_CYCLE_RDID, 1, len, ich_gen, + hwseq_data->addr_mask)) { + msg_perr("Timed out waiting for RDID to complete.\n"); + } + + ich_read_data(data, len, ICH9_REG_FDATA0); + uint32_t mfg_id = data[0]; + uint32_t model_id = (data[1] << 8) | data[2]; + + const struct flashchip *entry = flash_id_to_entry(mfg_id, model_id); + if (!entry) { + msg_pwarn("Unable to identify chip, mfg_id: 0x%02"PRIx32", " + "model_id: 0x%02"PRIx32"\n", mfg_id, model_id); + return; + } + + msg_pdbg("Chip identified: %s\n", entry->name); + + /* Update informational flash chip entries only */ + flash->chip->vendor = entry->vendor; + flash->chip->name = entry->name; + flash->chip->manufacture_id = entry->manufacture_id; + flash->chip->model_id = entry->model_id; + /* total_size read from flash descriptor */ + flash->chip->page_size = entry->page_size; + flash->chip->feature_bits = entry->feature_bits; + flash->chip->tested = entry->tested; + /* Support writeprotect */ + flash->chip->reg_bits = entry->reg_bits; + flash->chip->decode_range = entry->decode_range; +} + static int ich_hwseq_probe(struct flashctx *flash) { uint32_t total_size, boundary; @@ -1447,7 +1607,7 @@ static int ich_hwseq_probe(struct flashctx *flash) msg_cdbg("s with a combined"); else msg_cdbg(" with a"); - msg_cdbg(" density of %d kB.\n", total_size / 1024); + msg_cdbg(" density of %"PRId32" kB.\n", total_size / 1024); flash->chip->total_size = total_size / 1024; eraser = &(flash->chip->block_erasers[0]); @@ -1460,32 +1620,37 @@ static int ich_hwseq_probe(struct flashctx *flash) if (boundary == 0) { msg_cdbg2("There is only one partition containing the whole " - "address space (0x%06x - 0x%06x).\n", 0, size_high-1); + "address space (0x%06x - 0x%06"PRIx32").\n", 0, size_high-1); eraser->eraseblocks[0].size = erase_size_high; eraser->eraseblocks[0].count = size_high / erase_size_high; - msg_cdbg2("There are %d erase blocks with %d B each.\n", + msg_cdbg2("There are %"PRId32" erase blocks with %"PRId32" B each.\n", size_high / erase_size_high, erase_size_high); } else { - msg_cdbg2("The flash address space (0x%06x - 0x%06x) is divided " - "at address 0x%06x in two partitions.\n", + msg_cdbg2("The flash address space (0x%06x - 0x%06"PRIx32") is divided " + "at address 0x%06"PRIx32" in two partitions.\n", 0, total_size-1, boundary); size_low = total_size - size_high; erase_size_low = ich_hwseq_get_erase_block_size(0, hwseq_data->addr_mask, hwseq_data->only_4k); eraser->eraseblocks[0].size = erase_size_low; eraser->eraseblocks[0].count = size_low / erase_size_low; - msg_cdbg("The first partition ranges from 0x%06x to 0x%06x.\n", 0, size_low-1); - msg_cdbg("In that range are %d erase blocks with %d B each.\n", + msg_cdbg("The first partition ranges from 0x%06x to 0x%06"PRIx32".\n", 0, size_low-1); + msg_cdbg("In that range are %"PRId32" erase blocks with %"PRId32" B each.\n", size_low / erase_size_low, erase_size_low); eraser->eraseblocks[1].size = erase_size_high; eraser->eraseblocks[1].count = size_high / erase_size_high; - msg_cdbg("The second partition ranges from 0x%06x to 0x%06x.\n", + msg_cdbg("The second partition ranges from 0x%06"PRIx32" to 0x%06"PRIx32".\n", boundary, total_size-1); - msg_cdbg("In that range are %d erase blocks with %d B each.\n", + msg_cdbg("In that range are %"PRId32" erase blocks with %"PRId32" B each.\n", size_high / erase_size_high, erase_size_high); } - flash->chip->tested = TEST_OK_PREW; + + /* May be overwritten by ich_hwseq_get_flash_id(). */ + flash->chip->tested = TEST_OK_PREWB; + + ich_hwseq_get_flash_id(flash, ich_generation); + return 1; } @@ -1497,7 +1662,7 @@ static int ich_hwseq_block_erase(struct flashctx *flash, unsigned int addr, erase_block = ich_hwseq_get_erase_block_size(addr, hwseq_data->addr_mask, hwseq_data->only_4k); if (len != erase_block) { - msg_cerr("Erase block size for address 0x%06x is %d B, " + msg_cerr("Erase block size for address 0x%06x is %"PRId32" B, " "but requested erase block size is %d B. " "Not erasing anything.\n", addr, erase_block, len); return -1; @@ -1507,7 +1672,7 @@ static int ich_hwseq_block_erase(struct flashctx *flash, unsigned int addr, * containing the address) we play safe here. */ if (addr % erase_block != 0) { msg_cerr("Erase address 0x%06x is not aligned to the erase " - "block boundary (any multiple of %d). " + "block boundary (any multiple of %"PRId32"). " "Not erasing anything.\n", addr, erase_block); return -1; } @@ -1520,7 +1685,7 @@ static int ich_hwseq_block_erase(struct flashctx *flash, unsigned int addr, msg_pdbg("Erasing %d bytes starting at 0x%06x.\n", len, addr); - if (ich_exec_sync_hwseq_xfer(HSFC_CYCLE_BLOCK_ERASE, addr, 0, ich_generation, + if (ich_exec_sync_hwseq_xfer(flash, HSFC_CYCLE_BLOCK_ERASE, addr, 1, ich_generation, hwseq_data->addr_mask)) return -1; return 0; @@ -1548,7 +1713,7 @@ static int ich_hwseq_read(struct flashctx *flash, uint8_t *buf, /* as well as flash chip page borders as demanded in the Intel datasheets. */ block_len = min(block_len, 256 - (addr & 0xFF)); - if (ich_exec_sync_hwseq_xfer(HSFC_CYCLE_READ, addr, block_len, ich_generation, + if (ich_exec_sync_hwseq_xfer(flash, HSFC_CYCLE_READ, addr, block_len, ich_generation, hwseq_data->addr_mask)) return 1; ich_read_data(buf, block_len, ICH9_REG_FDATA0); @@ -1581,7 +1746,7 @@ static int ich_hwseq_write(struct flashctx *flash, const uint8_t *buf, unsigned block_len = min(block_len, 256 - (addr & 0xFF)); ich_fill_data(buf, block_len, ICH9_REG_FDATA0); - if (ich_exec_sync_hwseq_xfer(HSFC_CYCLE_WRITE, addr, block_len, ich_generation, + if (ich_exec_sync_hwseq_xfer(flash, HSFC_CYCLE_WRITE, addr, block_len, ich_generation, hwseq_data->addr_mask)) return -1; addr += block_len; @@ -1591,6 +1756,12 @@ static int ich_hwseq_write(struct flashctx *flash, const uint8_t *buf, unsigned return 0; } +static int ich_hwseq_shutdown(void *data) +{ + free(data); + return 0; +} + static int ich_spi_send_multicommand(const struct flashctx *flash, struct spi_command *cmds) { @@ -1651,9 +1822,13 @@ static int ich_spi_send_multicommand(const struct flashctx *flash, return ret; } -static bool ich_spi_probe_opcode(struct flashctx *flash, uint8_t opcode) +static bool ich_spi_probe_opcode(const struct flashctx *flash, uint8_t opcode) { - return find_opcode(curopcodes, opcode) >= 0; + int ret = find_opcode(curopcodes, opcode); + if ((ret == -1) && (lookup_spi_type(opcode) <= 3)) + /* opcode is in POSSIBLE_OPCODES, report supported. */ + return true; + return ret >= 0; } #define ICH_BMWAG(x) ((x >> 24) & 0xff) @@ -1668,12 +1843,58 @@ static const char *const access_names[] = { "read-write", "write-only", "read-only", "locked" }; -static enum ich_access_protection ich9_handle_frap(uint32_t frap, unsigned int i) +static void ich_get_bios_region_access(uint16_t *region_read_access, + uint16_t *region_write_access) +{ + uint32_t tmp; + *region_read_access = 0; + *region_write_access = 0; + + if (ich_generation >= CHIPSET_METEOR_LAKE) { + /* + * Starting from Meteor Lake, we need to fetch the region + * read/write access permissions from the BIOS_BM registers + * because we need to support FREG9 or above. + */ + *region_read_access = mmio_readw(ich_spibar + ICH_REG_BIOS_BM_RAP); + *region_write_access = mmio_readw(ich_spibar + ICH_REG_BIOS_BM_WAP); + msg_pdbg("0x118: 0x%04"PRIx16" (BIOS_BM_RAP)\n", *region_read_access); + msg_pdbg("0x11a: 0x%04"PRIx16" (BIOS_BM_WAP)\n", *region_write_access); + } else { + /* + * FRAP - Flash Regions Access Permissions Register + * Bit Descriptions: + * 31:24 BIOS Master Write Access Grant (BMWAG) + * 23:16 BIOS Master Read Access Grant (BMRAG) + * 15:8 BIOS Region Write Access (BRWA) + * 7:0 BIOS Region Read Access (BRRA) + */ + tmp = mmio_readl(ich_spibar + ICH9_REG_FRAP); + msg_pdbg("0x50: 0x%08"PRIx32" (FRAP)\n", tmp); + msg_pdbg("BMWAG 0x%02"PRIx32", ", ICH_BMWAG(tmp)); + msg_pdbg("BMRAG 0x%02"PRIx32", ", ICH_BMRAG(tmp)); + msg_pdbg("BRWA 0x%02"PRIx32", ", ICH_BRWA(tmp)); + msg_pdbg("BRRA 0x%02"PRIx32"\n", ICH_BRRA(tmp)); + + *region_read_access = (uint16_t)ICH_BRRA(tmp); + *region_write_access = (uint16_t)ICH_BRWA(tmp); + } +} + +static unsigned int ich_get_defined_region_count(void) { + return (ich_generation >= CHIPSET_METEOR_LAKE) ? 16 : 8; +} + +static enum ich_access_protection ich9_handle_region_access(struct fd_region *fd_regions, + uint16_t region_read_access, + uint16_t region_write_access, + unsigned int i) { static const char *const region_names[] = { "Flash Descriptor", "BIOS", "Management Engine", "Gigabit Ethernet", "Platform Data", "Device Expansion", - "BIOS2", "unknown", "EC/BMC", + "BIOS2", "unknown", "EC/BMC", "Device Expansion 2", + "Innovation Engine", "10GbE0", "10GbE1", "unknown", "unknown", "PTT", }; const char *const region_name = i < ARRAY_SIZE(region_names) ? region_names[i] : "unknown"; @@ -1689,28 +1910,34 @@ static enum ich_access_protection ich9_handle_frap(uint32_t frap, unsigned int i limit = ICH_FREG_LIMIT(freg); if (base > limit || (freg == 0 && i > 0)) { /* this FREG is disabled */ - msg_pdbg2("0x%02X: 0x%08x FREG%u: %s region is unused.\n", + msg_pdbg2("0x%02X: 0x%08"PRIx32" FREG%u: %s region is unused.\n", offset, freg, i, region_name); return NO_PROT; } - msg_pdbg("0x%02X: 0x%08x ", offset, freg); + msg_pdbg("0x%02X: 0x%08"PRIx32" ", offset, freg); - if (i < 8) { - rwperms_idx = (((ICH_BRWA(frap) >> i) & 1) << 1) | - (((ICH_BRRA(frap) >> i) & 1) << 0); + if (i < ich_get_defined_region_count()) { + rwperms_idx = (((region_write_access >> i) & 1) << 1) | + (((region_read_access >> i) & 1) << 0); rwperms = access_perms_to_protection[rwperms_idx]; } else { - /* Datasheets don't define any access bits for regions > 7. We + /* Datasheets might not define all the access bits for regions. We can't rely on the actual descriptor settings either as there are several overrides for them (those by other masters are not even readable by us, *shrug*). */ - msg_pdbg("FREG%u: %s region (0x%08x-0x%08x) has unknown permissions.\n", + msg_pdbg("FREG%u: %s region (0x%08"PRIx32"-0x%08"PRIx32") has unknown permissions.\n", i, region_name, base, limit); return NO_PROT; } - msg_pinfo("FREG%u: %s region (0x%08x-0x%08x) is %s.\n", i, + msg_pinfo("FREG%u: %s region (0x%08"PRIx32"-0x%08"PRIx32") is %s.\n", i, region_name, base, limit, access_names[rwperms]); + /* Save region attributes for use by ich_get_region(). */ + fd_regions[i].base = base; + fd_regions[i].limit = limit; + fd_regions[i].level = rwperms; + fd_regions[i].name = region_name; + return rwperms; } @@ -1736,12 +1963,12 @@ static enum ich_access_protection ich9_handle_pr(const size_t reg_pr0, unsigned i -= 5; if (rwperms == NO_PROT) { - msg_pdbg2("0x%02X: 0x%08x (%sPR%u is unused)\n", off, pr, prefix, i); + msg_pdbg2("0x%02"PRIX8": 0x%08"PRIx32" (%sPR%u is unused)\n", off, pr, prefix, i); return NO_PROT; } - msg_pdbg("0x%02X: 0x%08x ", off, pr); - msg_pwarn("%sPR%u: Warning: 0x%08x-0x%08x is %s.\n", prefix, i, ICH_FREG_BASE(pr), + msg_pdbg("0x%02"PRIX8": 0x%08"PRIx32" ", off, pr); + msg_pwarn("%sPR%u: Warning: 0x%08"PRIx32"-0x%08"PRIx32" is %s.\n", prefix, i, ICH_FREG_BASE(pr), ICH_FREG_LIMIT(pr), access_names[rwperms]); return rwperms; @@ -1755,7 +1982,7 @@ static void ich9_set_pr(const size_t reg_pr0, int i, int read_prot, int write_pr uint32_t old = mmio_readl(addr); uint32_t new; - msg_gspew("PR%u is 0x%08x", i, old); + msg_gspew("PR%u is 0x%08"PRIx32"", i, old); new = old & ~((1 << PR_RP_OFF) | (1 << PR_WP_OFF)); if (read_prot) new |= (1 << PR_RP_OFF); @@ -1765,12 +1992,12 @@ static void ich9_set_pr(const size_t reg_pr0, int i, int read_prot, int write_pr msg_gspew(" already.\n"); return; } - msg_gspew(", trying to set it to 0x%08x ", new); + msg_gspew(", trying to set it to 0x%08"PRIx32" ", new); rmmio_writel(new, addr); - msg_gspew("resulted in 0x%08x.\n", mmio_readl(addr)); + msg_gspew("resulted in 0x%08"PRIx32".\n", mmio_readl(addr)); } -static const struct spi_master spi_master_ich7 = { +static const struct spi_master spi_master_ich = { .max_data_read = 64, .max_data_write = 64, .command = ich_spi_send_command, @@ -1779,19 +2006,6 @@ static const struct spi_master spi_master_ich7 = { .unmap_flash_region = physunmap, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, -}; - -static const struct spi_master spi_master_ich9 = { - .max_data_read = 64, - .max_data_write = 64, - .command = ich_spi_send_command, - .multicommand = ich_spi_send_multicommand, - .map_flash_region = physmap, - .unmap_flash_region = physunmap, - .read = default_spi_read, - .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .probe_opcode = ich_spi_probe_opcode, }; @@ -1804,28 +2018,30 @@ static const struct opaque_master opaque_master_ich_hwseq = { .erase = ich_hwseq_block_erase, .read_register = ich_hwseq_read_status, .write_register = ich_hwseq_write_status, + .get_region = ich_get_region, + .shutdown = ich_hwseq_shutdown, }; static int init_ich7_spi(void *spibar, enum ich_chipset ich_gen) { unsigned int i; - msg_pdbg("0x00: 0x%04x (SPIS)\n", mmio_readw(spibar + 0)); - msg_pdbg("0x02: 0x%04x (SPIC)\n", mmio_readw(spibar + 2)); - msg_pdbg("0x04: 0x%08x (SPIA)\n", mmio_readl(spibar + 4)); + msg_pdbg("0x00: 0x%04"PRIx16" (SPIS)\n", mmio_readw(spibar + 0)); + msg_pdbg("0x02: 0x%04"PRIx16" (SPIC)\n", mmio_readw(spibar + 2)); + msg_pdbg("0x04: 0x%08"PRIx32" (SPIA)\n", mmio_readl(spibar + 4)); ichspi_bbar = mmio_readl(spibar + 0x50); - msg_pdbg("0x50: 0x%08x (BBAR)\n", ichspi_bbar); - msg_pdbg("0x54: 0x%04x (PREOP)\n", mmio_readw(spibar + 0x54)); - msg_pdbg("0x56: 0x%04x (OPTYPE)\n", mmio_readw(spibar + 0x56)); - msg_pdbg("0x58: 0x%08x (OPMENU)\n", mmio_readl(spibar + 0x58)); - msg_pdbg("0x5c: 0x%08x (OPMENU+4)\n", mmio_readl(spibar + 0x5c)); + msg_pdbg("0x50: 0x%08"PRIx32" (BBAR)\n", ichspi_bbar); + msg_pdbg("0x54: 0x%04"PRIx16" (PREOP)\n", mmio_readw(spibar + 0x54)); + msg_pdbg("0x56: 0x%04"PRIx16" (OPTYPE)\n", mmio_readw(spibar + 0x56)); + msg_pdbg("0x58: 0x%08"PRIx32" (OPMENU)\n", mmio_readl(spibar + 0x58)); + msg_pdbg("0x5c: 0x%08"PRIx32" (OPMENU+4)\n", mmio_readl(spibar + 0x5c)); for (i = 0; i < 3; i++) { int offs; offs = 0x60 + (i * 4); - msg_pdbg("0x%02x: 0x%08x (PBR%u)\n", offs, mmio_readl(spibar + offs), i); + msg_pdbg("0x%02x: 0x%08"PRIx32" (PBR%u)\n", offs, mmio_readl(spibar + offs), i); } if (mmio_readw(spibar) & (1 << 15)) { msg_pwarn("WARNING: SPI Configuration Lockdown activated.\n"); @@ -1833,7 +2049,7 @@ static int init_ich7_spi(void *spibar, enum ich_chipset ich_gen) } ich_init_opcodes(ich_gen); ich_set_bbar(0, ich_gen); - register_spi_master(&spi_master_ich7, NULL); + register_spi_master(&spi_master_ich, NULL); return 0; } @@ -1861,11 +2077,11 @@ static int get_ich_spi_mode_param(const struct programmer_cfg *cfg, enum ich_spi } else if (!strlen(arg)) { msg_perr("Missing argument for ich_spi_mode.\n"); free(arg); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } else { msg_perr("Unknown argument for ich_spi_mode: %s\n", arg); free(arg); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } free(arg); @@ -1880,6 +2096,7 @@ static void init_chipset_properties(struct swseq_data *swseq, struct hwseq_data switch (ich_gen) { case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_300_SERIES_CANNON_POINT: case CHIPSET_400_SERIES_COMET_POINT: case CHIPSET_500_SERIES_TIGER_POINT: @@ -1890,6 +2107,7 @@ static void init_chipset_properties(struct swseq_data *swseq, struct hwseq_data case CHIPSET_GEMINI_LAKE: case CHIPSET_JASPER_LAKE: case CHIPSET_ELKHART_LAKE: + case CHIPSET_PANTHER_LAKE: *num_pr = 6; /* Includes GPR0 */ *reg_pr0 = PCH100_REG_FPR0; swseq->reg_ssfsc = PCH100_REG_SSFSC; @@ -1909,7 +2127,7 @@ static void init_chipset_properties(struct swseq_data *swseq, struct hwseq_data swseq->reg_opmenu = ICH9_REG_OPMENU; hwseq->addr_mask = ICH9_FADDR_FLA; hwseq->only_4k = false; - hwseq->hsfc_fcycle = HSFC_FCYCLE; + hwseq->hsfc_fcycle = ICH9_HSFC_FCYCLE; break; } @@ -1918,6 +2136,7 @@ static void init_chipset_properties(struct swseq_data *swseq, struct hwseq_data *num_freg = 10; break; case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: *num_freg = 12; /* 12 MMIO regs, but 16 regions in FD spec */ break; case CHIPSET_300_SERIES_CANNON_POINT: @@ -1930,6 +2149,7 @@ static void init_chipset_properties(struct swseq_data *swseq, struct hwseq_data case CHIPSET_GEMINI_LAKE: case CHIPSET_JASPER_LAKE: case CHIPSET_ELKHART_LAKE: + case CHIPSET_PANTHER_LAKE: *num_freg = 16; break; default: @@ -1948,8 +2168,8 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum struct ich_descriptors desc = { 0 }; enum ich_spi_mode ich_spi_mode = ich_auto; size_t num_freg, num_pr, reg_pr0; - - init_chipset_properties(&swseq_data, &g_hwseq_data, &num_freg, &num_pr, ®_pr0, ich_gen); + struct hwseq_data hwseq_data = { 0 }; + init_chipset_properties(&swseq_data, &hwseq_data, &num_freg, &num_pr, ®_pr0, ich_gen); int ret = get_ich_spi_mode_param(cfg, &ich_spi_mode); if (ret) @@ -1972,16 +2192,17 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum if (desc_valid) { tmp2 = mmio_readw(spibar + ICH9_REG_HSFC); - msg_pdbg("0x06: 0x%04x (HSFC)\n", tmp2); + msg_pdbg("0x06: 0x%04"PRIx16" (HSFC)\n", tmp2); prettyprint_ich9_reg_hsfc(tmp2, ich_gen); } tmp = mmio_readl(spibar + ICH9_REG_FADDR); - msg_pdbg2("0x08: 0x%08x (FADDR)\n", tmp); + msg_pdbg2("0x08: 0x%08"PRIx32" (FADDR)\n", tmp); switch (ich_gen) { case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_300_SERIES_CANNON_POINT: case CHIPSET_400_SERIES_COMET_POINT: case CHIPSET_500_SERIES_TIGER_POINT: @@ -1992,8 +2213,9 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum case CHIPSET_GEMINI_LAKE: case CHIPSET_JASPER_LAKE: case CHIPSET_ELKHART_LAKE: + case CHIPSET_PANTHER_LAKE: tmp = mmio_readl(spibar + PCH100_REG_DLOCK); - msg_pdbg("0x0c: 0x%08x (DLOCK)\n", tmp); + msg_pdbg("0x0c: 0x%08"PRIx32" (DLOCK)\n", tmp); prettyprint_pch100_reg_dlock(tmp); break; default: @@ -2001,16 +2223,15 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum } if (desc_valid) { - tmp = mmio_readl(spibar + ICH9_REG_FRAP); - msg_pdbg("0x50: 0x%08x (FRAP)\n", tmp); - msg_pdbg("BMWAG 0x%02x, ", ICH_BMWAG(tmp)); - msg_pdbg("BMRAG 0x%02x, ", ICH_BMRAG(tmp)); - msg_pdbg("BRWA 0x%02x, ", ICH_BRWA(tmp)); - msg_pdbg("BRRA 0x%02x\n", ICH_BRRA(tmp)); - - /* Handle FREGx and FRAP registers */ + /* Get the region access data from FRAP/BIOS_BM */ + uint16_t region_read_access, region_write_access; + ich_get_bios_region_access(®ion_read_access, ®ion_write_access); + + /* Handle FREGx and region access registers */ for (i = 0; i < num_freg; i++) - ich_spi_rw_restricted |= ich9_handle_frap(tmp, i); + ich_spi_rw_restricted |= ich9_handle_region_access(hwseq_data.fd_regions, + region_read_access, + region_write_access, i); if (ich_spi_rw_restricted) msg_pinfo("Not all flash regions are freely accessible by flashrom. This is " "most likely\ndue to an active ME. Please see " @@ -2040,22 +2261,22 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum } tmp = mmio_readl(spibar + swseq_data.reg_ssfsc); - msg_pdbg("0x%zx: 0x%02x (SSFS)\n", swseq_data.reg_ssfsc, tmp & 0xff); + msg_pdbg("0x%zx: 0x%02"PRIx32" (SSFS)\n", swseq_data.reg_ssfsc, tmp & 0xff); prettyprint_ich9_reg_ssfs(tmp); if (tmp & SSFS_FCERR) { msg_pdbg("Clearing SSFS.FCERR\n"); mmio_writeb(SSFS_FCERR, spibar + swseq_data.reg_ssfsc); } - msg_pdbg("0x%zx: 0x%06x (SSFC)\n", swseq_data.reg_ssfsc + 1, tmp >> 8); + msg_pdbg("0x%zx: 0x%06"PRIx32" (SSFC)\n", swseq_data.reg_ssfsc + 1, tmp >> 8); prettyprint_ich9_reg_ssfc(tmp); - msg_pdbg("0x%zx: 0x%04x (PREOP)\n", + msg_pdbg("0x%zx: 0x%04"PRIx16" (PREOP)\n", swseq_data.reg_preop, mmio_readw(spibar + swseq_data.reg_preop)); - msg_pdbg("0x%zx: 0x%04x (OPTYPE)\n", + msg_pdbg("0x%zx: 0x%04"PRIx16" (OPTYPE)\n", swseq_data.reg_optype, mmio_readw(spibar + swseq_data.reg_optype)); - msg_pdbg("0x%zx: 0x%08x (OPMENU)\n", + msg_pdbg("0x%zx: 0x%08"PRIx32" (OPMENU)\n", swseq_data.reg_opmenu, mmio_readl(spibar + swseq_data.reg_opmenu)); - msg_pdbg("0x%zx: 0x%08x (OPMENU+4)\n", + msg_pdbg("0x%zx: 0x%08"PRIx32" (OPMENU+4)\n", swseq_data.reg_opmenu + 4, mmio_readl(spibar + swseq_data.reg_opmenu + 4)); if (desc_valid) { @@ -2063,6 +2284,7 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum case CHIPSET_ICH8: case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_300_SERIES_CANNON_POINT: case CHIPSET_400_SERIES_COMET_POINT: case CHIPSET_500_SERIES_TIGER_POINT: @@ -2074,27 +2296,28 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum case CHIPSET_JASPER_LAKE: case CHIPSET_BAYTRAIL: case CHIPSET_ELKHART_LAKE: + case CHIPSET_PANTHER_LAKE: break; default: ichspi_bbar = mmio_readl(spibar + ICH9_REG_BBAR); - msg_pdbg("0x%x: 0x%08x (BBAR)\n", ICH9_REG_BBAR, ichspi_bbar); + msg_pdbg("0x%x: 0x%08"PRIx32" (BBAR)\n", ICH9_REG_BBAR, ichspi_bbar); ich_set_bbar(0, ich_gen); break; } if (ich_gen == CHIPSET_ICH8) { tmp = mmio_readl(spibar + ICH8_REG_VSCC); - msg_pdbg("0x%x: 0x%08x (VSCC)\n", ICH8_REG_VSCC, tmp); + msg_pdbg("0x%x: 0x%08"PRIx32" (VSCC)\n", ICH8_REG_VSCC, tmp); msg_pdbg("VSCC: "); prettyprint_ich_reg_vscc(tmp, FLASHROM_MSG_DEBUG, true); } else { tmp = mmio_readl(spibar + ICH9_REG_LVSCC); - msg_pdbg("0x%x: 0x%08x (LVSCC)\n", ICH9_REG_LVSCC, tmp); + msg_pdbg("0x%x: 0x%08"PRIx32" (LVSCC)\n", ICH9_REG_LVSCC, tmp); msg_pdbg("LVSCC: "); prettyprint_ich_reg_vscc(tmp, FLASHROM_MSG_DEBUG, true); tmp = mmio_readl(spibar + ICH9_REG_UVSCC); - msg_pdbg("0x%x: 0x%08x (UVSCC)\n", ICH9_REG_UVSCC, tmp); + msg_pdbg("0x%x: 0x%08"PRIx32" (UVSCC)\n", ICH9_REG_UVSCC, tmp); msg_pdbg("UVSCC: "); prettyprint_ich_reg_vscc(tmp, FLASHROM_MSG_DEBUG, false); } @@ -2103,6 +2326,7 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum case CHIPSET_ICH8: case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_C740_SERIES_EMMITSBURG: case CHIPSET_300_SERIES_CANNON_POINT: case CHIPSET_400_SERIES_COMET_POINT: case CHIPSET_500_SERIES_TIGER_POINT: @@ -2113,10 +2337,11 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum case CHIPSET_GEMINI_LAKE: case CHIPSET_JASPER_LAKE: case CHIPSET_ELKHART_LAKE: + case CHIPSET_PANTHER_LAKE: break; default: tmp = mmio_readl(spibar + ICH9_REG_FPB); - msg_pdbg("0x%x: 0x%08x (FPB)\n", ICH9_REG_FPB, tmp); + msg_pdbg("0x%x: 0x%08"PRIx32" (FPB)\n", ICH9_REG_FPB, tmp); break; } @@ -2146,7 +2371,8 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum ich_gen == CHIPSET_400_SERIES_COMET_POINT || ich_gen == CHIPSET_500_SERIES_TIGER_POINT || ich_gen == CHIPSET_600_SERIES_ALDER_POINT || - ich_gen == CHIPSET_700_SERIES_RAPTOR_POINT)) { + ich_gen == CHIPSET_700_SERIES_RAPTOR_POINT || + ich_gen == CHIPSET_C740_SERIES_EMMITSBURG)) { msg_pdbg("Enabling hardware sequencing by default for 100+ series PCH.\n"); ich_spi_mode = ich_hwseq; } @@ -2156,8 +2382,9 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum ich_gen == CHIPSET_GEMINI_LAKE || ich_gen == CHIPSET_JASPER_LAKE || ich_gen == CHIPSET_ELKHART_LAKE || - ich_gen == CHIPSET_METEOR_LAKE)) { - msg_pdbg("Enabling hardware sequencing by default for Apollo/Gemini/Jasper/Elkhart/Meteor Lake.\n"); + ich_gen == CHIPSET_METEOR_LAKE || + ich_gen == CHIPSET_PANTHER_LAKE)) { + msg_pdbg("Enabling hardware sequencing by default for Apollo/Gemini/Jasper/Elkhart/Meteor/Panther Lake.\n"); ich_spi_mode = ich_hwseq; } @@ -2165,26 +2392,30 @@ static int init_ich_default(const struct programmer_cfg *cfg, void *spibar, enum if (!desc_valid) { msg_perr("Hardware sequencing was requested " "but the flash descriptor is not valid. Aborting.\n"); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } int tmpi = getFCBA_component_density(ich_gen, &desc, 0); if (tmpi < 0) { msg_perr("Could not determine density of flash component %d.\n", 0); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } - g_hwseq_data.size_comp0 = tmpi; + hwseq_data.size_comp0 = tmpi; tmpi = getFCBA_component_density(ich_gen, &desc, 1); if (tmpi < 0) { msg_perr("Could not determine density of flash component %d.\n", 1); - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; } - g_hwseq_data.size_comp1 = tmpi; + hwseq_data.size_comp1 = tmpi; - register_opaque_master(&opaque_master_ich_hwseq, &g_hwseq_data); + struct hwseq_data *opaque_hwseq_data = calloc(1, sizeof(struct hwseq_data)); + if (!opaque_hwseq_data) + return ERROR_FLASHROM_FATAL; + memcpy(opaque_hwseq_data, &hwseq_data, sizeof(*opaque_hwseq_data)); + register_opaque_master(&opaque_master_ich_hwseq, opaque_hwseq_data); } else { - register_spi_master(&spi_master_ich9, NULL); + register_spi_master(&spi_master_ich, NULL); } return 0; @@ -2215,7 +2446,6 @@ static const struct spi_master spi_master_via = { .unmap_flash_region = physunmap, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .probe_opcode = ich_spi_probe_opcode, }; @@ -2225,7 +2455,7 @@ int via_init_spi(uint32_t mmio_base) ich_spibar = rphysmap("VIA SPI MMIO registers", mmio_base, 0x70); if (ich_spibar == ERROR_PTR) - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; /* Do we really need no write enable? Like the LPC one at D17F0 0x40 */ /* Not sure if it speaks all these bus protocols. */ @@ -2233,27 +2463,27 @@ int via_init_spi(uint32_t mmio_base) ich_generation = CHIPSET_ICH7; register_spi_master(&spi_master_via, NULL); - msg_pdbg("0x00: 0x%04x (SPIS)\n", mmio_readw(ich_spibar + 0)); - msg_pdbg("0x02: 0x%04x (SPIC)\n", mmio_readw(ich_spibar + 2)); - msg_pdbg("0x04: 0x%08x (SPIA)\n", mmio_readl(ich_spibar + 4)); + msg_pdbg("0x00: 0x%04"PRIx16" (SPIS)\n", mmio_readw(ich_spibar + 0)); + msg_pdbg("0x02: 0x%04"PRIx16" (SPIC)\n", mmio_readw(ich_spibar + 2)); + msg_pdbg("0x04: 0x%08"PRIx32" (SPIA)\n", mmio_readl(ich_spibar + 4)); for (i = 0; i < 2; i++) { int offs; offs = 8 + (i * 8); - msg_pdbg("0x%02x: 0x%08x (SPID%d)\n", offs, mmio_readl(ich_spibar + offs), i); - msg_pdbg("0x%02x: 0x%08x (SPID%d+4)\n", offs + 4, + msg_pdbg("0x%02x: 0x%08"PRIx32" (SPID%d)\n", offs, mmio_readl(ich_spibar + offs), i); + msg_pdbg("0x%02x: 0x%08"PRIx32" (SPID%d+4)\n", offs + 4, mmio_readl(ich_spibar + offs + 4), i); } ichspi_bbar = mmio_readl(ich_spibar + 0x50); - msg_pdbg("0x50: 0x%08x (BBAR)\n", ichspi_bbar); - msg_pdbg("0x54: 0x%04x (PREOP)\n", mmio_readw(ich_spibar + 0x54)); - msg_pdbg("0x56: 0x%04x (OPTYPE)\n", mmio_readw(ich_spibar + 0x56)); - msg_pdbg("0x58: 0x%08x (OPMENU)\n", mmio_readl(ich_spibar + 0x58)); - msg_pdbg("0x5c: 0x%08x (OPMENU+4)\n", mmio_readl(ich_spibar + 0x5c)); + msg_pdbg("0x50: 0x%08"PRIx32" (BBAR)\n", ichspi_bbar); + msg_pdbg("0x54: 0x%04"PRIx16" (PREOP)\n", mmio_readw(ich_spibar + 0x54)); + msg_pdbg("0x56: 0x%04"PRIx16" (OPTYPE)\n", mmio_readw(ich_spibar + 0x56)); + msg_pdbg("0x58: 0x%08"PRIx32" (OPMENU)\n", mmio_readl(ich_spibar + 0x58)); + msg_pdbg("0x5c: 0x%08"PRIx32" (OPMENU+4)\n", mmio_readl(ich_spibar + 0x5c)); for (i = 0; i < 3; i++) { int offs; offs = 0x60 + (i * 4); - msg_pdbg("0x%02x: 0x%08x (PBR%d)\n", offs, mmio_readl(ich_spibar + offs), i); + msg_pdbg("0x%02x: 0x%08"PRIx32" (PBR%d)\n", offs, mmio_readl(ich_spibar + offs), i); } msg_pdbg("0x6c: 0x%04x (CLOCK/DEBUG)\n", mmio_readw(ich_spibar + 0x6c)); if (mmio_readw(ich_spibar) & (1 << 15)) { diff --git a/include/chipdrivers.h b/include/chipdrivers.h index 61d43c9fa..a2e75d1a5 100644 --- a/include/chipdrivers.h +++ b/include/chipdrivers.h @@ -26,6 +26,7 @@ int spi_aai_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); int spi_chip_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); int spi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start, int unsigned len); +bool spi_probe_opcode(const struct flashctx *flash, uint8_t opcode); /* spi25.c */ int probe_spi_rdid(struct flashctx *flash); @@ -52,8 +53,8 @@ int spi_block_erase_d7(struct flashctx *flash, unsigned int addr, unsigned int b int spi_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_db(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_dc(struct flashctx *flash, unsigned int addr, unsigned int blocklen); -erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode); -uint8_t spi_get_opcode_from_erasefn(erasefunc_t *func); +enum block_erase_func spi25_get_erasefn_from_opcode(uint8_t opcode); +const uint8_t *spi_get_opcode_from_erasefn(enum block_erase_func func); int spi_chip_write_1(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); int spi_nbyte_read(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len); int spi_read_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize); @@ -67,45 +68,6 @@ int spi_set_extended_address(struct flashctx *, uint8_t addr_high); int spi_read_register(const struct flashctx *flash, enum flash_reg reg, uint8_t *value); int spi_write_register(const struct flashctx *flash, enum flash_reg reg, uint8_t value); void spi_prettyprint_status_register_bit(uint8_t status, int bit); -int spi_prettyprint_status_register_plain(struct flashctx *flash); -int spi_prettyprint_status_register_default_welwip(struct flashctx *flash); -int spi_prettyprint_status_register_bp1_srwd(struct flashctx *flash); -int spi_prettyprint_status_register_bp2_srwd(struct flashctx *flash); -int spi_prettyprint_status_register_bp3_srwd(struct flashctx *flash); -int spi_prettyprint_status_register_bp4_srwd(struct flashctx *flash); -int spi_prettyprint_status_register_bp2_bpl(struct flashctx *flash); -int spi_prettyprint_status_register_bp2_tb_bpl(struct flashctx *flash); -int spi_disable_blockprotect(struct flashctx *flash); -int spi_disable_blockprotect_bp1_srwd(struct flashctx *flash); -int spi_disable_blockprotect_bp2_srwd(struct flashctx *flash); -int spi_disable_blockprotect_bp3_srwd(struct flashctx *flash); -int spi_disable_blockprotect_bp4_srwd(struct flashctx *flash); -int spi_prettyprint_status_register_amic_a25l032(struct flashctx *flash); -int spi_prettyprint_status_register_at25df(struct flashctx *flash); -int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash); -int spi_prettyprint_status_register_at25f(struct flashctx *flash); -int spi_prettyprint_status_register_at25f512a(struct flashctx *flash); -int spi_prettyprint_status_register_at25f512b(struct flashctx *flash); -int spi_prettyprint_status_register_at25f4096(struct flashctx *flash); -int spi_prettyprint_status_register_at25fs010(struct flashctx *flash); -int spi_prettyprint_status_register_at25fs040(struct flashctx *flash); -int spi_prettyprint_status_register_at26df081a(struct flashctx *flash); -int spi_disable_blockprotect_at2x_global_unprotect(struct flashctx *flash); -int spi_disable_blockprotect_at2x_global_unprotect_sec(struct flashctx *flash); -int spi_disable_blockprotect_at25f(struct flashctx *flash); -int spi_disable_blockprotect_at25f512a(struct flashctx *flash); -int spi_disable_blockprotect_at25f512b(struct flashctx *flash); -int spi_disable_blockprotect_at25fs010(struct flashctx *flash); -int spi_disable_blockprotect_at25fs040(struct flashctx *flash); -int spi_prettyprint_status_register_en25s_wp(struct flashctx *flash); -int spi_prettyprint_status_register_n25q(struct flashctx *flash); -int spi_disable_blockprotect_n25q(struct flashctx *flash); -int spi_prettyprint_status_register_bp2_ep_srwd(struct flashctx *flash); -int spi_disable_blockprotect_bp2_ep_srwd(struct flashctx *flash); -int spi_prettyprint_status_register_sst25(struct flashctx *flash); -int spi_prettyprint_status_register_sst25vf016(struct flashctx *flash); -int spi_prettyprint_status_register_sst25vf040b(struct flashctx *flash); -int spi_disable_blockprotect_sst26_global_unprotect(struct flashctx *flash); /* sfdp.c */ int probe_spi_sfdp(struct flashctx *flash); @@ -135,8 +97,7 @@ int probe_82802ab(struct flashctx *flash); int erase_block_82802ab(struct flashctx *flash, unsigned int page, unsigned int pagesize); int write_82802ab(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); void print_status_82802ab(uint8_t status); -int unlock_28f004s5(struct flashctx *flash); -int unlock_lh28f008bjt(struct flashctx *flash); +blockprotect_func_t *lookup_82802ab_blockprotect_func_ptr(const struct flashchip *const chip); /* jedec.c */ uint8_t oddparity(uint8_t val); @@ -150,10 +111,7 @@ int erase_sector_jedec(struct flashctx *flash, unsigned int page, unsigned int p int erase_block_jedec(struct flashctx *flash, unsigned int page, unsigned int blocksize); int erase_chip_block_jedec(struct flashctx *flash, unsigned int page, unsigned int blocksize); -int unlock_regspace2_uniform_32k(struct flashctx *flash); -int unlock_regspace2_uniform_64k(struct flashctx *flash); -int unlock_regspace2_block_eraser_0(struct flashctx *flash); -int unlock_regspace2_block_eraser_1(struct flashctx *flash); +blockprotect_func_t *lookup_jedec_blockprotect_func_ptr(const struct flashchip *const chip); int printlock_regspace2_uniform_64k(struct flashctx *flash); int printlock_regspace2_block_eraser_0(struct flashctx *flash); int printlock_regspace2_block_eraser_1(struct flashctx *flash); @@ -195,6 +153,7 @@ int printlock_at49f(struct flashctx *flash); /* w29ee011.c */ int probe_w29ee011(struct flashctx *flash); +bool w29ee011_can_override(const char *const chip_name, const char *const override_chip); /* stm50.c */ int erase_sector_stm50(struct flashctx *flash, unsigned int block, unsigned int blocksize); @@ -215,5 +174,8 @@ int spi_block_erase_emulation(struct flashctx *flash, unsigned int addr, unsigne /* writeprotect_ranges.c */ void decode_range_spi25(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len); +void decode_range_spi25_64k_block(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len); +void decode_range_spi25_bit_cmp(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len); +void decode_range_spi25_2x_block(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len); #endif /* !__CHIPDRIVERS_H__ */ diff --git a/include/cli_classic.h b/include/cli_classic.h new file mode 100644 index 000000000..eb1f0fe95 --- /dev/null +++ b/include/cli_classic.h @@ -0,0 +1,43 @@ +/* + * This file is part of the flashrom project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef CLI_CLASSIC_H +#define CLI_CLASSIC_H + +#ifdef HAVE_GETOPT_H +#include +#else + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +extern char *optarg; +extern int optind, opterr, optopt; + +struct option { + const char *name; + int has_arg; + int *flag; + int val; +}; + +int getopt (int argc, char *const *argv, const char *shortopts); +int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +int getopt_long_only (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); + +#endif /* HAVE_GETOPT_H */ +#endif /* CLI_CLASSIC_H */ diff --git a/include/custom_baud.h b/include/custom_baud.h index c8b8fc296..38e6cfc40 100644 --- a/include/custom_baud.h +++ b/include/custom_baud.h @@ -22,7 +22,13 @@ struct baudentry { unsigned int baud; }; -int set_custom_baudrate(int fd, unsigned int baud); +enum custom_baud_stage { + BEFORE_FLAGS = 0, + WITH_FLAGS, + AFTER_FLAGS +}; + +int set_custom_baudrate(int fd, unsigned int baud, const enum custom_baud_stage stage, void *tio_wanted); /* Returns 1 if non-exact rate would be used, and setting a custom rate is supported. The baudtable must be in ascending order and terminated with a 0-baud entry. */ diff --git a/include/erasure_layout.h b/include/erasure_layout.h new file mode 100644 index 000000000..b8b5f089a --- /dev/null +++ b/include/erasure_layout.h @@ -0,0 +1,41 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2022 Aarya Chaumal + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ERASURE_LAYOUT_H__ +#define __ERASURE_LAYOUT_H__ 1 + +struct eraseblock_data { + chipoff_t start_addr; + chipoff_t end_addr; + bool selected; + size_t block_num; + size_t first_sub_block_index; + size_t last_sub_block_index; +}; + +struct erase_layout { + struct eraseblock_data* layout_list; + size_t block_count; + const struct block_eraser *eraser; +}; + +void free_erase_layout(struct erase_layout *layout, unsigned int erasefn_count); +int create_erase_layout(struct flashctx *const flashctx, struct erase_layout **erase_layout); +int erase_write(struct flashctx *const flashctx, chipoff_t region_start, chipoff_t region_end, + uint8_t* curcontents, uint8_t* newcontents, + struct erase_layout *erase_layout, bool *all_skipped); + +#endif /* !__ERASURE_LAYOUT_H__ */ diff --git a/include/flash.h b/include/flash.h index 863eb8f04..27a694b4f 100644 --- a/include/flash.h +++ b/include/flash.h @@ -60,7 +60,8 @@ void *master_map_flash_region(const struct registered_master *mast, const char *descr, uintptr_t phys_addr, size_t len); void master_unmap_flash_region(const struct registered_master *mast, void *virt_addr, size_t len); -void programmer_delay(unsigned int usecs); +/* NOTE: flashctx is not used in default_delay. In this case, a context should be NULL. */ +void programmer_delay(const struct flashrom_flashctx *flash, unsigned int usecs); #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) @@ -82,18 +83,18 @@ enum chipbustype { */ enum write_granularity { /* We assume 256 byte granularity by default. */ - write_gran_256bytes = 0,/* If less than 256 bytes are written, the unwritten bytes are undefined. */ - write_gran_1bit, /* Each bit can be cleared individually. */ - write_gran_1byte, /* A byte can be written once. Further writes to an already written byte cause + WRITE_GRAN_256BYTES = 0,/* If less than 256 bytes are written, the unwritten bytes are undefined. */ + WRITE_GRAN_1BIT, /* Each bit can be cleared individually. */ + WRITE_GRAN_1BYTE, /* A byte can be written once. Further writes to an already written byte cause * its contents to be either undefined or to stay unchanged. */ - write_gran_128bytes, /* If less than 128 bytes are written, the unwritten bytes are undefined. */ - write_gran_264bytes, /* If less than 264 bytes are written, the unwritten bytes are undefined. */ - write_gran_512bytes, /* If less than 512 bytes are written, the unwritten bytes are undefined. */ - write_gran_528bytes, /* If less than 528 bytes are written, the unwritten bytes are undefined. */ - write_gran_1024bytes, /* If less than 1024 bytes are written, the unwritten bytes are undefined. */ - write_gran_1056bytes, /* If less than 1056 bytes are written, the unwritten bytes are undefined. */ - write_gran_64kbytes, /* If less than 64 kbytes are written, the unwritten bytes are undefined. */ - write_gran_1byte_implicit_erase, /* EEPROMs and other chips with implicit erase and 1-byte writes. */ + WRITE_GRAN_128BYTES, /* If less than 128 bytes are written, the unwritten bytes are undefined. */ + WRITE_GRAN_264BYTES, /* If less than 264 bytes are written, the unwritten bytes are undefined. */ + WRITE_GRAN_512BYTES, /* If less than 512 bytes are written, the unwritten bytes are undefined. */ + WRITE_GRAN_528BYTES, /* If less than 528 bytes are written, the unwritten bytes are undefined. */ + WRITE_GRAN_1024BYTES, /* If less than 1024 bytes are written, the unwritten bytes are undefined. */ + WRITE_GRAN_1056BYTES, /* If less than 1056 bytes are written, the unwritten bytes are undefined. */ + WRITE_GRAN_64KBYTES, /* If less than 64 kbytes are written, the unwritten bytes are undefined. */ + WRITE_GRAN_1BYTE_IMPLICIT_ERASE, /* EEPROMs and other chips with implicit erase and 1-byte writes. */ }; /* @@ -148,6 +149,14 @@ enum write_granularity { * other flash chips, such as the ENE KB9012 internal flash, work the opposite way. */ #define FEATURE_ERASED_ZERO (1 << 18) +/* + * Feature indicates that the chip does not require erase before writing: + * write operations can set any bit to any value without first doing an erase, + * but bulk erase operations may still be supported. + * + * EEPROMs usually behave this way (compare to Flash, which requires erase), + * for example the ST M95M02. + */ #define FEATURE_NO_ERASE (1 << 19) #define FEATURE_WRSR_EXT2 (1 << 20) @@ -155,7 +164,17 @@ enum write_granularity { #define FEATURE_WRSR_EXT3 ((1 << 22) | FEATURE_WRSR_EXT2) #define FEATURE_WRSR3 (1 << 23) +/* + * Whether chip has security register (RDSCUR/WRSCUR commands). + * Not to be confused with "secure registers" of OTP. + */ +#define FEATURE_SCUR (1 << 24) + +/* Whether chip has configuration register (RDCR/WRSR_EXT2 commands) */ +#define FEATURE_CFGR (1 << 25) + #define ERASED_VALUE(flash) (((flash)->chip->feature_bits & FEATURE_ERASED_ZERO) ? 0x00 : 0xff) +#define UNERASED_VALUE(flash) (((flash)->chip->feature_bits & FEATURE_ERASED_ZERO) ? 0xff : 0x00) enum test_state { OK = 0, @@ -165,17 +184,19 @@ enum test_state { NA, /* Not applicable (e.g. write support on ROM chips) */ }; -#define TEST_UNTESTED (struct tested){ .probe = NT, .read = NT, .erase = NT, .write = NT } +#define TEST_UNTESTED (struct tested){ .probe = NT, .read = NT, .erase = NT, .write = NT, .wp = NT } -#define TEST_OK_PROBE (struct tested){ .probe = OK, .read = NT, .erase = NT, .write = NT } -#define TEST_OK_PR (struct tested){ .probe = OK, .read = OK, .erase = NT, .write = NT } -#define TEST_OK_PRE (struct tested){ .probe = OK, .read = OK, .erase = OK, .write = NT } -#define TEST_OK_PREW (struct tested){ .probe = OK, .read = OK, .erase = OK, .write = OK } +#define TEST_OK_PROBE (struct tested){ .probe = OK, .read = NT, .erase = NT, .write = NT, .wp = NT } +#define TEST_OK_PR (struct tested){ .probe = OK, .read = OK, .erase = NT, .write = NT, .wp = NT } +#define TEST_OK_PRE (struct tested){ .probe = OK, .read = OK, .erase = OK, .write = NT, .wp = NT } +#define TEST_OK_PREW (struct tested){ .probe = OK, .read = OK, .erase = OK, .write = OK, .wp = NT } +#define TEST_OK_PREWB (struct tested){ .probe = OK, .read = OK, .erase = OK, .write = OK, .wp = OK } -#define TEST_BAD_PROBE (struct tested){ .probe = BAD, .read = NT, .erase = NT, .write = NT } -#define TEST_BAD_PR (struct tested){ .probe = BAD, .read = BAD, .erase = NT, .write = NT } -#define TEST_BAD_PRE (struct tested){ .probe = BAD, .read = BAD, .erase = BAD, .write = NT } -#define TEST_BAD_PREW (struct tested){ .probe = BAD, .read = BAD, .erase = BAD, .write = BAD } +#define TEST_BAD_PROBE (struct tested){ .probe = BAD, .read = NT, .erase = NT, .write = NT, .wp = NT } +#define TEST_BAD_PR (struct tested){ .probe = BAD, .read = BAD, .erase = NT, .write = NT, .wp = NT } +#define TEST_BAD_PRE (struct tested){ .probe = BAD, .read = BAD, .erase = BAD, .write = NT, .wp = NT } +#define TEST_BAD_PREW (struct tested){ .probe = BAD, .read = BAD, .erase = BAD, .write = BAD, .wp = NT } +#define TEST_BAD_PREWB (struct tested){ .probe = BAD, .read = BAD, .erase = BAD, .write = BAD, .wp = BAD } struct flashrom_flashctx; #define flashctx flashrom_flashctx /* TODO: Agree on a name and convert all occurrences. */ @@ -186,6 +207,8 @@ enum flash_reg { STATUS1, STATUS2, STATUS3, + SECURITY, + CONFIG, MAX_REGISTERS }; @@ -209,6 +232,205 @@ struct reg_bit_info { struct wp_bits; +enum decode_range_func { + NO_DECODE_RANGE_FUNC = 0, /* 0 indicates no range decode function is set. */ + DECODE_RANGE_SPI25 = 1, + DECODE_RANGE_SPI25_64K_BLOCK = 2, + DECODE_RANGE_SPI25_BIT_CMP = 3, + DECODE_RANGE_SPI25_2X_BLOCK = 4, +}; +typedef void (decode_range_func_t)(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len); + +enum probe_func { + NO_PROBE_FUNC = 0, /* 0 indicates no probe function set. */ + PROBE_JEDEC = 1, + PROBE_JEDEC_29GL, + PROBE_OPAQUE, + PROBE_EDI_KB9012, + PROBE_AT82802AB, + PROBE_W29EE011, + PROBE_EN29LV640B, + PROBE_SPI_AT25F, + PROBE_SPI_AT45DB, + PROBE_SPI_BIG_SPANSION, + PROBE_SPI_RDID, + PROBE_SPI_RDID4, + PROBE_SPI_REMS, + PROBE_SPI_RES1, + PROBE_SPI_RES2, + PROBE_SPI_SFDP, + PROBE_SPI_ST95, +}; + +enum write_func { + NO_WRITE_FUNC = 0, /* 0 indicates no write function set. */ + WRITE_JEDEC = 1, + WRITE_JEDEC1, + WRITE_OPAQUE, + SPI_CHIP_WRITE1, + SPI_CHIP_WRITE256, + SPI_WRITE_AAI, + SPI_WRITE_AT45DB, + WRITE_28SF040, + WRITE_82802AB, + WRITE_EN29LV640B, + EDI_CHIP_WRITE, +#ifdef FLASHROM_TEST + TEST_WRITE_INJECTOR, /* special case must come last. */ +#endif +}; +typedef int (write_func_t)(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); + +#ifdef FLASHROM_TEST +extern write_func_t *g_test_write_injector; +#endif + +enum read_func { + NO_READ_FUNC = 0, /* 0 indicates no read function set. */ + SPI_CHIP_READ = 1, + READ_OPAQUE, + READ_MEMMAPPED, + EDI_CHIP_READ, + SPI_READ_AT45DB, + SPI_READ_AT45DB_E8, +#ifdef FLASHROM_TEST + TEST_READ_INJECTOR, /* special case must come last. */ +#endif +}; +typedef int (read_func_t)(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); +int read_flash(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); + +#ifdef FLASHROM_TEST +extern read_func_t *g_test_read_injector; +#endif + +enum block_erase_func { + NO_BLOCK_ERASE_FUNC = 0, /* 0 indicates no block erase function set. */ + SPI_BLOCK_ERASE_EMULATION = 1, + SPI_BLOCK_ERASE_20, + SPI_BLOCK_ERASE_21, + SPI_BLOCK_ERASE_40, + SPI_BLOCK_ERASE_50, + SPI_BLOCK_ERASE_52, + SPI_BLOCK_ERASE_53, + SPI_BLOCK_ERASE_5C, + SPI_BLOCK_ERASE_60, + SPI_BLOCK_ERASE_62, + SPI_BLOCK_ERASE_81, + SPI_BLOCK_ERASE_C4, + SPI_BLOCK_ERASE_C7, + SPI_BLOCK_ERASE_D7, + SPI_BLOCK_ERASE_D8, + SPI_BLOCK_ERASE_DB, + SPI_BLOCK_ERASE_DC, + S25FL_BLOCK_ERASE, + S25FS_BLOCK_ERASE_D8, + JEDEC_SECTOR_ERASE, + JEDEC_BLOCK_ERASE, + JEDEC_CHIP_BLOCK_ERASE, + OPAQUE_ERASE, + SPI_ERASE_AT45CS_SECTOR, + SPI_ERASE_AT45DB_BLOCK, + SPI_ERASE_AT45DB_CHIP, + SPI_ERASE_AT45DB_PAGE, + SPI_ERASE_AT45DB_SECTOR, + ERASE_CHIP_28SF040, + ERASE_SECTOR_28SF040, + ERASE_BLOCK_82802AB, + ERASE_SECTOR_49LFXXXC, + STM50_SECTOR_ERASE, + EDI_CHIP_BLOCK_ERASE, +#ifdef FLASHROM_TEST + /* special cases must come last. */ + TEST_ERASE_INJECTOR_1, + TEST_ERASE_INJECTOR_2, + TEST_ERASE_INJECTOR_3, + TEST_ERASE_INJECTOR_4, + TEST_ERASE_INJECTOR_5, +#endif +}; + +#ifdef FLASHROM_TEST +#define NUM_TEST_ERASE_INJECTORS 5 +extern erasefunc_t *g_test_erase_injector[NUM_TEST_ERASE_INJECTORS]; +#endif + +enum blockprotect_func { + NO_BLOCKPROTECT_FUNC = 0, /* 0 indicates no unlock function set. */ + SPI_DISABLE_BLOCKPROTECT, + SPI_DISABLE_BLOCKPROTECT_BP2_EP_SRWD, + SPI_DISABLE_BLOCKPROTECT_BP1_SRWD, + SPI_DISABLE_BLOCKPROTECT_BP2_SRWD, + SPI_DISABLE_BLOCKPROTECT_BP3_SRWD, + SPI_DISABLE_BLOCKPROTECT_BP4_SRWD, + SPI_DISABLE_BLOCKPROTECT_AT45DB, + SPI_DISABLE_BLOCKPROTECT_AT25F, + SPI_DISABLE_BLOCKPROTECT_AT25FS010, + SPI_DISABLE_BLOCKPROTECT_AT25FS040, + SPI_DISABLE_BLOCKPROTECT_AT25F512A, + SPI_DISABLE_BLOCKPROTECT_AT25F512B, + SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT, + SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT_SEC, + SPI_DISABLE_BLOCKPROTECT_SST26_GLOBAL_UNPROTECT, + SPI_DISABLE_BLOCKPROTECT_N25Q, + UNLOCK_REGSPACE2_BLOCK_ERASER_0, + UNLOCK_REGSPACE2_BLOCK_ERASER_1, + UNLOCK_REGSPACE2_UNIFORM_32K, + UNLOCK_REGSPACE2_UNIFORM_64K, + UNLOCK_28F004S5, + UNLOCK_LH28F008BJT, + UNLOCK_SST_FWHUB, + UNPROTECT_28SF040, +}; + +enum printlock_func { + NO_PRINTLOCK_FUNC, + PRINTLOCK_AT49F, + PRINTLOCK_REGSPACE2_BLOCK_ERASER_0, + PRINTLOCK_REGSPACE2_BLOCK_ERASER_1, + PRINTLOCK_SST_FWHUB, + PRINTLOCK_W39F010, + PRINTLOCK_W39L010, + PRINTLOCK_W39L020, + PRINTLOCK_W39L040, + PRINTLOCK_W39V040A, + PRINTLOCK_W39V040B, + PRINTLOCK_W39V040C, + PRINTLOCK_W39V040FA, + PRINTLOCK_W39V040FB, + PRINTLOCK_W39V040FC, + PRINTLOCK_W39V080A, + PRINTLOCK_W39V080FA, + PRINTLOCK_W39V080FA_DUAL, + SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF, + SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF_SEC, + SPI_PRETTYPRINT_STATUS_REGISTER_AT25F, + SPI_PRETTYPRINT_STATUS_REGISTER_AT25F4096, + SPI_PRETTYPRINT_STATUS_REGISTER_AT25F512A, + SPI_PRETTYPRINT_STATUS_REGISTER_AT25F512B, + SPI_PRETTYPRINT_STATUS_REGISTER_AT25FS010, + SPI_PRETTYPRINT_STATUS_REGISTER_AT25FS040, + SPI_PRETTYPRINT_STATUS_REGISTER_AT26DF081A, + SPI_PRETTYPRINT_STATUS_REGISTER_AT45DB, + SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD, + SPI_PRETTYPRINT_STATUS_REGISTER_BP2_BPL, + SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD, + SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD, + SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL, + SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP, + SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD, + SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD, + SPI_PRETTYPRINT_STATUS_REGISTER_DEFAULT_WELWIP, + SPI_PRETTYPRINT_STATUS_REGISTER_EN25S_WP, + SPI_PRETTYPRINT_STATUS_REGISTER_N25Q, + SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN, + SPI_PRETTYPRINT_STATUS_REGISTER_SST25, + SPI_PRETTYPRINT_STATUS_REGISTER_SST25VF016, + SPI_PRETTYPRINT_STATUS_REGISTER_SST25VF040B, +}; +typedef int (printlockfunc_t)(struct flashctx *flash); +printlockfunc_t *lookup_printlock_func_ptr(struct flashctx *flash); + struct flashchip { const char *vendor; const char *name; @@ -235,6 +457,7 @@ struct flashchip { enum test_state read; enum test_state erase; enum test_state write; + enum test_state wp; } tested; /* @@ -249,7 +472,7 @@ struct flashchip { SPI_EDI = 1, } spi_cmd_set; - int (*probe) (struct flashctx *flash); + enum probe_func probe; /* Delay after "enter/exit ID mode" commands in microseconds. * NB: negative values have special meanings, see TIMING_* below. @@ -259,9 +482,7 @@ struct flashchip { /* * Erase blocks and associated erase function. Any chip erase function * is stored as chip-sized virtual block together with said function. - * The first one that fits will be chosen. There is currently no way to - * influence that behaviour. For testing just comment out the other - * elements or set the function pointer to NULL. + * The logic for how to optimally select erase functions is in erasure_layout.c */ struct block_eraser { struct eraseblock { @@ -270,13 +491,13 @@ struct flashchip { } eraseblocks[NUM_ERASEREGIONS]; /* a block_erase function should try to erase one block of size * 'blocklen' at address 'blockaddr' and return 0 on success. */ - int (*block_erase) (struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen); + enum block_erase_func block_erase; } block_erasers[NUM_ERASEFUNCTIONS]; - int (*printlock) (struct flashctx *flash); - int (*unlock) (struct flashctx *flash); - int (*write) (struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); - int (*read) (struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); + enum printlock_func printlock; + enum blockprotect_func unlock; + enum write_func write; + enum read_func read; struct voltage { uint16_t min; uint16_t max; @@ -318,12 +539,16 @@ struct flashchip { struct reg_bit_info wps; } reg_bits; - /* Function that takes a set of WP config bits (e.g. BP, SEC, TB, etc) */ - /* and determines what protection range they select. */ - void (*decode_range)(size_t *start, size_t *len, const struct wp_bits *, size_t chip_len); + /* + * Function that takes a set of WP config bits (e.g. BP, SEC, TB, etc) + * and determines what protection range they select. + */ + enum decode_range_func decode_range; }; -typedef int (*chip_restore_fn_cb_t)(struct flashctx *flash, uint8_t status); +typedef int (*chip_restore_fn_cb_t)(struct flashctx *flash, void *data); +typedef int (blockprotect_func_t)(struct flashctx *flash); +blockprotect_func_t *lookup_blockprotect_func_ptr(const struct flashchip *const chip); struct flashrom_flashctx { struct flashchip *chip; @@ -344,6 +569,8 @@ struct flashrom_flashctx { bool force_boardmismatch; bool verify_after_write; bool verify_whole_chip; + bool skip_unreadable_regions; + bool skip_unwritable_regions; } flags; /* We cache the state of the extended address register (highest byte * of a 4BA for 3BA instructions) and the state of the 4BA mode here. @@ -356,7 +583,7 @@ struct flashrom_flashctx { int chip_restore_fn_count; struct chip_restore_func_data { chip_restore_fn_cb_t func; - uint8_t status; + void *data; } chip_restore_fn[MAX_CHIP_RESTORE_FUNCTIONS]; /* Progress reporting */ flashrom_progress_callback *progress_callback; @@ -388,7 +615,6 @@ void chip_readn(const struct flashctx *flash, uint8_t *buf, const chipaddr addr, /* print.c */ int print_supported(void); -void print_supported_wiki(void); /* helpers.c */ uint32_t address_to_bits(uint32_t addr); @@ -413,13 +639,12 @@ size_t strnlen(const char *str, size_t n); /* flashrom.c */ extern const char flashrom_version[]; -extern const char *chip_to_probe; char *flashbuses_to_text(enum chipbustype bustype); int map_flash(struct flashctx *flash); void unmap_flash(struct flashctx *flash); int read_memmapped(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); int erase_flash(struct flashctx *flash); -int probe_flash(struct registered_master *mst, int startchip, struct flashctx *fill_flash, int force); +int probe_flash(struct registered_master *mst, int startchip, struct flashctx *flash, int force, const char *const chip_to_probe); int verify_range(struct flashctx *flash, const uint8_t *cmpbuf, unsigned int start, unsigned int len); void emergency_help_message(void); void print_version(void); @@ -431,13 +656,20 @@ int read_buf_from_file(unsigned char *buf, unsigned long size, const char *filen int write_buf_to_file(const unsigned char *buf, unsigned long size, const char *filename); int prepare_flash_access(struct flashctx *, bool read_it, bool write_it, bool erase_it, bool verify_it); void finalize_flash_access(struct flashctx *); -int register_chip_restore(chip_restore_fn_cb_t func, struct flashctx *flash, uint8_t status); +int register_chip_restore(chip_restore_fn_cb_t func, struct flashctx *flash, void *data); +int check_block_eraser(const struct flashctx *flash, int k, int log); +unsigned int count_usable_erasers(const struct flashctx *flash); +int need_erase(const uint8_t *have, const uint8_t *want, unsigned int len, enum write_granularity gran, const uint8_t erased_value); +erasefunc_t *lookup_erase_func_ptr(const struct block_eraser *const eraser); +int check_erased_range(struct flashctx *flash, unsigned int start, unsigned int len); +unsigned int get_next_write(const uint8_t *have, const uint8_t *want, unsigned int len, unsigned int *first_start, enum write_granularity gran); +int write_flash(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); /* Something happened that shouldn't happen, but we can go on. */ -#define ERROR_NONFATAL 0x100 +#define ERROR_FLASHROM_NONFATAL 0x100 /* Something happened that shouldn't happen, we'll abort. */ -#define ERROR_FATAL -0xee +#define ERROR_FLASHROM_FATAL -0xee #define ERROR_FLASHROM_BUG -200 /* We reached one of the hardcoded limits of flashrom. This can be fixed by * increasing the limit of a compile-time allocation or by switching to dynamic diff --git a/include/flashchips.h b/include/flashchips.h index 5df42dcf0..534304adb 100644 --- a/include/flashchips.h +++ b/include/flashchips.h @@ -127,6 +127,7 @@ #define AMIC_A49LF040A 0x9d #define ATMEL_ID 0x1F /* Atmel (now used by Adesto) */ +#define ATMEL_AT25DF011 0x4200 #define ATMEL_AT25DF021 0x4300 #define ATMEL_AT25DF021A 0x4301 #define ATMEL_AT25DF041A 0x4401 @@ -210,7 +211,9 @@ /* Boya/BoHong Microelectronics Inc. */ #define BOYA_BOHONG_ID 0x68 +#define BOYA_BOHONG_B__25D80A 0x4014 #define BOYA_BOHONG_B_25D16A 0x4015 +#define BOYA_BOHONG_B_25Q64AS 0x4017 #define BOYA_BOHONG_B_25Q128AS 0x4018 /* Bright Microelectronics has the same manufacturer ID as Hyundai... */ @@ -341,9 +344,12 @@ #define FUDAN_FM25F01 0x3111 #define FUDAN_FM25F02 0x3112 /* Same as FM25F02A */ #define FUDAN_FM25F04 0x3113 /* Same as FM25F04A */ +#define FUDAN_FM25Q04 0x4013 #define FUDAN_FM25Q08 0x4014 #define FUDAN_FM25Q16 0x4015 #define FUDAN_FM25Q32 0x4016 +#define FUDAN_FM25Q64 0x4017 +#define FUDAN_FM25Q128 0x4018 #define FUJITSU_ID 0x04 /* Fujitsu */ #define FUJITSU_MBM29DL400BC 0x0F @@ -388,18 +394,28 @@ #define GIGADEVICE_GD25Q16 0x4015 /* Same as GD25Q16B (which has OTP) */ #define GIGADEVICE_GD25Q32 0x4016 /* Same as GD25Q32B */ #define GIGADEVICE_GD25Q64 0x4017 /* Same as GD25Q64B */ -#define GIGADEVICE_GD25Q128 0x4018 /* GD25Q128B and GD25Q128C only, can be distinguished by SFDP */ -#define GIGADEVICE_GD25Q256D 0x4019 +#define GIGADEVICE_GD25Q128 0x4018 /* Same as GD25Q128B, GD25Q127C, GD25Q128C,and GD25Q128E, GD25B128E, GD25R128E can be distinguished by SFDP */ +#define GIGADEVICE_GD25Q256D 0x4019 /* Same as GD25B256E, GD25Q256E, GD25R256E */ +#define GIGADEVICE_GD25B512MF 0x401A /* Same as GD25R512MF */ #define GIGADEVICE_GD25VQ21B 0x4212 #define GIGADEVICE_GD25VQ41B 0x4213 /* Same as GD25VQ40C, can be distinguished by SFDP */ #define GIGADEVICE_GD25VQ80C 0x4214 #define GIGADEVICE_GD25VQ16C 0x4215 +#define GIGADEVICE_GD25F64F 0x4317 +#define GIGADEVICE_GD25F256F 0x4319 #define GIGADEVICE_GD25LQ40 0x6013 #define GIGADEVICE_GD25LQ80 0x6014 #define GIGADEVICE_GD25LQ16 0x6015 #define GIGADEVICE_GD25LQ32 0x6016 #define GIGADEVICE_GD25LQ64 0x6017 /* Same as GD25LQ64B (which is faster) */ #define GIGADEVICE_GD25LQ128CD 0x6018 +#define GIGADEVICE_GD25LQ255E 0x6019 +#define GIGADEVICE_GD25LB512MF 0x601A /* Same as GD25LR512MF */ +#define GIGADEVICE_GD25LF128E 0x6318 +#define GIGADEVICE_GD25LF256F 0x6319 +#define GIGADEVICE_GD25LF512MF 0x631A +#define GIGADEVICE_GD25LR256E 0x6719 +#define GIGADEVICE_GD25LR512ME 0x671A /* Same as GD25LB512ME */ #define GIGADEVICE_GD25WQ80E 0x6514 #define GIGADEVICE_GD29GL064CAB 0x7E0601 @@ -472,13 +488,20 @@ #define ISSI_ID 0xD5 /* ISSI Integrated Silicon Solutions, see also PMC. */ #define ISSI_ID_SPI 0x9D /* ISSI ID used for SPI flash, see also PMC_ID_NOPREFIX */ +#define ISSI_IS25LP016 0x6015 #define ISSI_IS25LP064 0x6017 #define ISSI_IS25LP128 0x6018 #define ISSI_IS25LP256 0x6019 +#define ISSI_IS25LQ016 0x1445 +#define ISSI_IS25WP016 0x7015 +#define ISSI_IS25WP020 0x7012 #define ISSI_IS25WP032 0x7016 +#define ISSI_IS25WP040 0x7013 #define ISSI_IS25WP064 0x7017 +#define ISSI_IS25WP080 0x7014 #define ISSI_IS25WP128 0x7018 #define ISSI_IS25WP256 0x7019 +#define ISSI_IS25WQ040 0x1253 #define ISSI_PMC_IS29GL032B 0xF9 #define ISSI_PMC_IS29GL032T 0xF6 #define ISSI_PMC_IS29GL064B 0x7E1000 @@ -503,27 +526,38 @@ #define MACRONIX_MX25L2005 0x2012 /* Same as MX25L2005C, MX25L2006E */ #define MACRONIX_MX25L4005 0x2013 /* Same as MX25L4005A, MX25L4005C, MX25L4006E */ #define MACRONIX_MX25L8005 0x2014 /* Same as MX25V8005, MX25L8006E, MX25L8008E, FIXME: MX25L8073E (4k 0x20) */ -#define MACRONIX_MX25L1605 0x2015 /* MX25L1605 (64k 0x20); MX25L1605A/MX25L1606E/MX25L1608E (4k 0x20, 64k 0x52); MX25L1605D/MX25L1608D/MX25L1673E (4k 0x20) */ +#define MACRONIX_MX25L1605 0x2015 /* MX25L1605 (64k 0x20); MX25V16066 (4k 0x20, 32k 0x52, 64k 0xD8); MX25L1605A/MX25L1606E/MX25L1608E (4k 0x20, 64k 0x52); MX25L1605D/MX25L1608D/MX25L1673E (4k 0x20) */ #define MACRONIX_MX25L3205 0x2016 /* MX25L3205, MX25L3205A (64k 0x20); MX25L3205D/MX25L3208D (4k 0x20); MX25L3206E/MX25L3208E (4k 0x20, 64k 0x52); MX25L3233F/MX25L3273E (4k 0x20, 32k 0x52) */ #define MACRONIX_MX25L6405 0x2017 /* MX25L6405, MX25L6405D (64k 0x20); MX25L6406E/MX25L6408E (4k 0x20); MX25L6436E/MX25L6445E/MX25L6465E/MX25L6473E (4k 0x20, 32k 0x52) */ -#define MACRONIX_MX25L12805D 0x2018 /* MX25L12805D (no 32k); MX25L12865E, MX25L12835F, MX25L12845E, MX25L12873F, MX25L12833F (32k 0x52) */ +#define MACRONIX_MX25L12805D 0x2018 /* MX25L12805D (no 32k); MX25L12865E, MX25L12835F, MX25L12845E, MX25L12873F, MX25L12833F, MX25L12850F (32k 0x52) */ #define MACRONIX_MX25L25635F 0x2019 /* Same as MX25L25639F, but the latter seems to not support REMS */ -#define MACRONIX_MX25L1635D 0x2415 +#define MACRONIX_MX25L1635D 0x2415 /* MX25L1633E */ #define MACRONIX_MX25L1635E 0x2515 /* MX25L1635{E} */ #define MACRONIX_MX66L51235F 0x201a /* MX66L51235F, MX25L51245G */ #define MACRONIX_MX66L1G45G 0x201b /* MX66L1G45G */ +#define MACRONIX_MX25V4035F 0x2313 +#define MACRONIX_MX25V8035F 0x2314 +#define MACRONIX_MX25V1635F 0x2315 /* MX25V1636E */ #define MACRONIX_MX25U8032E 0x2534 #define MACRONIX_MX25U1635E 0x2535 #define MACRONIX_MX25U3235E 0x2536 /* Same as MX25U6435F */ #define MACRONIX_MX25U6435E 0x2537 /* Same as MX25U6435F */ #define MACRONIX_MX25U12835E 0x2538 /* Same as MX25U12835F */ -#define MACRONIX_MX25U25635F 0x2539 +#define MACRONIX_MX25U25635F 0x2539 /* Same as MX25U25643G, MX25U25645G */ #define MACRONIX_MX25U51245G 0x253a #define MACRONIX_MX25L3235D 0x5E16 /* MX25L3225D/MX25L3235D/MX25L3237D */ #define MACRONIX_MX25L6495F 0x9517 +#define MACRONIX_MX25L3255E 0x9e16 +#define MACRONIX_MX77L25650F 0x7519 +#define MACRONIX_MX77U51250F 0x753A +#define MACRONIX_MX25L3239E 0x2536 +#define MACRONIX_MX25R1635F 0x2815 #define MACRONIX_MX25R3235F 0x2816 #define MACRONIX_MX25R6435F 0x2817 +#define MACRONIX_MX25R2035F 0x2812 +#define MACRONIX_MX25R4035F 0x2813 +#define MACRONIX_MX25R8035F 0x2814 #define MACRONIX_MX29F001B 0x19 #define MACRONIX_MX29F001T 0x18 @@ -621,6 +655,11 @@ #define PMC_PM49FL002 0x6D #define PMC_PM49FL004 0x6E +#define PUYA_ID 0x85 +#define PUYA_P25Q06H 0x4010 +#define PUYA_P25Q11H 0x4011 +#define PUYA_P25Q21H 0x4012 + /* * The Sanyo chip found so far uses SPI, first byte is manufacturer code, * second byte is the device code, @@ -814,14 +853,23 @@ #define ST_M45PE10 0x4011 #define ST_M45PE20 0x4012 #define ST_M45PE40 0x4013 -#define ST_M45PE80 0x4014 +#define ST_M45PE80 0x4014 /* Same as XM25QH80B */ #define ST_M45PE16 0x4015 -#define XMC_XM25QH64C 0x4017 +#define XMC_XM25QH64C 0x4017 /* Same as XM25QH64D */ #define XMC_XM25QU64C 0x4117 -#define XMC_XM25QH128C 0x4018 -#define XMC_XM25QU128C 0x4118 -#define XMC_XM25QH256C 0x4019 -#define XMC_XM25QU256C 0x4119 +#define XMC_XM25QU80B 0x5014 +#define XMC_XM25QH16C 0x4015 /* Same as XM25QH16D */ +#define XMC_XM25QU16C 0x5015 +#define XMC_XM25QH32C 0x4016 /* Same as XM25QH32D */ +#define XMC_XM25QU32C 0x5016 +#define XMC_XM25QH128A 0x7018 +#define XMC_XM25QH128C 0x4018 /* Same as XM25QH128D */ +#define XMC_XM25QU128C 0x4118 /* Same as XM25QU128D */ +#define XMC_XM25QH256C 0x4019 /* Same as XM25QH256D */ +#define XMC_XM25QU256C 0x4119 /* Same as XM25QU256D */ +#define XMC_XM25RU256C 0x4419 +#define XMC_XM25QH512C 0x4020 /* Same as XM25QH512D */ +#define XMC_XM25QU512C 0x4120 /* Same as XM25QU512D */ #define ST_M25PX80 0x7114 #define ST_M25PX16 0x7115 #define ST_M25PX32 0x7116 @@ -978,6 +1026,8 @@ #define WINBOND_NEX_W25Q64_W 0x6017 /* W25Q64DW; W25Q64FV in QPI mode */ #define WINBOND_NEX_W25Q128_W 0x6018 /* W25Q128FW; W25Q128FV in QPI mode */ #define WINBOND_NEX_W25Q256_W 0x6019 /* W25Q256JW */ +#define WINBOND_NEX_W25Q16JV_M 0x7015 /* W25Q16JV_M (QE=0) */ +#define WINBOND_NEX_W25Q32JV_M 0x7016 /* W25Q32JV_M (QE=0) */ #define WINBOND_NEX_W25Q64JV 0x7017 /* W25Q64JV */ #define WINBOND_NEX_W25Q128_V_M 0x7018 /* W25Q128JVSM */ #define WINBOND_NEX_W25Q256JV_M 0x7019 /* W25Q256JV_M (QE=0) */ @@ -1029,8 +1079,14 @@ #define WINBOND_W49V002A 0xB0 #define WINBOND_W49V002FA 0x32 -#define ZETTADEVICE_ID 0xBA /* Zetta Device */ -#define ZETTADEVICE_ZD25D20 0x2012 -#define ZETTADEVICE_ZD25D40 0x2013 +#define XTX_ID 0x0B /* XTX Technology Limited */ +#define XTX_XT25F02E 0x4012 +#define XTX_XT25F64B 0x4017 +#define XTX_XT25F128B 0x4018 + +#define ZETTA_ID 0xBA /* Zetta Device */ +#define ZETTA_ZD25D20 0x2012 +#define ZETTA_ZD25D40 0x2013 +#define ZETTA_ZD25LQ128_REMS 0x17 /* RDID = 0x4218 */ #endif /* !FLASHCHIPS_H */ diff --git a/include/layout.h b/include/layout.h index abbdc22c1..d03a15b20 100644 --- a/include/layout.h +++ b/include/layout.h @@ -35,14 +35,26 @@ typedef uint32_t chipsize_t; /* Able to store the number of bytes of any support #define MAX_ROMLAYOUT 128 +struct flash_region { + char *name; + /* + * Note that because start and end are chipoff_t, end is an inclusive upper + * bound: the length of a region is (end - start + 1) bytes and it is + * impossible to represent a region with zero length. + */ + chipoff_t start; + chipoff_t end; + bool read_prot; + bool write_prot; +}; + struct romentry { struct romentry *next; - chipoff_t start; - chipoff_t end; bool included; - char *name; char *file; + + struct flash_region region; }; struct flashrom_layout; @@ -65,5 +77,7 @@ const struct romentry *layout_next(const struct flashrom_layout *, const struct int included_regions_overlap(const struct flashrom_layout *); void prepare_layout_for_extraction(struct flashrom_flashctx *); int layout_sanity_checks(const struct flashrom_flashctx *); +int check_for_unwritable_regions(const struct flashrom_flashctx *flash, unsigned int start, unsigned int len); +void get_flash_region(const struct flashrom_flashctx *flash, int addr, struct flash_region *region); #endif /* !__LAYOUT_H__ */ diff --git a/include/libflashrom.h b/include/libflashrom.h index 21a5785f3..e87776be1 100644 --- a/include/libflashrom.h +++ b/include/libflashrom.h @@ -121,6 +121,7 @@ struct flashrom_flashchip_info { enum flashrom_test_state read; enum flashrom_test_state erase; enum flashrom_test_state write; + enum flashrom_test_state wp; } tested; }; @@ -250,6 +251,8 @@ enum flashrom_flag { FLASHROM_FLAG_FORCE_BOARDMISMATCH, FLASHROM_FLAG_VERIFY_AFTER_WRITE, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, + FLASHROM_FLAG_SKIP_UNREADABLE_REGIONS, + FLASHROM_FLAG_SKIP_UNWRITABLE_REGIONS, }; /** @@ -417,6 +420,16 @@ int flashrom_layout_add_region(struct flashrom_layout *layout, size_t start, siz * 1 if the given name can't be found. */ int flashrom_layout_include_region(struct flashrom_layout *layout, const char *name); +/** + * @brief Mark given region as not included. + * + * @param layout The layout to alter. + * @param name The name of the region to exclude. + * + * @return 0 on success, + * 1 if the given name can't be found. + */ +int flashrom_layout_exclude_region(struct flashrom_layout *layout, const char *name); /** * @brief Get given region's offset and length. * @@ -463,7 +476,8 @@ enum flashrom_wp_result { FLASHROM_WP_ERR_VERIFY_FAILED = 5, FLASHROM_WP_ERR_RANGE_UNSUPPORTED = 6, FLASHROM_WP_ERR_MODE_UNSUPPORTED = 7, - FLASHROM_WP_ERR_RANGE_LIST_UNAVAILABLE = 8 + FLASHROM_WP_ERR_RANGE_LIST_UNAVAILABLE = 8, + FLASHROM_WP_ERR_UNSUPPORTED_STATE = 9 }; enum flashrom_wp_mode { diff --git a/include/platform/pci.h b/include/platform/pci.h index 93bc163be..6abde5923 100644 --- a/include/platform/pci.h +++ b/include/platform/pci.h @@ -1,25 +1,31 @@ /* - * This is a wrapper for libpci. - * ... + * This file is part of the flashrom project. + * + * Copyright (C) 2022 secunet Security Networks AG + * (written by Thomas Heijligen +#ifdef HAVE_PCIUTILS_PCI_H +#include #else #include -#endif - -#undef index +#endif /* HAVE_PCIUTILS_PCI_H */ -#endif /* __PLATFORM_PCI_H__ */ \ No newline at end of file +#endif /* __PLATFORM_PCI_H__ */ diff --git a/include/programmer.h b/include/programmer.h index c64dbac7a..10feaf1c0 100644 --- a/include/programmer.h +++ b/include/programmer.h @@ -30,7 +30,11 @@ enum programmer_type { USB, OTHER, }; -struct programmer_cfg; +struct board_cfg; +struct programmer_cfg { + char *params; + struct board_cfg *bcfg; +}; struct dev_entry { uint16_t vendor_id; @@ -49,8 +53,6 @@ struct programmer_entry { } devs; int (*init) (const struct programmer_cfg *cfg); - - void (*delay) (unsigned int usecs); }; extern const struct programmer_entry *const programmer_table[]; @@ -59,11 +61,13 @@ extern const size_t programmer_table_size; /* programmer drivers */ extern const struct programmer_entry programmer_ast1100; extern const struct programmer_entry programmer_ast2400; +extern const struct programmer_entry programmer_asm106x; extern const struct programmer_entry programmer_atahpt; extern const struct programmer_entry programmer_atapromise; extern const struct programmer_entry programmer_atavia; extern const struct programmer_entry programmer_buspirate_spi; extern const struct programmer_entry programmer_ch341a_spi; +extern const struct programmer_entry programmer_ch347_spi; extern const struct programmer_entry programmer_dediprog; extern const struct programmer_entry programmer_developerbox; extern const struct programmer_entry programmer_digilent_spi; @@ -98,6 +102,7 @@ extern const struct programmer_entry programmer_serprog; extern const struct programmer_entry programmer_stlinkv3_spi; extern const struct programmer_entry programmer_usbblaster_spi; extern const struct programmer_entry programmer_ite_ec; +extern const struct programmer_entry programmer_dirtyjtag_spi; int programmer_init(const struct programmer_entry *prog, const char *param); int programmer_shutdown(void); @@ -167,6 +172,11 @@ enum board_match_phase { P3 }; +struct board_cfg { + int is_laptop; + bool laptop_ok; +}; + struct board_match { /* Any device, but make it sensible, like the ISA bridge. */ uint16_t first_vendor; @@ -196,19 +206,18 @@ struct board_match { int max_rom_decode_parallel; const enum test_state status; - int (*enable) (void); /* May be NULL. */ + int (*enable) (struct board_cfg *cfg); /* May be NULL. */ }; extern const struct board_match board_matches[]; +extern const size_t board_matches_size; struct board_info { const char *vendor; const char *name; const enum test_state working; -#ifdef CONFIG_PRINT_WIKI const char *url; const char *note; -#endif }; extern const struct board_info boards_known[]; @@ -216,10 +225,8 @@ extern const struct board_info laptops_known[]; #endif /* udelay.c */ -void myusec_delay(unsigned int usecs); -void myusec_calibrate_delay(void); void internal_sleep(unsigned int usecs); -void internal_delay(unsigned int usecs); +void default_delay(unsigned int usecs); #if CONFIG_INTERNAL == 1 /* board_enable.c */ @@ -229,9 +236,11 @@ void w836xx_ext_enter(uint16_t port); void w836xx_ext_leave(uint16_t port); void probe_superio_winbond(void); int it8705f_write_enable(uint8_t port); -void board_handle_before_superio(void); -void board_handle_before_laptop(void); -int board_flash_enable(const char *vendor, const char *model, const char *cb_vendor, const char *cb_model); +void board_handle_before_superio(struct board_cfg *cfg, bool force_boardenable); +void board_handle_before_laptop(struct board_cfg *cfg, bool force_boardenable); +int board_flash_enable(struct board_cfg *cfg, + const char *vendor, const char *model, const char *cb_vendor, const char *cb_model, + bool force_boardenable); /* chipset_enable.c */ int chipset_flash_enable(const struct programmer_cfg *cfg); @@ -265,7 +274,7 @@ int cb_check_image(const uint8_t *bios, unsigned int size); /* dmi.c */ #if defined(__i386__) || defined(__x86_64__) -void dmi_init(void); +void dmi_init(int *is_laptop); bool dmi_is_supported(void); int dmi_match(const char *pattern); #endif // defined(__i386__) || defined(__x86_64__) @@ -284,9 +293,6 @@ extern int superio_count; #endif #if CONFIG_INTERNAL == 1 -extern int is_laptop; -extern bool laptop_ok; -extern bool force_boardenable; extern bool force_boardmismatch; void probe_superio(void); int register_superio(struct superio s); @@ -307,8 +313,7 @@ struct decode_sizes { // FIXME: These need to be local, not global extern struct decode_sizes max_rom_decode; extern bool programmer_may_write; -extern unsigned long flashbase; -unsigned int count_max_decode_exceedings(const struct flashctx *flash); +extern uintptr_t flashbase; /* used in programmer_enable.c */ char *extract_programmer_param_str(const struct programmer_cfg *cfg, const char *param_name); /* spi.c */ @@ -335,17 +340,15 @@ struct spi_master { int (*write_256)(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); int (*write_aai)(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); int (*shutdown)(void *data); - bool (*probe_opcode)(struct flashctx *flash, uint8_t opcode); + bool (*probe_opcode)(const struct flashctx *flash, uint8_t opcode); /* NULL func implies true. */ + void (*delay) (const struct flashctx *flash, unsigned int usecs); + void (*get_region)(const struct flashctx *flash, unsigned int addr, struct flash_region *region); void *data; }; -int default_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, - const unsigned char *writearr, unsigned char *readarr); -int default_spi_send_multicommand(const struct flashctx *flash, struct spi_command *cmds); int default_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); int default_spi_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); int default_spi_write_aai(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); -bool default_spi_probe_opcode(struct flashctx *flash, uint8_t opcode); int register_spi_master(const struct spi_master *mst, void *data); /* The following enum is needed by ich_descriptor_tool and ich* code as well as in chipset_enable.c. */ @@ -372,6 +375,7 @@ enum ich_chipset { CHIPSET_9_SERIES_WILDCAT_POINT_LP, CHIPSET_100_SERIES_SUNRISE_POINT, /* also 6th/7th gen Core i/o (LP) variants */ CHIPSET_C620_SERIES_LEWISBURG, + CHIPSET_C740_SERIES_EMMITSBURG, CHIPSET_300_SERIES_CANNON_POINT, CHIPSET_400_SERIES_COMET_POINT, CHIPSET_500_SERIES_TIGER_POINT, @@ -382,6 +386,8 @@ enum ich_chipset { CHIPSET_GEMINI_LAKE, CHIPSET_JASPER_LAKE, CHIPSET_ELKHART_LAKE, + /* All chipsets after METEOR_LAKE should support checking BIOS_BM to get read/write access to of FREG0~15 */ + CHIPSET_PANTHER_LAKE, }; /* ichspi.c */ @@ -413,11 +419,14 @@ static inline int try_mtd(const struct programmer_cfg *cfg) /* mcp6x_spi.c */ int mcp6x_spi_init(int want_spi); +/* internal_par.c */ +void internal_par_init(enum chipbustype buses); + /* sb600spi.c */ int sb600_probe_spi(const struct programmer_cfg *cfg, struct pci_dev *dev); /* wbsio_spi.c */ -int wbsio_check_for_spi(void); +int wbsio_check_for_spi(struct board_cfg *); #endif /* opaque.c */ @@ -440,7 +449,9 @@ struct opaque_master { enum flashrom_wp_result (*wp_write_cfg)(struct flashctx *, const struct flashrom_wp_cfg *); enum flashrom_wp_result (*wp_read_cfg)(struct flashrom_wp_cfg *, struct flashctx *); enum flashrom_wp_result (*wp_get_ranges)(struct flashrom_wp_ranges **, struct flashctx *); + void (*get_region)(const struct flashctx *flash, unsigned int addr, struct flash_region *region); int (*shutdown)(void *data); + void (*delay) (const struct flashctx *flash, unsigned int usecs); void *data; }; int register_opaque_master(const struct opaque_master *mst, void *data); @@ -458,19 +469,12 @@ struct par_master { uint32_t (*chip_readl) (const struct flashctx *flash, const chipaddr addr); void (*chip_readn) (const struct flashctx *flash, uint8_t *buf, const chipaddr addr, size_t len); int (*shutdown)(void *data); + void (*delay) (const struct flashctx *flash, unsigned int usecs); void *data; }; int register_par_master(const struct par_master *mst, const enum chipbustype buses, void *data); /* programmer.c */ -void *fallback_map(const char *descr, uintptr_t phys_addr, size_t len); -void fallback_unmap(void *virt_addr, size_t len); -void fallback_chip_writew(const struct flashctx *flash, uint16_t val, chipaddr addr); -void fallback_chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr); -void fallback_chip_writen(const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len); -uint16_t fallback_chip_readw(const struct flashctx *flash, const chipaddr addr); -uint32_t fallback_chip_readl(const struct flashctx *flash, const chipaddr addr); -void fallback_chip_readn(const struct flashctx *flash, uint8_t *buf, const chipaddr addr, size_t len); struct registered_master { enum chipbustype buses_supported; struct { @@ -542,6 +546,12 @@ static inline bool spi_master_no_4ba_modes(const struct flashctx *const flash) return flash->mst->buses_supported & BUS_SPI && flash->mst->spi.features & SPI_MASTER_NO_4BA_MODES; } +/* spi_chip feature checks */ +static inline bool spi_chip_4ba(const struct flashctx *const flash) +{ + return flash->chip->bustype == BUS_SPI && + (flash->chip->feature_bits & (FEATURE_4BA_ENTER | FEATURE_4BA_ENTER_WREN | FEATURE_4BA_ENTER_EAR7)); +} /* usbdev.c */ struct libusb_device_handle; diff --git a/include/spi.h b/include/spi.h index 9b38cab64..505aecd01 100644 --- a/include/spi.h +++ b/include/spi.h @@ -167,6 +167,21 @@ #define JEDEC_WRSR3_OUTSIZE 0x02 #define JEDEC_WRSR3_INSIZE 0x00 +/* Read Security Register */ +#define JEDEC_RDSCUR 0x2b +#define JEDEC_RDSCUR_OUTSIZE 0x01 +#define JEDEC_RDSCUR_INSIZE 0x01 + +/* Write Security Register */ +#define JEDEC_WRSCUR 0x2f +#define JEDEC_WRSCUR_OUTSIZE 0x01 +#define JEDEC_WRSCUR_INSIZE 0x00 + +/* Read Configuration Register */ +#define JEDEC_RDCR 0x15 +#define JEDEC_RDCR_OUTSIZE 0x01 +#define JEDEC_RDCR_INSIZE 0x01 + /* Enter 4-byte Address Mode */ #define JEDEC_ENTER_4_BYTE_ADDR_MODE 0xB7 diff --git a/include/writeprotect.h b/include/writeprotect.h index 12926c4d3..7ceed0792 100644 --- a/include/writeprotect.h +++ b/include/writeprotect.h @@ -89,4 +89,10 @@ enum flashrom_wp_result wp_get_available_ranges(struct flashrom_wp_ranges **, st /* Checks if writeprotect functions can be used with the current flash/programmer */ bool wp_operations_available(struct flashrom_flashctx *); +/* + * Converts a writeprotect config to register values and masks that indicate which register bits affect WP state. + * reg_values, bit_masks, and write_masks must all have length of at least MAX_REGISTERS. + */ +enum flashrom_wp_result wp_cfg_to_reg_values(uint8_t *reg_values, uint8_t *bit_masks, uint8_t *write_masks, struct flashrom_flashctx *, const struct flashrom_wp_cfg *); + #endif /* !__WRITEPROTECT_H__ */ diff --git a/internal.c b/internal.c index 473f21c68..df27086c8 100644 --- a/internal.c +++ b/internal.c @@ -18,79 +18,19 @@ #include #include #include + #include "flash.h" #include "programmer.h" -#include "hwaccess_physmap.h" #include "platform/pci.h" #if defined(__i386__) || defined(__x86_64__) #include "hwaccess_x86_io.h" #endif -int is_laptop = 0; -bool laptop_ok = false; - -bool force_boardenable = false; bool force_boardmismatch = false; enum chipbustype internal_buses_supported = BUS_NONE; -static void internal_chip_writeb(const struct flashctx *flash, uint8_t val, - chipaddr addr) -{ - mmio_writeb(val, (void *) addr); -} - -static void internal_chip_writew(const struct flashctx *flash, uint16_t val, - chipaddr addr) -{ - mmio_writew(val, (void *) addr); -} - -static void internal_chip_writel(const struct flashctx *flash, uint32_t val, - chipaddr addr) -{ - mmio_writel(val, (void *) addr); -} - -static uint8_t internal_chip_readb(const struct flashctx *flash, - const chipaddr addr) -{ - return mmio_readb((void *) addr); -} - -static uint16_t internal_chip_readw(const struct flashctx *flash, - const chipaddr addr) -{ - return mmio_readw((void *) addr); -} - -static uint32_t internal_chip_readl(const struct flashctx *flash, - const chipaddr addr) -{ - return mmio_readl((void *) addr); -} - -static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf, - const chipaddr addr, size_t len) -{ - mmio_readn((void *)addr, buf, len); - return; -} - -static const struct par_master par_master_internal = { - .map_flash_region = physmap, - .unmap_flash_region = physunmap, - .chip_readb = internal_chip_readb, - .chip_readw = internal_chip_readw, - .chip_readl = internal_chip_readl, - .chip_readn = internal_chip_readn, - .chip_writeb = internal_chip_writeb, - .chip_writew = internal_chip_writew, - .chip_writel = internal_chip_writel, - .chip_writen = fallback_chip_writen, -}; - static int get_params(const struct programmer_cfg *cfg, bool *boardenable, bool *boardmismatch, bool *force_laptop, bool *not_a_laptop, @@ -164,6 +104,39 @@ static int get_params(const struct programmer_cfg *cfg, return 0; } +static void report_nonwl_laptop_detected(const struct board_cfg *bcfg) +{ + const int is_laptop = bcfg->is_laptop; + const bool laptop_ok = bcfg->laptop_ok; + + if (!is_laptop || laptop_ok) + return; + + msg_pinfo("========================================================================\n"); + if (is_laptop == 1) { + msg_pinfo("You seem to be running flashrom on an unknown laptop. Some\n" + "internal buses have been disabled for safety reasons.\n\n"); + } else { + msg_pinfo("You may be running flashrom on an unknown laptop. We could not\n" + "detect this for sure because your vendor has not set up the SMBIOS\n" + "tables correctly. Some internal buses have been disabled for\n" + "safety reasons. You can enforce using all buses by adding\n" + " -p internal:laptop=this_is_not_a_laptop\n" + "to the command line, but please read the following warning if you\n" + "are not sure.\n\n"); + } + msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n" + "recommend to use the vendor flashing utility. The embedded controller\n" + "(EC) in these machines often interacts badly with flashing.\n" + "See the manpage and https://flashrom.org/Laptops for details.\n\n" + "If flash is shared with the EC, erase is guaranteed to brick your laptop\n" + "and write may brick your laptop.\n" + "Read and probe may irritate your EC and cause fan failure, backlight\n" + "failure and sudden poweroff.\n" + "You have been warned.\n" + "========================================================================\n"); +} + static int internal_init(const struct programmer_cfg *cfg) { int ret = 0; @@ -175,6 +148,8 @@ static int internal_init(const struct programmer_cfg *cfg) const char *cb_vendor = NULL; const char *cb_model = NULL; #endif + bool force_boardenable = false; + struct board_cfg bcfg = {0}; ret = get_params(cfg, &force_boardenable, &force_boardmismatch, @@ -226,12 +201,12 @@ static int internal_init(const struct programmer_cfg *cfg) } } - is_laptop = 2; /* Assume that we don't know by default. */ + bcfg.is_laptop = 2; /* Assume that we don't know by default. */ - dmi_init(); + dmi_init(&bcfg.is_laptop); /* In case Super I/O probing would cause pretty explosions. */ - board_handle_before_superio(); + board_handle_before_superio(&bcfg, force_boardenable); /* Probe for the Super I/O chip and fill global struct superio. */ probe_superio(); @@ -244,24 +219,26 @@ static int internal_init(const struct programmer_cfg *cfg) #endif /* Check laptop whitelist. */ - board_handle_before_laptop(); + board_handle_before_laptop(&bcfg, force_boardenable); /* * Disable all internal buses by default if we are not sure * this isn't a laptop. Board-enables may override this, * non-legacy buses (SPI and opaque atm) are probed anyway. */ - if (is_laptop && !(laptop_ok || force_laptop || (not_a_laptop && is_laptop == 2))) + if (bcfg.is_laptop && !(bcfg.laptop_ok || force_laptop || (not_a_laptop && bcfg.is_laptop == 2))) internal_buses_supported = BUS_NONE; /* try to enable it. Failure IS an option, since not all motherboards * really need this to be done, etc., etc. */ - ret = chipset_flash_enable(cfg); + struct programmer_cfg icfg = *cfg; + icfg.bcfg = &bcfg; + ret = chipset_flash_enable(&icfg); if (ret == -2) { msg_perr("WARNING: No chipset found. Flash detection " "will most likely fail.\n"); - } else if (ret == ERROR_FATAL) { + } else if (ret == ERROR_FLASHROM_FATAL) { goto internal_init_exit; } @@ -270,42 +247,18 @@ static int internal_init(const struct programmer_cfg *cfg) * parallel writes on IT8705F. Also, this handles the manual chip select for Gigabyte's DualBIOS. */ init_superio_ite(cfg); - if (board_flash_enable(board_vendor, board_model, cb_vendor, cb_model)) { + if (board_flash_enable(&bcfg, + board_vendor, board_model, cb_vendor, cb_model, force_boardenable)) { msg_perr("Aborting to be safe.\n"); ret = 1; goto internal_init_exit; } #endif - if (internal_buses_supported & BUS_NONSPI) - register_par_master(&par_master_internal, internal_buses_supported, NULL); + internal_par_init(internal_buses_supported); /* Report if a non-whitelisted laptop is detected that likely uses a legacy bus. */ - if (is_laptop && !laptop_ok) { - msg_pinfo("========================================================================\n"); - if (is_laptop == 1) { - msg_pinfo("You seem to be running flashrom on an unknown laptop. Some\n" - "internal buses have been disabled for safety reasons.\n\n"); - } else { - msg_pinfo("You may be running flashrom on an unknown laptop. We could not\n" - "detect this for sure because your vendor has not set up the SMBIOS\n" - "tables correctly. Some internal buses have been disabled for\n" - "safety reasons. You can enforce using all buses by adding\n" - " -p internal:laptop=this_is_not_a_laptop\n" - "to the command line, but please read the following warning if you\n" - "are not sure.\n\n"); - } - msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n" - "recommend to use the vendor flashing utility. The embedded controller\n" - "(EC) in these machines often interacts badly with flashing.\n" - "See the manpage and https://flashrom.org/Laptops for details.\n\n" - "If flash is shared with the EC, erase is guaranteed to brick your laptop\n" - "and write may brick your laptop.\n" - "Read and probe may irritate your EC and cause fan failure, backlight\n" - "failure and sudden poweroff.\n" - "You have been warned.\n" - "========================================================================\n"); - } + report_nonwl_laptop_detected(&bcfg); ret = 0; diff --git a/internal_par.c b/internal_par.c new file mode 100644 index 000000000..e8e387cad --- /dev/null +++ b/internal_par.c @@ -0,0 +1,79 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2009 Carl-Daniel Hailfinger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "programmer.h" +#include "hwaccess_physmap.h" + +static void internal_chip_writeb(const struct flashctx *flash, uint8_t val, + chipaddr addr) +{ + mmio_writeb(val, (void *) addr); +} + +static void internal_chip_writew(const struct flashctx *flash, uint16_t val, + chipaddr addr) +{ + mmio_writew(val, (void *) addr); +} + +static void internal_chip_writel(const struct flashctx *flash, uint32_t val, + chipaddr addr) +{ + mmio_writel(val, (void *) addr); +} + +static uint8_t internal_chip_readb(const struct flashctx *flash, + const chipaddr addr) +{ + return mmio_readb((void *) addr); +} + +static uint16_t internal_chip_readw(const struct flashctx *flash, + const chipaddr addr) +{ + return mmio_readw((void *) addr); +} + +static uint32_t internal_chip_readl(const struct flashctx *flash, + const chipaddr addr) +{ + return mmio_readl((void *) addr); +} + +static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf, + const chipaddr addr, size_t len) +{ + mmio_readn((void *)addr, buf, len); + return; +} + +static const struct par_master par_master_internal = { + .map_flash_region = physmap, + .unmap_flash_region = physunmap, + .chip_readb = internal_chip_readb, + .chip_readw = internal_chip_readw, + .chip_readl = internal_chip_readl, + .chip_readn = internal_chip_readn, + .chip_writeb = internal_chip_writeb, + .chip_writew = internal_chip_writew, + .chip_writel = internal_chip_writel, +}; + +void internal_par_init(enum chipbustype buses) +{ + if (buses & BUS_NONSPI) + register_par_master(&par_master_internal, internal_buses_supported, NULL); +} diff --git a/it8212.c b/it8212.c index 8fe2b5985..3c1161d60 100644 --- a/it8212.c +++ b/it8212.c @@ -64,13 +64,7 @@ static int it8212_shutdown(void *par_data) static const struct par_master par_master_it8212 = { .chip_readb = it8212_chip_readb, - .chip_readw = fallback_chip_readw, - .chip_readl = fallback_chip_readl, - .chip_readn = fallback_chip_readn, .chip_writeb = it8212_chip_writeb, - .chip_writew = fallback_chip_writew, - .chip_writel = fallback_chip_writel, - .chip_writen = fallback_chip_writen, .shutdown = it8212_shutdown, }; diff --git a/it87spi.c b/it87spi.c index d82baee7d..a46f3efe5 100644 --- a/it87spi.c +++ b/it87spi.c @@ -148,7 +148,7 @@ static int it8716f_spi_page_program(struct flashctx *flash, const uint8_t *buf, if((status & SPI_SR_WIP) == 0) return 0; - programmer_delay(1000); + default_delay(1000); } return 0; } @@ -316,14 +316,12 @@ static const struct spi_master spi_master_it87xx = { .max_data_read = 3, .max_data_write = MAX_DATA_UNSPECIFIED, .command = it8716f_spi_send_command, - .multicommand = default_spi_send_multicommand, .map_flash_region = physmap, .unmap_flash_region = physunmap, .read = it8716f_spi_chip_read, .write_256 = it8716f_spi_chip_write_256, .write_aai = spi_chip_write_1, .shutdown = it8716f_shutdown, - .probe_opcode = default_spi_probe_opcode, }; static uint16_t it87spi_probe(const struct programmer_cfg *cfg, uint16_t port) diff --git a/ite_ec.c b/ite_ec.c index c0324a8e5..56cbcacdb 100644 --- a/ite_ec.c +++ b/ite_ec.c @@ -503,7 +503,7 @@ static int ite_ec_probe(struct flashctx *flash) flash->chip->page_size = BYTES_PER_BLOCK; flash->chip->total_size = ctx_data->rom_size_in_blocks * KBYTES_PER_BLOCK; /* This EC supports only write granularity of 64KiB */ - flash->chip->gran = write_gran_64kbytes; + flash->chip->gran = WRITE_GRAN_64KBYTES; /* * Erase operation must be done in one sway. * So report an eraser for the whole chip size. diff --git a/jedec.c b/jedec.c index 2542f3e67..2d18de7f3 100644 --- a/jedec.c +++ b/jedec.c @@ -38,14 +38,11 @@ uint8_t oddparity(uint8_t val) static void toggle_ready_jedec_common(const struct flashctx *flash, chipaddr dst, unsigned int delay) { unsigned int i = 0; - uint8_t tmp1, tmp2; - - tmp1 = chip_readb(flash, dst) & 0x40; + uint8_t tmp1 = chip_readb(flash, dst) & 0x40; while (i++ < 0xFFFFFFF) { - if (delay) - programmer_delay(delay); - tmp2 = chip_readb(flash, dst) & 0x40; + programmer_delay(flash, delay); + uint8_t tmp2 = chip_readb(flash, dst) & 0x40; if (tmp1 == tmp2) { break; } @@ -67,8 +64,9 @@ void toggle_ready_jedec(const struct flashctx *flash, chipaddr dst) * Given that erase is slow on all chips, it is recommended to use * toggle_ready_jedec_slow in erase functions. */ -static void toggle_ready_jedec_slow(const struct flashctx *flash, chipaddr dst) +static void toggle_ready_jedec_slow(const struct flashctx *flash) { + const chipaddr dst = flash->virtual_memory; toggle_ready_jedec_common(flash, dst, 8 * 1000); } @@ -76,12 +74,11 @@ void data_polling_jedec(const struct flashctx *flash, chipaddr dst, uint8_t data) { unsigned int i = 0; - uint8_t tmp; data &= 0x80; while (i++ < 0xFFFFFFF) { - tmp = chip_readb(flash, dst) & 0x80; + uint8_t tmp = chip_readb(flash, dst) & 0x80; if (tmp == data) { break; } @@ -109,10 +106,11 @@ static unsigned int getaddrmask(const struct flashchip *chip) } } -static void start_program_jedec_common(const struct flashctx *flash, unsigned int mask) +static void start_program_jedec_common(const struct flashctx *flash) { - chipaddr bios = flash->virtual_memory; - bool shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED); + const chipaddr bios = flash->virtual_memory; + const bool shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED); + const unsigned int mask = getaddrmask(flash->chip); chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask)); @@ -121,8 +119,8 @@ static void start_program_jedec_common(const struct flashctx *flash, unsigned in int probe_jedec_29gl(struct flashctx *flash) { - unsigned int mask = getaddrmask(flash->chip); - chipaddr bios = flash->virtual_memory; + const unsigned int mask = getaddrmask(flash->chip); + const chipaddr bios = flash->virtual_memory; const struct flashchip *chip = flash->chip; /* Reset chip to a clean slate */ @@ -143,7 +141,7 @@ int probe_jedec_29gl(struct flashctx *flash) /* Issue JEDEC Product ID Exit command */ chip_writeb(flash, 0xF0, bios + (0x5555 & mask)); - msg_cdbg("%s: man_id 0x%02x, dev_id 0x%06x", __func__, man_id, dev_id); + msg_cdbg("%s: man_id 0x%02"PRIx32", dev_id 0x%06"PRIx32"", __func__, man_id, dev_id); if (!oddparity(man_id)) msg_cdbg(", man_id parity violation"); @@ -165,59 +163,64 @@ int probe_jedec_29gl(struct flashctx *flash) return 1; } -static int probe_jedec_common(struct flashctx *flash, unsigned int mask) +static int probe_timings(const struct flashchip *chip, unsigned int *tenter, unsigned int *texit) { - chipaddr bios = flash->virtual_memory; + if (chip->probe_timing > 0) { + *tenter = *texit = chip->probe_timing; + } else if (chip->probe_timing == TIMING_ZERO) { /* No delay. */ + *tenter = *texit = 0; + } else if (chip->probe_timing == TIMING_FIXME) { /* == _IGNORED */ + msg_cdbg("Chip lacks correct probe timing information, using default 10ms/40us. "); + *tenter = 10000; + *texit = 40; + } else { + msg_cerr("Chip has negative value in probe_timing, failing without chip access\n"); + return -1; + } + + return 0; +} + +int probe_jedec(struct flashctx *flash) +{ + const chipaddr bios = flash->virtual_memory; const struct flashchip *chip = flash->chip; - bool shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED); + const bool shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED); + const unsigned int mask = getaddrmask(flash->chip); uint8_t id1, id2; uint32_t largeid1, largeid2; uint32_t flashcontent1, flashcontent2; unsigned int probe_timing_enter, probe_timing_exit; - if (chip->probe_timing > 0) - probe_timing_enter = probe_timing_exit = chip->probe_timing; - else if (chip->probe_timing == TIMING_ZERO) { /* No delay. */ - probe_timing_enter = probe_timing_exit = 0; - } else if (chip->probe_timing == TIMING_FIXME) { /* == _IGNORED */ - msg_cdbg("Chip lacks correct probe timing information, using default 10ms/40us. "); - probe_timing_enter = 10000; - probe_timing_exit = 40; - } else { - msg_cerr("Chip has negative value in probe_timing, failing without chip access\n"); + if (probe_timings(chip, &probe_timing_enter, &probe_timing_exit) < 0) return 0; - } /* Earlier probes might have been too fast for the chip to enter ID * mode completely. Allow the chip to finish this before seeing a * reset command. */ - if (probe_timing_enter) - programmer_delay(probe_timing_enter); + programmer_delay(flash, probe_timing_enter); /* Reset chip to a clean slate */ - if ((chip->feature_bits & FEATURE_RESET_MASK) == FEATURE_LONG_RESET) - { + if ((chip->feature_bits & FEATURE_RESET_MASK) == FEATURE_LONG_RESET) { chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); if (probe_timing_exit) - programmer_delay(10); + programmer_delay(flash, 10); chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask)); if (probe_timing_exit) - programmer_delay(10); + programmer_delay(flash, 10); } chip_writeb(flash, 0xF0, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); - if (probe_timing_exit) - programmer_delay(probe_timing_exit); + programmer_delay(flash, probe_timing_exit); /* Issue JEDEC Product ID Entry command */ chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); if (probe_timing_enter) - programmer_delay(10); + programmer_delay(flash, 10); chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask)); if (probe_timing_enter) - programmer_delay(10); + programmer_delay(flash, 10); chip_writeb(flash, 0x90, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); - if (probe_timing_enter) - programmer_delay(probe_timing_enter); + programmer_delay(flash, probe_timing_enter); /* Read product ID */ id1 = chip_readb(flash, bios + (0x00 << shifted)); @@ -238,20 +241,18 @@ static int probe_jedec_common(struct flashctx *flash, unsigned int mask) } /* Issue JEDEC Product ID Exit command */ - if ((chip->feature_bits & FEATURE_RESET_MASK) == FEATURE_LONG_RESET) - { + if ((chip->feature_bits & FEATURE_RESET_MASK) == FEATURE_LONG_RESET) { chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); if (probe_timing_exit) - programmer_delay(10); + programmer_delay(flash, 10); chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask)); if (probe_timing_exit) - programmer_delay(10); + programmer_delay(flash, 10); } chip_writeb(flash, 0xF0, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); - if (probe_timing_exit) - programmer_delay(probe_timing_exit); + programmer_delay(flash, probe_timing_exit); - msg_cdbg("%s: id1 0x%02x, id2 0x%02x", __func__, largeid1, largeid2); + msg_cdbg("%s: id1 0x%02"PRIx32", id2 0x%02"PRIx32"", __func__, largeid1, largeid2); if (!oddparity(id1)) msg_cdbg(", id1 parity violation"); @@ -281,144 +282,104 @@ static int probe_jedec_common(struct flashctx *flash, unsigned int mask) return 1; } -static int erase_sector_jedec_common(struct flashctx *flash, unsigned int page, - unsigned int pagesize, unsigned int mask) +static void issuecmd(const struct flashctx *flash, uint8_t op, unsigned int operand) { - chipaddr bios = flash->virtual_memory; + const chipaddr bios = flash->virtual_memory; bool shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED); - unsigned int delay_us = 0; + const unsigned int mask = getaddrmask(flash->chip); + unsigned int delay_us = (flash->chip->probe_timing == TIMING_ZERO) ? 0 : 10; - if(flash->chip->probe_timing != TIMING_ZERO) - delay_us = 10; + if (!operand) + operand = (shifted ? 0x2AAA : 0x5555) & mask; - /* Issue the Sector Erase command */ chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); - programmer_delay(delay_us); + programmer_delay(flash, delay_us); chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask)); - programmer_delay(delay_us); - chip_writeb(flash, 0x80, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); - programmer_delay(delay_us); + programmer_delay(flash, delay_us); + chip_writeb(flash, op, bios + operand); + programmer_delay(flash, delay_us); +} - chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); - programmer_delay(delay_us); - chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask)); - programmer_delay(delay_us); - chip_writeb(flash, 0x30, bios + page); - programmer_delay(delay_us); +int erase_sector_jedec(struct flashctx *flash, unsigned int page, unsigned int size) +{ + /* Issue the Sector Erase command */ + issuecmd(flash, 0x80, 0); + issuecmd(flash, 0x30, page); - /* wait for Toggle bit ready */ - toggle_ready_jedec_slow(flash, bios); + /* Wait for Toggle bit ready */ + toggle_ready_jedec_slow(flash); /* FIXME: Check the status register for errors. */ return 0; } -static int erase_block_jedec_common(struct flashctx *flash, unsigned int block, - unsigned int blocksize, unsigned int mask) +int erase_block_jedec(struct flashctx *flash, unsigned int block, unsigned int size) { - chipaddr bios = flash->virtual_memory; - bool shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED); - unsigned int delay_us = 0; - - if(flash->chip->probe_timing != TIMING_ZERO) - delay_us = 10; + /* Issue the Block Erase command */ + issuecmd(flash, 0x80, 0); + issuecmd(flash, 0x50, block); - /* Issue the Sector Erase command */ - chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); - programmer_delay(delay_us); - chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask)); - programmer_delay(delay_us); - chip_writeb(flash, 0x80, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); - programmer_delay(delay_us); - - chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); - programmer_delay(delay_us); - chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask)); - programmer_delay(delay_us); - chip_writeb(flash, 0x50, bios + block); - programmer_delay(delay_us); - - /* wait for Toggle bit ready */ - toggle_ready_jedec_slow(flash, bios); + /* Wait for Toggle bit ready */ + toggle_ready_jedec_slow(flash); /* FIXME: Check the status register for errors. */ return 0; } -static int erase_chip_jedec_common(struct flashctx *flash, unsigned int mask) +/* erase chip with block_erase() prototype */ +int erase_chip_block_jedec(struct flashctx *flash, unsigned int addr, unsigned int blocksize) { - chipaddr bios = flash->virtual_memory; - bool shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED); - unsigned int delay_us = 0; - - if(flash->chip->probe_timing != TIMING_ZERO) - delay_us = 10; - - /* Issue the JEDEC Chip Erase command */ - chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); - programmer_delay(delay_us); - chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask)); - programmer_delay(delay_us); - chip_writeb(flash, 0x80, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); - programmer_delay(delay_us); + if ((addr != 0) || (blocksize != flash->chip->total_size * 1024)) { + msg_cerr("%s called with incorrect arguments\n", __func__); + return -1; + } - chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); - programmer_delay(delay_us); - chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask)); - programmer_delay(delay_us); - chip_writeb(flash, 0x10, bios + ((shifted ? 0x2AAA : 0x5555) & mask)); - programmer_delay(delay_us); + /* Issue the JEDEC Chip Erase command */ + issuecmd(flash, 0x80, 0); + issuecmd(flash, 0x10, 0); - toggle_ready_jedec_slow(flash, bios); + toggle_ready_jedec_slow(flash); /* FIXME: Check the status register for errors. */ return 0; } static int write_byte_program_jedec_common(const struct flashctx *flash, const uint8_t *src, - chipaddr dst, unsigned int mask) + chipaddr dst) { - int tried = 0, failed = 0; - chipaddr bios = flash->virtual_memory; + int tries = 0; /* If the data is 0xFF, don't program it and don't complain. */ if (*src == 0xFF) { return 0; } -retry: - /* Issue JEDEC Byte Program command */ - start_program_jedec_common(flash, mask); + for (; tries < MAX_REFLASH_TRIES; tries++) { + const chipaddr bios = flash->virtual_memory; + /* Issue JEDEC Byte Program command */ + start_program_jedec_common(flash); - /* transfer data from source to destination */ - chip_writeb(flash, *src, dst); - toggle_ready_jedec(flash, bios); + /* transfer data from source to destination */ + chip_writeb(flash, *src, dst); + toggle_ready_jedec(flash, bios); - if (chip_readb(flash, dst) != *src && tried++ < MAX_REFLASH_TRIES) { - goto retry; + if (chip_readb(flash, dst) == *src) + break; } - if (tried >= MAX_REFLASH_TRIES) - failed = 1; - - return failed; + return (tries >= MAX_REFLASH_TRIES) ? 1 : 0; } /* chunksize is 1 */ int write_jedec_1(struct flashctx *flash, const uint8_t *src, unsigned int start, unsigned int len) { - unsigned int i; int failed = 0; chipaddr dst = flash->virtual_memory + start; - chipaddr olddst; - unsigned int mask; - - mask = getaddrmask(flash->chip); + const chipaddr olddst = dst; - olddst = dst; - for (i = 0; i < len; i++) { - if (write_byte_program_jedec_common(flash, src, dst, mask)) + for (unsigned int i = 0; i < len; i++) { + if (write_byte_program_jedec_common(flash, src, dst)) failed = 1; dst++, src++; update_progress(flash, FLASHROM_PROGRESS_WRITE, i + 1, len); @@ -429,45 +390,43 @@ int write_jedec_1(struct flashctx *flash, const uint8_t *src, unsigned int start return failed; } -static int write_page_write_jedec_common(struct flashctx *flash, const uint8_t *src, +static int jedec_write_page(struct flashctx *flash, const uint8_t *src, unsigned int start, unsigned int page_size) { - unsigned int i; - int tried = 0, failed; + int tries = 0, failed; const uint8_t *s = src; - chipaddr bios = flash->virtual_memory; + const chipaddr bios = flash->virtual_memory; chipaddr dst = bios + start; chipaddr d = dst; - unsigned int mask; - - mask = getaddrmask(flash->chip); -retry: - /* Issue JEDEC Start Program command */ - start_program_jedec_common(flash, mask); - - /* transfer data from source to destination */ - for (i = 0; i < page_size; i++) { - /* If the data is 0xFF, don't program it */ - if (*src != 0xFF) - chip_writeb(flash, *src, dst); - dst++; - src++; - } + for (; tries < MAX_REFLASH_TRIES; tries++) { + /* Issue JEDEC Start Program command */ + start_program_jedec_common(flash); + + /* transfer data from source to destination */ + for (unsigned int i = 0; i < page_size; i++) { + /* If the data is 0xFF, don't program it */ + if (*src != 0xFF) + chip_writeb(flash, *src, dst); + dst++; + src++; + } - toggle_ready_jedec(flash, dst - 1); + toggle_ready_jedec(flash, dst - 1); - dst = d; - src = s; - failed = verify_range(flash, src, start, page_size); + dst = d; + src = s; + failed = verify_range(flash, src, start, page_size); + if (!failed) + break; - if (failed && tried++ < MAX_REFLASH_TRIES) { msg_cerr("retrying.\n"); - goto retry; } + if (failed) { msg_cerr(" page 0x%" PRIxPTR " failed!\n", (d - bios) / page_size); } + return failed; } @@ -481,14 +440,14 @@ static int write_page_write_jedec_common(struct flashctx *flash, const uint8_t * int write_jedec(struct flashctx *flash, const uint8_t *buf, unsigned int start, int unsigned len) { - unsigned int i, starthere, lenhere; + unsigned int starthere, lenhere; /* FIXME: page_size is the wrong variable. We need max_writechunk_size * in struct flashctx to do this properly. All chips using * write_jedec have page_size set to max_writechunk_size, so * we're OK for now. */ - unsigned int page_size = flash->chip->page_size; - unsigned int nwrites = (start + len - 1) / page_size; + const unsigned int page_size = flash->chip->page_size; + const unsigned int nwrites = (start + len - 1) / page_size; /* Warning: This loop has a very unusual condition and body. * The loop needs to go through each page with at least one affected @@ -499,247 +458,17 @@ int write_jedec(struct flashctx *flash, const uint8_t *buf, unsigned int start, * (start + len - 1) / page_size. Since we want to include that last * page as well, the loop condition uses <=. */ - for (i = start / page_size; i <= nwrites; i++) { + for (unsigned int i = start / page_size; i <= nwrites; i++) { /* Byte position of the first byte in the range in this page. */ /* starthere is an offset to the base address of the chip. */ starthere = max(start, i * page_size); /* Length of bytes in the range in this page. */ lenhere = min(start + len, (i + 1) * page_size) - starthere; - if (write_page_write_jedec_common(flash, buf + starthere - start, starthere, lenhere)) + if (jedec_write_page(flash, buf + starthere - start, starthere, lenhere)) return 1; update_progress(flash, FLASHROM_PROGRESS_WRITE, i + 1, nwrites + 1); } return 0; } - -/* erase chip with block_erase() prototype */ -int erase_chip_block_jedec(struct flashctx *flash, unsigned int addr, - unsigned int blocksize) -{ - unsigned int mask; - - mask = getaddrmask(flash->chip); - if ((addr != 0) || (blocksize != flash->chip->total_size * 1024)) { - msg_cerr("%s called with incorrect arguments\n", - __func__); - return -1; - } - return erase_chip_jedec_common(flash, mask); -} - -int probe_jedec(struct flashctx *flash) -{ - unsigned int mask; - - mask = getaddrmask(flash->chip); - return probe_jedec_common(flash, mask); -} - -int erase_sector_jedec(struct flashctx *flash, unsigned int page, - unsigned int size) -{ - unsigned int mask; - - mask = getaddrmask(flash->chip); - return erase_sector_jedec_common(flash, page, size, mask); -} - -int erase_block_jedec(struct flashctx *flash, unsigned int page, - unsigned int size) -{ - unsigned int mask; - - mask = getaddrmask(flash->chip); - return erase_block_jedec_common(flash, page, size, mask); -} - -struct unlockblock { - unsigned int size; - unsigned int count; -}; - -typedef int (*unlockblock_func)(const struct flashctx *flash, chipaddr offset); -static int regspace2_walk_unlockblocks(const struct flashctx *flash, const struct unlockblock *block, unlockblock_func func) -{ - chipaddr off = flash->virtual_registers + 2; - while (block->count != 0) { - unsigned int j; - for (j = 0; j < block->count; j++) { - if (func(flash, off)) - return -1; - off += block->size; - } - block++; - } - return 0; -} - -#define REG2_RWLOCK ((1 << 2) | (1 << 0)) -#define REG2_LOCKDOWN (1 << 1) -#define REG2_MASK (REG2_RWLOCK | REG2_LOCKDOWN) - -static int printlock_regspace2_block(const struct flashctx *flash, chipaddr lockreg) -{ - uint8_t state = chip_readb(flash, lockreg); - msg_cdbg("Lock status of block at 0x%0*" PRIxPTR " is ", PRIxPTR_WIDTH, lockreg); - switch (state & REG2_MASK) { - case 0: - msg_cdbg("Full Access.\n"); - break; - case 1: - msg_cdbg("Write Lock (Default State).\n"); - break; - case 2: - msg_cdbg("Locked Open (Full Access, Locked Down).\n"); - break; - case 3: - msg_cdbg("Write Lock, Locked Down.\n"); - break; - case 4: - msg_cdbg("Read Lock.\n"); - break; - case 5: - msg_cdbg("Read/Write Lock.\n"); - break; - case 6: - msg_cdbg("Read Lock, Locked Down.\n"); - break; - case 7: - msg_cdbg("Read/Write Lock, Locked Down.\n"); - break; - } - return 0; -} - -static int printlock_regspace2_uniform(struct flashctx *flash, unsigned long block_size) -{ - const unsigned int elems = flash->chip->total_size * 1024 / block_size; - struct unlockblock blocks[2] = {{.size = block_size, .count = elems}}; - return regspace2_walk_unlockblocks(flash, blocks, &printlock_regspace2_block); -} - -int printlock_regspace2_uniform_64k(struct flashctx *flash) -{ - return printlock_regspace2_uniform(flash, 64 * 1024); -} - -int printlock_regspace2_block_eraser_0(struct flashctx *flash) -{ - // FIXME: this depends on the eraseblocks not to be filled up completely (i.e. to be null-terminated). - const struct unlockblock *unlockblocks = - (const struct unlockblock *)flash->chip->block_erasers[0].eraseblocks; - return regspace2_walk_unlockblocks(flash, unlockblocks, &printlock_regspace2_block); -} - -int printlock_regspace2_block_eraser_1(struct flashctx *flash) -{ - // FIXME: this depends on the eraseblocks not to be filled up completely (i.e. to be null-terminated). - const struct unlockblock *unlockblocks = - (const struct unlockblock *)flash->chip->block_erasers[1].eraseblocks; - return regspace2_walk_unlockblocks(flash, unlockblocks, &printlock_regspace2_block); -} - -/* Try to change the lock register at address lockreg from cur to new. - * - * - Try to unlock the lock bit if requested and it is currently set (although this is probably futile). - * - Try to change the read/write bits if requested. - * - Try to set the lockdown bit if requested. - * Return an error immediately if any of this fails. */ -static int changelock_regspace2_block(const struct flashctx *flash, chipaddr lockreg, uint8_t cur, uint8_t new) -{ - /* Only allow changes to known read/write/lockdown bits */ - if (((cur ^ new) & ~REG2_MASK) != 0) { - msg_cerr("Invalid lock change from 0x%02x to 0x%02x requested at 0x%0*" PRIxPTR "!\n" - "Please report a bug at flashrom@flashrom.org\n", - cur, new, PRIxPTR_WIDTH, lockreg); - return -1; - } - - /* Exit early if no change (of read/write/lockdown bits) was requested. */ - if (((cur ^ new) & REG2_MASK) == 0) { - msg_cdbg2("Lock bits at 0x%0*" PRIxPTR " not changed.\n", PRIxPTR_WIDTH, lockreg); - return 0; - } - - /* Normally the lockdown bit can not be cleared. Try nevertheless if requested. */ - if ((cur & REG2_LOCKDOWN) && !(new & REG2_LOCKDOWN)) { - chip_writeb(flash, cur & ~REG2_LOCKDOWN, lockreg); - cur = chip_readb(flash, lockreg); - if ((cur & REG2_LOCKDOWN) == REG2_LOCKDOWN) { - msg_cwarn("Lockdown can't be removed at 0x%0*" PRIxPTR "! New value: 0x%02x.\n", - PRIxPTR_WIDTH, lockreg, cur); - return -1; - } - } - - /* Change read and/or write bit */ - if ((cur ^ new) & REG2_RWLOCK) { - /* Do not lockdown yet. */ - uint8_t wanted = (cur & ~REG2_RWLOCK) | (new & REG2_RWLOCK); - chip_writeb(flash, wanted, lockreg); - cur = chip_readb(flash, lockreg); - if (cur != wanted) { - msg_cerr("Changing lock bits failed at 0x%0*" PRIxPTR "! New value: 0x%02x.\n", - PRIxPTR_WIDTH, lockreg, cur); - return -1; - } - msg_cdbg("Changed lock bits at 0x%0*" PRIxPTR " to 0x%02x.\n", - PRIxPTR_WIDTH, lockreg, cur); - } - - /* Eventually, enable lockdown if requested. */ - if (!(cur & REG2_LOCKDOWN) && (new & REG2_LOCKDOWN)) { - chip_writeb(flash, new, lockreg); - cur = chip_readb(flash, lockreg); - if (cur != new) { - msg_cerr("Enabling lockdown FAILED at 0x%0*" PRIxPTR "! New value: 0x%02x.\n", - PRIxPTR_WIDTH, lockreg, cur); - return -1; - } - msg_cdbg("Enabled lockdown at 0x%0*" PRIxPTR ".\n", PRIxPTR_WIDTH, lockreg); - } - - return 0; -} - -static int unlock_regspace2_block_generic(const struct flashctx *flash, chipaddr lockreg) -{ - uint8_t old = chip_readb(flash, lockreg); - /* We don't care for the lockdown bit as long as the RW locks are 0 after we're done */ - return changelock_regspace2_block(flash, lockreg, old, old & ~REG2_RWLOCK); -} - -static int unlock_regspace2_uniform(struct flashctx *flash, unsigned long block_size) -{ - const unsigned int elems = flash->chip->total_size * 1024 / block_size; - struct unlockblock blocks[2] = {{.size = block_size, .count = elems}}; - return regspace2_walk_unlockblocks(flash, blocks, &unlock_regspace2_block_generic); -} - -int unlock_regspace2_uniform_64k(struct flashctx *flash) -{ - return unlock_regspace2_uniform(flash, 64 * 1024); -} - -int unlock_regspace2_uniform_32k(struct flashctx *flash) -{ - return unlock_regspace2_uniform(flash, 32 * 1024); -} - -int unlock_regspace2_block_eraser_0(struct flashctx *flash) -{ - // FIXME: this depends on the eraseblocks not to be filled up completely (i.e. to be null-terminated). - const struct unlockblock *unlockblocks = - (const struct unlockblock *)flash->chip->block_erasers[0].eraseblocks; - return regspace2_walk_unlockblocks(flash, unlockblocks, &unlock_regspace2_block_generic); -} - -int unlock_regspace2_block_eraser_1(struct flashctx *flash) -{ - // FIXME: this depends on the eraseblocks not to be filled up completely (i.e. to be null-terminated). - const struct unlockblock *unlockblocks = - (const struct unlockblock *)flash->chip->block_erasers[1].eraseblocks; - return regspace2_walk_unlockblocks(flash, unlockblocks, &unlock_regspace2_block_generic); -} diff --git a/jlink_spi.c b/jlink_spi.c index 63d15b8f8..447629cce 100644 --- a/jlink_spi.c +++ b/jlink_spi.c @@ -51,10 +51,16 @@ /* Minimum target voltage required for operation in mV. */ #define MIN_TARGET_VOLTAGE 1200 +enum cs_wiring { + CS_RESET, /* nCS is wired to nRESET(pin 15) */ + CS_TRST, /* nCS is wired to nTRST(pin 3) */ + CS_TMS, /* nCS is wired to TMS/nCS(pin 7) */ +}; + struct jlink_spi_data { struct jaylink_context *ctx; struct jaylink_device_handle *devh; - bool reset_cs; + enum cs_wiring cs; bool enable_target_power; }; @@ -62,20 +68,27 @@ static bool assert_cs(struct jlink_spi_data *jlink_data) { int ret; - if (jlink_data->reset_cs) { + if (jlink_data->cs == CS_RESET) { ret = jaylink_clear_reset(jlink_data->devh); if (ret != JAYLINK_OK) { msg_perr("jaylink_clear_reset() failed: %s.\n", jaylink_strerror(ret)); return false; } - } else { + } else if (jlink_data->cs == CS_TRST) { ret = jaylink_jtag_clear_trst(jlink_data->devh); if (ret != JAYLINK_OK) { msg_perr("jaylink_jtag_clear_trst() failed: %s.\n", jaylink_strerror(ret)); return false; } + } else { + ret = jaylink_jtag_clear_tms(jlink_data->devh); + + if (ret != JAYLINK_OK) { + msg_perr("jaylink_jtag_clear_tms() failed: %s.\n", jaylink_strerror(ret)); + return false; + } } return true; @@ -85,20 +98,27 @@ static bool deassert_cs(struct jlink_spi_data *jlink_data) { int ret; - if (jlink_data->reset_cs) { + if (jlink_data->cs == CS_RESET) { ret = jaylink_set_reset(jlink_data->devh); if (ret != JAYLINK_OK) { msg_perr("jaylink_set_reset() failed: %s.\n", jaylink_strerror(ret)); return false; } - } else { + } else if (jlink_data->cs == CS_TRST) { ret = jaylink_jtag_set_trst(jlink_data->devh); if (ret != JAYLINK_OK) { msg_perr("jaylink_jtag_set_trst() failed: %s.\n", jaylink_strerror(ret)); return false; } + } else { + ret = jaylink_jtag_set_tms(jlink_data->devh); + + if (ret != JAYLINK_OK) { + msg_perr("jaylink_jtag_set_tms() failed: %s.\n", jaylink_strerror(ret)); + return false; + } } return true; @@ -109,6 +129,7 @@ static int jlink_spi_send_command(const struct flashctx *flash, unsigned int wri { uint32_t length; uint8_t *buffer; + static const uint8_t zeros[JTAG_MAX_TRANSFER_SIZE] = {0}; struct jlink_spi_data *jlink_data = flash->mst->spi.data; length = writecnt + readcnt; @@ -133,10 +154,13 @@ static int jlink_spi_send_command(const struct flashctx *flash, unsigned int wri return SPI_PROGRAMMER_ERROR; } + /* If CS is wired to TMS, TMS should remain zero. */ + const uint8_t *tms_buffer = jlink_data->cs == CS_TMS ? zeros : buffer; + int ret; ret = jaylink_jtag_io(jlink_data->devh, - buffer, buffer, buffer, length * 8, JAYLINK_JTAG_VERSION_2); + tms_buffer, buffer, buffer, length * 8, JAYLINK_JTAG_VERSION_2); if (ret != JAYLINK_OK) { msg_perr("jaylink_jtag_io() failed: %s.\n", jaylink_strerror(ret)); @@ -184,13 +208,10 @@ static const struct spi_master spi_master_jlink_spi = { /* Maximum data write size in one go (excluding opcode+address). */ .max_data_write = JTAG_MAX_TRANSFER_SIZE - 5, .command = jlink_spi_send_command, - .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .features = SPI_MASTER_4BA, .shutdown = jlink_spi_shutdown, - .probe_opcode = default_spi_probe_opcode, }; static int jlink_spi_init(const struct programmer_cfg *cfg) @@ -199,7 +220,7 @@ static int jlink_spi_init(const struct programmer_cfg *cfg) unsigned long speed = 0; struct jaylink_context *jaylink_ctx = NULL; struct jaylink_device_handle *jaylink_devh = NULL; - bool reset_cs; + enum cs_wiring cs; struct jlink_spi_data *jlink_data = NULL; bool enable_target_power; @@ -258,14 +279,16 @@ static int jlink_spi_init(const struct programmer_cfg *cfg) free(arg); - reset_cs = true; + cs = CS_RESET; arg = extract_programmer_param_str(cfg, "cs"); if (arg) { if (!strcasecmp(arg, "reset")) { - reset_cs = true; + cs = CS_RESET; } else if (!strcasecmp(arg, "trst")) { - reset_cs = false; + cs = CS_TRST; + } else if (!strcasecmp(arg, "tms")) { + cs = CS_TMS; } else { msg_perr("Invalid chip select pin specified: '%s'.\n", arg); free(arg); @@ -275,10 +298,12 @@ static int jlink_spi_init(const struct programmer_cfg *cfg) free(arg); - if (reset_cs) + if (cs == CS_RESET) msg_pdbg("Using RESET as chip select signal.\n"); - else + else if (cs == CS_TRST) msg_pdbg("Using TRST as chip select signal.\n"); + else + msg_pdbg("Using TMS/CS as chip select signal.\n"); enable_target_power = false; arg = extract_programmer_param_str(cfg, "power"); @@ -509,7 +534,7 @@ static int jlink_spi_init(const struct programmer_cfg *cfg) /* jaylink_ctx, jaylink_devh are allocated by jaylink_init and jaylink_open */ jlink_data->ctx = jaylink_ctx; jlink_data->devh = jaylink_devh; - jlink_data->reset_cs = reset_cs; + jlink_data->cs = cs; jlink_data->enable_target_power = enable_target_power; /* Ensure that the CS signal is not active initially. */ diff --git a/known_boards.c b/known_boards.c index afc6992d0..c412b8f65 100644 --- a/known_boards.c +++ b/known_boards.c @@ -18,12 +18,7 @@ #include "programmer.h" - -#ifdef CONFIG_PRINT_WIKI #define B(vendor, name, status, url, note) { vendor, name, status, url, note } -#else -#define B(vendor, name, status, url, note) { vendor, name, status } -#endif /* Please keep this list alphabetically ordered by vendor/board. */ const struct board_info boards_known[] = { diff --git a/layout.c b/layout.c index 0212699ab..e46e61ae5 100644 --- a/layout.c +++ b/layout.c @@ -61,7 +61,7 @@ static struct romentry *_layout_entry_by_name( if (!layout || !name) return NULL; while ((entry = mutable_layout_next(layout, entry))) { - if (!strcmp(entry->name, name)) + if (!strcmp(entry->region.name, name)) return entry; } return NULL; @@ -114,27 +114,60 @@ int layout_from_file(struct flashrom_layout **layout, const char *name) } #endif -/* register an include argument (-i) for later processing */ -int register_include_arg(struct layout_include_args **args, const char *arg) +static bool parse_include_args(const char *arg, char **name, char **file) { - struct layout_include_args *tmp; char *colon; - char *name; - char *file; + char *tmp_name; + char *tmp_file = NULL; /* file is optional, so defaults to NULL */ if (arg == NULL) { msg_gerr(" is a bad region name.\n"); - return 1; + return false; } /* -i [:] */ colon = strchr(arg, ':'); if (colon && !colon[1]) { msg_gerr("Missing filename parameter in %s\n", arg); - return 1; + return false; + } + + if (colon) { + tmp_name = strndup(arg, colon - arg); + if (!tmp_name) { + msg_gerr("Out of memory\n"); + goto error; + } + + tmp_file = strdup(colon + 1); + if (!tmp_file) { + msg_gerr("Out of memory\n"); + goto error; + } + } else { + tmp_name = strdup(arg); } - name = colon ? strndup(arg, colon - arg) : strdup(arg); - file = colon ? strdup(colon + 1) : NULL; + + *name = tmp_name; + *file = tmp_file; + + return true; + +error: + free(tmp_name); + free(tmp_file); + return false; +} + +/* register an include argument (-i) for later processing */ +int register_include_arg(struct layout_include_args **args, const char *arg) +{ + struct layout_include_args *tmp; + char *name; + char *file; + + if (!parse_include_args(arg, &name, &file)) + return 1; for (tmp = *args; tmp; tmp = tmp->next) { if (!strcmp(tmp->name, name)) { @@ -145,7 +178,7 @@ int register_include_arg(struct layout_include_args **args, const char *arg) tmp = malloc(sizeof(*tmp)); if (tmp == NULL) { - msg_gerr("Could not allocate memory"); + msg_gerr("Out of memory\n"); goto error; } @@ -161,6 +194,15 @@ int register_include_arg(struct layout_include_args **args, const char *arg) return 1; } +static char *sanitise_filename(char *filename) +{ + for (unsigned i = 0; filename[i]; i++) { + if (isspace((unsigned char)filename[i])) + filename[i] = '_'; + } + return filename; +} + /* returns 0 to indicate success, 1 to indicate failure */ static int include_region(struct flashrom_layout *const l, const char *name, const char *file) @@ -169,14 +211,25 @@ static int include_region(struct flashrom_layout *const l, const char *name, if (entry) { entry->included = true; if (file) - entry->file = strdup(file); + entry->file = sanitise_filename(strdup(file)); + return 0; + } + return 1; +} + +/* returns 0 to indicate success, 1 to indicate failure */ +static int exclude_region(struct flashrom_layout *const l, const char *name) +{ + struct romentry *const entry = _layout_entry_by_name(l, name); + if (entry) { + entry->included = false; return 0; } return 1; } /* returns -1 if an entry is not found, 0 if found. */ -static int find_romentry(struct flashrom_layout *const l, char *name, char *file) +static int romentry_exists(struct flashrom_layout *const l, char *name, char *file) { if (!l->head) return -1; @@ -211,7 +264,7 @@ int process_include_args(struct flashrom_layout *l, const struct layout_include_ tmp = args; while (tmp) { - if (find_romentry(l, tmp->name, tmp->file) < 0) { + if (romentry_exists(l, tmp->name, tmp->file) < 0) { msg_gerr("Invalid region specified: \"%s\".\n", tmp->name); return 1; @@ -250,14 +303,17 @@ int included_regions_overlap(const struct flashrom_layout *const l) if (!rhs->included) continue; - if (lhs->start > rhs->end) + const struct flash_region *rhsr = &rhs->region; + const struct flash_region *lhsr = &lhs->region; + + if (lhsr->start > rhsr->end) continue; - if (lhs->end < rhs->start) + if (lhsr->end < rhsr->start) continue; - msg_gwarn("Regions %s [0x%08x-0x%08x] and %s [0x%08x-0x%08x] overlap\n", - lhs->name, lhs->start, lhs->end, rhs->name, rhs->start, rhs->end); + msg_gwarn("Regions %s [0x%08"PRIx32"-0x%08"PRIx32"] and %s [0x%08"PRIx32"-0x%08"PRIx32"] overlap\n", + lhsr->name, lhsr->start, lhsr->end, rhsr->name, rhsr->start, rhsr->end); overlap_detected = 1; } } @@ -285,15 +341,16 @@ int layout_sanity_checks(const struct flashrom_flashctx *const flash) const struct romentry *entry = NULL; while ((entry = layout_next(layout, entry))) { - if (entry->start >= total_size || entry->end >= total_size) { + const struct flash_region *region = &entry->region; + if (region->start >= total_size || region->end >= total_size) { msg_gwarn("Warning: Address range of region \"%s\" " - "exceeds the current chip's address space.\n", entry->name); + "exceeds the current chip's address space.\n", region->name); if (entry->included) ret = 1; } - if (entry->start > entry->end) { + if (region->start > region->end) { msg_gerr("Error: Size of the address range of region \"%s\" is not positive.\n", - entry->name); + region->name); ret = 1; } } @@ -305,18 +362,12 @@ void prepare_layout_for_extraction(struct flashctx *flash) { const struct flashrom_layout *const l = get_layout(flash); struct romentry *entry = NULL; - unsigned int i; while ((entry = mutable_layout_next(l, entry))) { entry->included = true; if (!entry->file) - entry->file = strdup(entry->name); - - for (i = 0; entry->file[i]; ++i) { - if (isspace((unsigned char)entry->file[i])) - entry->file[i] = '_'; - } + entry->file = sanitise_filename(strdup(entry->region.name)); } } @@ -328,9 +379,9 @@ const struct romentry *layout_next_included_region( while ((entry = layout_next(l, entry))) { if (!entry->included) continue; - if (entry->end < where) + if (entry->region.end < where) continue; - if (!lowest || lowest->start > entry->start) + if (!lowest || lowest->region.start > entry->region.start) lowest = entry; } @@ -355,14 +406,12 @@ const struct romentry *layout_next( int flashrom_layout_new(struct flashrom_layout **const layout) { - *layout = malloc(sizeof(**layout)); + *layout = calloc(1, sizeof(**layout)); if (!*layout) { msg_gerr("Error creating layout: %s\n", strerror(errno)); return 1; } - const struct flashrom_layout tmp = { 0 }; - **layout = tmp; return 0; } @@ -376,14 +425,16 @@ int flashrom_layout_add_region( const struct romentry tmp = { .next = layout->head, - .start = start, - .end = end, .included = false, - .name = strdup(name), .file = NULL, + .region = { + .start = start, + .end = end, + .name = strdup(name), + }, }; *entry = tmp; - if (!entry->name) + if (!entry->region.name) goto _err_ret; msg_gdbg("Added layout entry %08zx - %08zx named %s\n", start, end, name); @@ -401,13 +452,19 @@ int flashrom_layout_include_region(struct flashrom_layout *const layout, const c return include_region(layout, name, NULL); } +int flashrom_layout_exclude_region(struct flashrom_layout *const layout, const char *name) +{ + return exclude_region(layout, name); +} + int flashrom_layout_get_region_range(struct flashrom_layout *const l, const char *name, unsigned int *start, unsigned int *len) { const struct romentry *const entry = _layout_entry_by_name(l, name); if (entry) { - *start = entry->start; - *len = entry->end - entry->start + 1; + const struct flash_region *region = &entry->region; + *start = region->start; + *len = region->end - region->start + 1; return 0; } return 1; @@ -422,7 +479,7 @@ void flashrom_layout_release(struct flashrom_layout *const layout) struct romentry *const entry = layout->head; layout->head = entry->next; free(entry->file); - free(entry->name); + free(entry->region.name); free(entry); } free(layout); diff --git a/libflashrom.c b/libflashrom.c index 3e28938c9..7c885cf1c 100644 --- a/libflashrom.c +++ b/libflashrom.c @@ -36,7 +36,6 @@ int flashrom_init(const int perform_selfcheck) { if (perform_selfcheck && selfcheck()) return 1; - myusec_calibrate_delay(); return 0; } @@ -91,26 +90,26 @@ const char *flashrom_version_info(void) struct flashrom_flashchip_info *flashrom_supported_flash_chips(void) { - unsigned int i = 0; struct flashrom_flashchip_info *supported_flashchips = malloc(flashchips_size * sizeof(*supported_flashchips)); - if (supported_flashchips != NULL) { - for (; i < flashchips_size; ++i) { - supported_flashchips[i].vendor = flashchips[i].vendor; - supported_flashchips[i].name = flashchips[i].name; - supported_flashchips[i].tested.erase = - (enum flashrom_test_state)flashchips[i].tested.erase; - supported_flashchips[i].tested.probe = - (enum flashrom_test_state)flashchips[i].tested.probe; - supported_flashchips[i].tested.read = - (enum flashrom_test_state)flashchips[i].tested.read; - supported_flashchips[i].tested.write = - (enum flashrom_test_state)flashchips[i].tested.write; - supported_flashchips[i].total_size = flashchips[i].total_size; - } - } else { + if (!supported_flashchips) { msg_gerr("Memory allocation error!\n"); + return NULL; + } + + for (unsigned int i = 0; i < flashchips_size; ++i) { + supported_flashchips[i].vendor = flashchips[i].vendor; + supported_flashchips[i].name = flashchips[i].name; + supported_flashchips[i].tested.erase = + (enum flashrom_test_state)flashchips[i].tested.erase; + supported_flashchips[i].tested.probe = + (enum flashrom_test_state)flashchips[i].tested.probe; + supported_flashchips[i].tested.read = + (enum flashrom_test_state)flashchips[i].tested.read; + supported_flashchips[i].tested.write = + (enum flashrom_test_state)flashchips[i].tested.write; + supported_flashchips[i].total_size = flashchips[i].total_size; } return supported_flashchips; @@ -120,7 +119,6 @@ struct flashrom_board_info *flashrom_supported_boards(void) { #if CONFIG_INTERNAL == 1 int boards_known_size = 0; - int i = 0; const struct board_info *binfo = boards_known; while ((binfo++)->vendor) @@ -132,15 +130,16 @@ struct flashrom_board_info *flashrom_supported_boards(void) struct flashrom_board_info *supported_boards = malloc(boards_known_size * sizeof(*supported_boards)); - if (supported_boards != NULL) { - for (; i < boards_known_size; ++i) { - supported_boards[i].vendor = binfo[i].vendor; - supported_boards[i].name = binfo[i].name; - supported_boards[i].working = - (enum flashrom_test_state) binfo[i].working; - } - } else { + if (!supported_boards) { msg_gerr("Memory allocation error!\n"); + return NULL; + } + + for (int i = 0; i < boards_known_size; ++i) { + supported_boards[i].vendor = binfo[i].vendor; + supported_boards[i].name = binfo[i].name; + supported_boards[i].working = + (enum flashrom_test_state) binfo[i].working; } return supported_boards; @@ -153,7 +152,6 @@ struct flashrom_chipset_info *flashrom_supported_chipsets(void) { #if CONFIG_INTERNAL == 1 int chipset_enables_size = 0; - int i = 0; const struct penable *chipset = chipset_enables; while ((chipset++)->vendor_name) @@ -165,17 +163,18 @@ struct flashrom_chipset_info *flashrom_supported_chipsets(void) struct flashrom_chipset_info *supported_chipsets = malloc(chipset_enables_size * sizeof(*supported_chipsets)); - if (supported_chipsets != NULL) { - for (; i < chipset_enables_size; ++i) { - supported_chipsets[i].vendor = chipset[i].vendor_name; - supported_chipsets[i].chipset = chipset[i].device_name; - supported_chipsets[i].vendor_id = chipset[i].vendor_id; - supported_chipsets[i].chipset_id = chipset[i].device_id; - supported_chipsets[i].status = - (enum flashrom_test_state) chipset[i].status; - } - } else { + if (!supported_chipsets) { msg_gerr("Memory allocation error!\n"); + return NULL; + } + + for (int i = 0; i < chipset_enables_size; ++i) { + supported_chipsets[i].vendor = chipset[i].vendor_name; + supported_chipsets[i].chipset = chipset[i].device_name; + supported_chipsets[i].vendor_id = chipset[i].vendor_id; + supported_chipsets[i].chipset_id = chipset[i].device_id; + supported_chipsets[i].status = + (enum flashrom_test_state) chipset[i].status; } return supported_chipsets; @@ -221,8 +220,6 @@ int flashrom_flash_probe(struct flashrom_flashctx **const flashctx, int i, ret = 2; struct flashrom_flashctx second_flashctx = { 0, }; - chip_to_probe = chip_name; /* chip_to_probe is global in flashrom.c */ - *flashctx = malloc(sizeof(**flashctx)); if (!*flashctx) return 1; @@ -230,10 +227,10 @@ int flashrom_flash_probe(struct flashrom_flashctx **const flashctx, for (i = 0; i < registered_master_count; ++i) { int flash_idx = -1; - if (!ret || (flash_idx = probe_flash(®istered_masters[i], 0, *flashctx, 0)) != -1) { + if (!ret || (flash_idx = probe_flash(®istered_masters[i], 0, *flashctx, 0, chip_name)) != -1) { ret = 0; /* We found one chip, now check that there is no second match. */ - if (probe_flash(®istered_masters[i], flash_idx + 1, &second_flashctx, 0) != -1) { + if (probe_flash(®istered_masters[i], flash_idx + 1, &second_flashctx, 0, chip_name) != -1) { flashrom_layout_release(second_flashctx.default_layout); free(second_flashctx.chip); ret = 3; @@ -267,21 +264,25 @@ void flashrom_flag_set(struct flashrom_flashctx *const flashctx, const enum flashrom_flag flag, const bool value) { switch (flag) { - case FLASHROM_FLAG_FORCE: flashctx->flags.force = value; break; - case FLASHROM_FLAG_FORCE_BOARDMISMATCH: flashctx->flags.force_boardmismatch = value; break; - case FLASHROM_FLAG_VERIFY_AFTER_WRITE: flashctx->flags.verify_after_write = value; break; - case FLASHROM_FLAG_VERIFY_WHOLE_CHIP: flashctx->flags.verify_whole_chip = value; break; + case FLASHROM_FLAG_FORCE: flashctx->flags.force = value; break; + case FLASHROM_FLAG_FORCE_BOARDMISMATCH: flashctx->flags.force_boardmismatch = value; break; + case FLASHROM_FLAG_VERIFY_AFTER_WRITE: flashctx->flags.verify_after_write = value; break; + case FLASHROM_FLAG_VERIFY_WHOLE_CHIP: flashctx->flags.verify_whole_chip = value; break; + case FLASHROM_FLAG_SKIP_UNREADABLE_REGIONS: flashctx->flags.skip_unreadable_regions = value; break; + case FLASHROM_FLAG_SKIP_UNWRITABLE_REGIONS: flashctx->flags.skip_unwritable_regions = value; break; } } bool flashrom_flag_get(const struct flashrom_flashctx *const flashctx, const enum flashrom_flag flag) { switch (flag) { - case FLASHROM_FLAG_FORCE: return flashctx->flags.force; - case FLASHROM_FLAG_FORCE_BOARDMISMATCH: return flashctx->flags.force_boardmismatch; - case FLASHROM_FLAG_VERIFY_AFTER_WRITE: return flashctx->flags.verify_after_write; - case FLASHROM_FLAG_VERIFY_WHOLE_CHIP: return flashctx->flags.verify_whole_chip; - default: return false; + case FLASHROM_FLAG_FORCE: return flashctx->flags.force; + case FLASHROM_FLAG_FORCE_BOARDMISMATCH: return flashctx->flags.force_boardmismatch; + case FLASHROM_FLAG_VERIFY_AFTER_WRITE: return flashctx->flags.verify_after_write; + case FLASHROM_FLAG_VERIFY_WHOLE_CHIP: return flashctx->flags.verify_whole_chip; + case FLASHROM_FLAG_SKIP_UNREADABLE_REGIONS: return flashctx->flags.skip_unreadable_regions; + case FLASHROM_FLAG_SKIP_UNWRITABLE_REGIONS: return flashctx->flags.skip_unwritable_regions; + default: return false; } } @@ -299,7 +300,7 @@ int flashrom_layout_read_from_ifd(struct flashrom_layout **const layout, struct goto _free_ret; msg_cinfo("Reading ich descriptor... "); - if (flashctx->chip->read(flashctx, desc, 0, 0x1000)) { + if (read_flash(flashctx, desc, 0, 0x1000)) { msg_cerr("Read operation failed!\n"); msg_cinfo("FAILED.\n"); ret = 2; @@ -360,6 +361,16 @@ static int flashrom_layout_parse_fmap(struct flashrom_layout **layout, return 1; for (i = 0, area = fmap->areas; i < fmap->nareas; i++, area++) { + if (area->size == 0) { + /* Layout regions use inclusive upper and lower bounds, + * so it's impossible to represent a region with zero + * size although it's allowed in fmap. */ + msg_gwarn("Ignoring zero-size fmap region \"%s\";" + " empty regions are unsupported.\n", + area->name); + continue; + } + snprintf(name, sizeof(name), "%s", area->name); if (flashrom_layout_add_region(l, area->offset, area->offset + area->size - 1, name)) { flashrom_layout_release(l); diff --git a/libflashrom.map b/libflashrom.map index e3c7a769f..e1cdfa6a7 100644 --- a/libflashrom.map +++ b/libflashrom.map @@ -1,7 +1,5 @@ LIBFLASHROM_1.0 { global: - flashrom_board_info; - flashrom_chipset_info; flashrom_data_free; flashrom_flag_get; flashrom_flag_set; @@ -9,12 +7,12 @@ LIBFLASHROM_1.0 { flashrom_flash_getsize; flashrom_flash_probe; flashrom_flash_release; - flashrom_flashchip_info; flashrom_image_read; flashrom_image_verify; flashrom_image_write; flashrom_init; flashrom_layout_add_region; + flashrom_layout_exclude_region; flashrom_layout_get_region_range; flashrom_layout_include_region; flashrom_layout_new; diff --git a/linux_mtd.c b/linux_mtd.c index b8aee0616..eea0cf225 100644 --- a/linux_mtd.c +++ b/linux_mtd.c @@ -179,7 +179,7 @@ static int linux_mtd_probe(struct flashctx *flash) if (data->no_erase) flash->chip->feature_bits |= FEATURE_NO_ERASE; - flash->chip->tested = TEST_OK_PREW; + flash->chip->tested = TEST_OK_PREWB; flash->chip->total_size = data->total_size / 1024; /* bytes -> kB */ flash->chip->block_erasers[0].eraseblocks[0].size = data->erasesize; flash->chip->block_erasers[0].eraseblocks[0].count = @@ -429,6 +429,14 @@ static enum flashrom_wp_result linux_mtd_wp_get_available_ranges(struct flashrom return FLASHROM_WP_ERR_RANGE_LIST_UNAVAILABLE; } +static void linux_mtd_nop_delay(const struct flashctx *flash, unsigned int usecs) +{ + /* + * Ignore delay requests. The Linux MTD framework brokers all flash + * protocol, including timing, resets, etc. + */ +} + static const struct opaque_master linux_mtd_opaque_master = { /* max_data_{read,write} don't have any effect for this programmer */ .max_data_read = MAX_DATA_UNSPECIFIED, @@ -441,6 +449,7 @@ static const struct opaque_master linux_mtd_opaque_master = { .wp_read_cfg = linux_mtd_wp_read_cfg, .wp_write_cfg = linux_mtd_wp_write_cfg, .wp_get_ranges = linux_mtd_wp_get_available_ranges, + .delay = linux_mtd_nop_delay, }; /* Returns 0 if setup is successful, non-zero to indicate error */ diff --git a/linux_spi.c b/linux_spi.c index ee023045c..ceca05f9a 100644 --- a/linux_spi.c +++ b/linux_spi.c @@ -116,12 +116,9 @@ static const struct spi_master spi_master_linux = { .max_data_read = MAX_DATA_UNSPECIFIED, /* TODO? */ .max_data_write = MAX_DATA_UNSPECIFIED, /* TODO? */ .command = linux_spi_send_command, - .multicommand = default_spi_send_multicommand, .read = linux_spi_read, .write_256 = linux_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = linux_spi_shutdown, - .probe_opcode = default_spi_probe_opcode, }; /* Read max buffer size from sysfs, or use page size as fallback. */ diff --git a/mcp6x_spi.c b/mcp6x_spi.c index 78699251e..165bca50f 100644 --- a/mcp6x_spi.c +++ b/mcp6x_spi.c @@ -146,7 +146,7 @@ int mcp6x_spi_init(int want_spi) * 32-bit non-prefetchable memory BAR. */ mcp6x_spibaraddr &= ~0xffff; - msg_pdbg("MCP SPI BAR is at 0x%08x\n", mcp6x_spibaraddr); + msg_pdbg("MCP SPI BAR is at 0x%08"PRIx32"\n", mcp6x_spibaraddr); /* Accessing a NULL pointer BAR is evil. Don't do it. */ if (!mcp6x_spibaraddr && want_spi) { diff --git a/mediatek_i2c_spi.c b/mediatek_i2c_spi.c index 3aa9dd97b..d28e47818 100644 --- a/mediatek_i2c_spi.c +++ b/mediatek_i2c_spi.c @@ -456,12 +456,9 @@ static const struct spi_master spi_master_i2c_mediatek = { // Leave room for 1-byte command and up to a 4-byte address. .max_data_write = I2C_SMBUS_BLOCK_MAX - 5, .command = mediatek_send_command, - .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = mediatek_shutdown, - .probe_opcode = default_spi_probe_opcode, }; static int get_params(const struct programmer_cfg *cfg, bool *allow_brick) diff --git a/meson.build b/meson.build index a01b93f4c..539534239 100644 --- a/meson.build +++ b/meson.build @@ -1,22 +1,43 @@ -project('flashromutils', 'c', - version : run_command('util/getversion.sh', '--version', check : true).stdout().strip(), +project('flashrom', 'c', + version : run_command('cat', 'VERSION', check: true).stdout().strip(), license : 'GPL-2.0', - meson_version : '>=0.53.0', + meson_version : '>=0.56.0', default_options : [ 'warning_level=2', 'c_std=c99', 'werror=true', 'optimization=s', 'debug=false', + 'default_library=both' ], ) +fs = import('fs') + +if get_option('classic_cli').enabled() and get_option('default_library') == 'shared' + error(''' + Cannot build cli_classic with shared libflashrom. Use \'-Dclassic_cli=disabled\' to disable the cli, + or use \'--default-library=both\' to also build the classic_cli + ''') +endif + # libtool versioning lt_current = '1' lt_revision = '0' lt_age = '0' lt_version = '@0@.@1@.@2@'.format(lt_current, lt_age, lt_revision) +flashrom_version = meson.project_version() +git = find_program('git', native : true, required : false) +if git.found() + version_git = run_command('git', 'describe', check : false) + if version_git.returncode() == 0 + flashrom_version += ' (git:@0@)'.format(version_git.stdout().strip()) + endif +endif + +subdir('doc') + # hide/enable some warnings warning_flags = [ '-Wshadow', @@ -28,8 +49,6 @@ warning_flags = [ '-Wno-missing-braces', ] -conf = configuration_data() - cc = meson.get_compiler('c') add_project_arguments(cc.get_supported_arguments(warning_flags), language : 'c') add_project_arguments('-D_DEFAULT_SOURCE', language : 'c') @@ -39,15 +58,15 @@ add_project_arguments('-D__BSD_VISIBLE', language : 'c') # required for u_char, add_project_arguments('-D__XSI_VISIBLE', language : 'c') # required for gettimeofday() on FreeBSD add_project_arguments('-D_NETBSD_SOURCE', language : 'c') # required for indirect include of strings.h on NetBSD add_project_arguments('-D_DARWIN_C_SOURCE', language : 'c') # required for indirect include of strings.h on MacOS -add_project_arguments('-DFLASHROM_VERSION="' + meson.project_version() + '"', language : 'c') +add_project_arguments('-DFLASHROM_VERSION="' + flashrom_version + '"', language : 'c') # get defaults from configure -config_print_wiki= get_option('classic_cli_print_wiki') config_default_programmer_name = get_option('default_programmer_name') config_default_programmer_args = get_option('default_programmer_args') config_ite_ec = get_option('config_ite_ec') cargs = [] +link_args = [] deps = [] srcs = files( '82802ab.c', @@ -55,6 +74,7 @@ srcs = files( 'bitbang_spi.c', 'edi.c', 'en29lv640b.c', + 'erasure_layout.c', 'flashchips.c', 'flashrom.c', 'fmap.c', @@ -62,6 +82,7 @@ srcs = files( 'helpers_fileio.c', 'ich_descriptors.c', 'jedec.c', + 'printlock.c', 'layout.c', 'libflashrom.c', 'opaque.c', @@ -79,13 +100,22 @@ srcs = files( 'sst49lfxxxc.c', 'sst_fwhub.c', 'stm50.c', - 'udelay.c', 'w29ee011.c', 'w39.c', 'writeprotect.c', 'writeprotect_ranges.c', ) +# Select an appropriate delay implementation for the target OS +delay_src = files('udelay.c') +if target_machine.system() == 'dos' + delay_src = files('udelay_dos.c') +endif +srcs += delay_src +cargs += ['-DCONFIG_DELAY_MINIMUM_SLEEP_US=@0@'.format( + get_option('delay_minimum_sleep_us') +)] + # check for required symbols if cc.has_function('clock_gettime') add_project_arguments('-DHAVE_CLOCK_GETTIME=1', language : 'c') @@ -93,6 +123,12 @@ endif if cc.has_function('strnlen') add_project_arguments('-DHAVE_STRNLEN=1', language : 'c') endif +if cc.check_header('getopt.h') + add_project_arguments('-DHAVE_GETOPT_H=1', language : 'c') +endif +if cc.check_header('pciutils/pci.h') + add_project_arguments('-DHAVE_PCIUTILS_PCI_H=1', language : 'c') +endif if cc.check_header('sys/utsname.h') add_project_arguments('-DHAVE_UTSNAME=1', language : 'c') endif @@ -102,8 +138,16 @@ else add_project_arguments('-DIS_WINDOWS=0', language : 'c') endif -systems_hwaccess = [ 'linux', 'openbsd', 'freebsd', 'dragonfly', 'netbsd' ] -systems_serial = [ 'linux', 'openbsd', 'freebsd', 'dragonfly', 'netbsd', 'darwin' ] +if host_machine.system() == 'linux' + custom_baud_c = 'custom_baud_linux.c' +elif host_machine.system() == 'darwin' + custom_baud_c = 'custom_baud_darwin.c' +else + custom_baud_c = 'custom_baud.c' +endif + +systems_hwaccess = [ 'linux', 'openbsd', 'freebsd', 'dragonfly', 'netbsd', 'dos' ] +systems_serial = [ 'linux', 'openbsd', 'freebsd', 'dragonfly', 'netbsd', 'darwin', 'windows' ] cpus_port_io = [ 'x86', 'x86_64' ] @@ -116,10 +160,42 @@ group_jlink = get_option('programmer').contains('group_jlink') group_internal = get_option('programmer').contains('group_internal') group_external = get_option('programmer').contains('group_external') -libpci = dependency('libpci', required : group_pci, static : (host_machine.system() == 'openbsd' ? true : false)) # On openbsd a static version of libpci is needed to get also -libz +libpci = dependency('libpci', required : group_pci, version : '>=2.2.0', + static : (host_machine.system() == 'openbsd' ? true : false)) # On openbsd a static version of libpci is needed to get also -libz libusb1 = dependency('libusb-1.0', required : group_usb) libftdi1 = dependency('libftdi1', required : group_ftdi) -libjaylink = dependency('libjaylink', required : group_jlink) +libjaylink = dependency('libjaylink', required : group_jlink, version : '>=0.3.0') + +# ECAM is supported in libpci after 3.13.0 +if libpci.version().version_compare('>=3.13.0') + add_project_arguments('-DCONFIG_USE_LIBPCI_ECAM=1', language: 'c') +else + add_project_arguments('-DCONFIG_USE_LIBPCI_ECAM=0', language: 'c') +endif + +if host_machine.system() == 'windows' + # Specifying an include_path that doesn't exist is an error, + # but we only use this if the library is found in the same directory. + ni845x_search_path = get_option('ni845x_search_path') + if fs.is_dir(ni845x_search_path) + ni845x_include_path = [ni845x_search_path] + else + ni845x_include_path = [] + endif + + libni845x = declare_dependency( + dependencies : [ + cc.find_library( + 'ni845x', + dirs : get_option('ni845x_search_path'), + required : get_option('programmer').contains('ni845x_spi') + ), + ], + include_directories : ni845x_include_path, + ) +else + libni845x = dependency('', required : false) +endif subdir('platform') @@ -244,6 +320,13 @@ linux_headers = \ # 'active' : boolean, # added on runtime # } programmer = { + 'asm106x' : { + 'systems' : systems_hwaccess, + 'deps' : [ libpci ], + 'groups' : [ group_pci, group_internal ], + 'srcs' : files('asm106x.c', 'pcidev.c'), + 'flags' : [ '-DCONFIG_ASM106X=1' ], + }, 'atahpt' : { 'systems' : systems_hwaccess, 'cpu_families' : cpus_port_io, @@ -272,19 +355,27 @@ programmer = { 'buspirate_spi' : { 'systems' : systems_serial, 'groups' : [ group_serial, group_external ], - 'srcs' : files('buspirate_spi.c', 'serial.c', (host_machine.system() == 'linux' ? 'custom_baud_linux.c' : 'custom_baud.c')), + 'srcs' : files('buspirate_spi.c', 'serial.c', custom_baud_c), 'flags' : [ '-DCONFIG_BUSPIRATE_SPI=1' ], }, 'ch341a_spi' : { 'deps' : [ libusb1 ], 'groups' : [ group_usb, group_external ], 'srcs' : files('ch341a_spi.c'), + 'test_srcs' : files('tests/ch341a_spi.c'), 'flags' : [ '-DCONFIG_CH341A_SPI=1' ], }, + 'ch347_spi' : { + 'deps' : [ libusb1 ], + 'groups' : [ group_usb, group_external ], + 'srcs' : files('ch347_spi.c'), + 'flags' : [ '-DCONFIG_CH347_SPI=1' ], + }, 'dediprog' : { 'deps' : [ libusb1 ], 'groups' : [ group_usb, group_external ], 'srcs' : files('dediprog.c', 'usbdev.c'), + 'test_srcs' : files('tests/dediprog.c'), 'flags' : [ '-DCONFIG_DEDIPROG=1' ], }, 'developerbox_spi' : { @@ -299,6 +390,12 @@ programmer = { 'srcs' : files('digilent_spi.c'), 'flags' : [ '-DCONFIG_DIGILENT_SPI=1' ], }, + 'dirtyjtag_spi' : { + 'deps' : [ libusb1 ], + 'groups' : [ group_usb, group_external ], + 'srcs' : files('dirtyjtag_spi.c'), + 'flags' : [ '-DCONFIG_DIRTYJTAG_SPI=1' ], + }, 'drkaiser' : { 'systems' : systems_hwaccess, 'deps' : [ libpci ], @@ -308,6 +405,7 @@ programmer = { }, 'dummy' : { 'srcs' : files('dummyflasher.c'), + 'test_srcs' : files('tests/dummyflasher.c'), 'flags' : [ '-DCONFIG_DUMMY=1' ], }, 'ft2232_spi' : { @@ -334,8 +432,10 @@ programmer = { 'board_enable.c', 'cbtable.c', 'internal.c', + 'internal_par.c', 'it87spi.c', 'sb600spi.c', + 'superio.c', 'amd_imc.c', 'wbsio_spi.c', 'mcp6x_spi.c', @@ -348,6 +448,7 @@ programmer = { 'cbtable.c', 'chipset_enable.c', 'internal.c', + 'internal_par.c', 'processor_enable.c', 'pcidev.c', 'known_boards.c', @@ -369,13 +470,13 @@ programmer = { 'groups' : [ group_jlink, group_external ], 'srcs' : files('jlink_spi.c'), 'flags' : [ '-DCONFIG_JLINK_SPI=1' ], - 'default' : false, }, 'linux_mtd' : { 'systems' : [ 'linux' ], 'deps' : [ linux_headers ], 'groups' : [ group_internal ], 'srcs' : files('linux_mtd.c'), + 'test_srcs' : files('tests/linux_mtd.c'), 'flags' : [ '-DCONFIG_LINUX_MTD=1' ], }, 'linux_spi' : { @@ -383,6 +484,7 @@ programmer = { 'deps' : [ linux_headers ], # internal / external? 'srcs' : files('linux_spi.c'), + 'test_srcs' : files('tests/linux_spi.c'), 'flags' : [ '-DCONFIG_LINUX_SPI=1' ], }, 'parade_lspcon' : { @@ -390,6 +492,7 @@ programmer = { 'deps' : [ linux_headers ], 'groups' : [ group_i2c ], 'srcs' : files('parade_lspcon.c', 'i2c_helper_linux.c'), + 'test_srcs' : files('tests/parade_lspcon.c'), 'flags' : [ '-DCONFIG_PARADE_LSPCON=1' ], 'default' : false }, @@ -398,10 +501,11 @@ programmer = { 'deps' : [ linux_headers ], 'groups' : [ group_i2c ], 'srcs' : files('mediatek_i2c_spi.c', 'i2c_helper_linux.c'), + 'test_srcs' : files('tests/mediatek_i2c_spi.c'), 'flags' : [ '-DCONFIG_MEDIATEK_I2C_SPI=1' ], 'default' : false, }, - 'mstarddc_spi' : { + 'mstarddc_spi' : { 'systems' : [ 'linux' ], 'deps' : [ linux_headers ], 'groups' : [ group_i2c ], @@ -409,6 +513,14 @@ programmer = { 'flags' : [ '-DCONFIG_MSTARDDC_SPI=1' ], 'default' : false }, + 'ni845x_spi' : { + 'systems' : [ 'windows' ], + 'cpu_families' : [ 'x86' ], # The required ni845x library is 32-bit only + 'deps' : [ libni845x ], + 'srcs' : files('ni845x_spi.c'), + 'flags' : [ '-DCONFIG_NI845X_SPI=1' ], + 'default' : false, + }, 'nic3com' : { 'systems' : systems_hwaccess, 'cpu_families' : cpus_port_io, @@ -453,6 +565,7 @@ programmer = { 'deps' : [ libpci ], 'groups' : [ group_pci, group_internal ], 'srcs' : files('nicrealtek.c', 'pcidev.c'), + 'test_srcs' : files('tests/nicrealtek.c'), 'flags' : [ '-DCONFIG_NICREALTEK=1' ], }, 'ogp_spi' : { @@ -471,13 +584,14 @@ programmer = { 'pony_spi' : { 'systems' : systems_serial, 'groups' : [ group_serial, group_external ], - 'srcs' : files('pony_spi.c', 'serial.c', (host_machine.system() == 'linux' ? 'custom_baud_linux.c' : 'custom_baud.c')), + 'srcs' : files('pony_spi.c', 'serial.c', custom_baud_c), 'flags' : [ '-DCONFIG_PONY_SPI=1' ], }, 'raiden_debug_spi' : { 'deps' : [ libusb1 ], 'groups' : [ group_usb, group_external ], 'srcs' : files('raiden_debug_spi.c', 'usb_device.c'), + 'test_srcs' : files('tests/raiden_debug_spi.c'), 'flags' : [ '-DCONFIG_RAIDEN_DEBUG_SPI=1' ], }, 'rayer_spi' : { @@ -492,6 +606,7 @@ programmer = { 'deps' : [ linux_headers ], 'groups' : [ group_i2c ], 'srcs' : files('realtek_mst_i2c_spi.c', 'i2c_helper_linux.c'), + 'test_srcs' : files('tests/realtek_mst_i2c_spi.c'), 'flags' : [ '-DCONFIG_REALTEK_MST_I2C_SPI=1' ], 'default' : false, }, @@ -513,7 +628,7 @@ programmer = { 'serprog' : { 'systems' : systems_serial, 'groups' : [ group_serial, group_external ], - 'srcs' : files('serprog.c', 'serial.c', (host_machine.system() == 'linux' ? 'custom_baud_linux.c' : 'custom_baud.c')), + 'srcs' : files('serprog.c', 'serial.c', custom_baud_c), 'flags' : [ '-DCONFIG_SERPROG=1' ], }, 'stlinkv3_spi' : { @@ -538,6 +653,7 @@ foreach p_name, p_data : programmer 'deps' : p_data.get('deps', []), 'groups' : p_data.get('groups', []), 'srcs' : p_data.get('srcs', []), + 'test_srcs': p_data.get('test_srcs', []), 'flags' : p_data.get('flags', []), 'default' : p_data.get('default', true), } @@ -573,7 +689,13 @@ endif if selected_hard if not available - error(p_name + ' selected but not supported on this platform') + error('programmer @0@ was selected but is not supported on this platform (needs @1@/@2@, but system is @3@/@4@)'.format( + p_name, + p_data.get('systems'), + p_data.get('cpu_families'), + host_machine.system(), + host_machine.cpu_family() + )) elif not deps_found error(p_name + ' selected but dependency ' + not_found_dep +'not found') else @@ -614,15 +736,6 @@ foreach p_name, p_data : programmer endif endforeach -if config_print_wiki.enabled() - if get_option('classic_cli').disabled() - error('`classic_cli_print_wiki` can not be enabled without `classic_cli`') - else - srcs += files('print_wiki.c') - cargs += '-DCONFIG_PRINT_WIKI=1' - endif -endif - if config_default_programmer_name != '' cargs += '-DCONFIG_DEFAULT_PROGRAMMER_NAME=&programmer_' + config_default_programmer_name else @@ -631,6 +744,11 @@ endif cargs += '-DCONFIG_DEFAULT_PROGRAMMER_ARGS="' + config_default_programmer_args + '"' +if get_option('llvm_cov').enabled() + cargs += ['-fprofile-instr-generate', '-fcoverage-mapping'] + link_args += ['-fprofile-instr-generate', '-fcoverage-mapping'] +endif + install_headers([ 'include/libflashrom.h', ], @@ -644,7 +762,7 @@ if host_machine.system() == 'darwin' else vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile) endif -libflashrom = both_libraries( +libflashrom = library( 'flashrom', sources : [ srcs, @@ -659,58 +777,86 @@ libflashrom = both_libraries( cargs, ], install : true, - link_args : vflag, + link_args : link_args + [vflag], link_depends : mapfile, ) -version = meson.project_version() -#strip leading characters -if version.startswith('v') - version = version.split('v')[1] -endif -if version.startswith('p') - version = version.split('p')[1] -endif - pkgg = import('pkgconfig') pkgg.generate( libraries : libflashrom, - version : version, + version : flashrom_version.split()[0], # cut off the git version name : 'flashrom', filebase : 'flashrom', description : 'library to interact with flashrom', ) -conf.set('VERSION', version) -conf.set('MAN_DATE', run_command('util/getversion.sh', '--man-date', check : true).stdout().strip()) -configure_file( - input : 'flashrom.8.tmpl', - output : 'flashrom.8', - configuration : conf, - install: true, - install_dir: join_paths(get_option('mandir'), 'man8'), -) +if get_option('classic_cli').enabled() or get_option('classic_cli').auto() and not get_option('default_library') == 'shared' -if get_option('classic_cli').auto() or get_option('classic_cli').enabled() - executable( + cli_srcs = files( + 'cli_classic.c', + 'cli_common.c', + 'cli_output.c' + ) + + if not cc.has_function('getopt_long') + cli_srcs += files('cli_getopt.c') + endif + + classic_cli = executable( 'flashrom', - files( - 'cli_classic.c', - 'cli_common.c', - 'cli_output.c', - ), + cli_srcs, c_args : cargs, include_directories : include_dir, install : true, install_dir : get_option('sbindir'), - link_with : libflashrom.get_static_lib(), # flashrom needs internal symbols of libflashrom + link_args : link_args, + # flashrom needs internal symbols of libflashrom + link_with : get_option('default_library') == 'static' ? libflashrom : libflashrom.get_static_lib(), ) + if get_option('llvm_cov').enabled() + run_target('llvm-cov-cli', command : ['scripts/llvm-cov', classic_cli]) + endif endif if get_option('ich_descriptors_tool').auto() or get_option('ich_descriptors_tool').enabled() subdir('util/ich_descriptors_tool') endif +if get_option('bash_completion').auto() or get_option('bash_completion').enabled() + if get_option('classic_cli').disabled() + if get_option('bash_completion').enabled() + error('`bash_completion` can not be enabled without `classic_cli`') + endif + else + bash_comp = dependency('bash-completion', required : false) + if bash_comp.found() + bash_comp_install_dir = bash_comp.get_variable( + pkgconfig : 'completionsdir', + pkgconfig_define : ['datadir', get_option('datadir')] + ) + else + bash_comp_install_dir = join_paths(get_option('datadir'), 'bash-completion', 'completions') + endif + + programmer_names_active_str = '' + foreach p_name, p_data : programmer + if p_data.get('active') + programmer_names_active_str += p_name + ' ' + endif + endforeach + + configure_file( + input : 'util/flashrom.bash-completion.tmpl', + output : 'flashrom.bash', + configuration : { + 'PROGRAMMERS' : programmer_names_active_str, + }, + install: true, + install_dir: bash_comp_install_dir, + ) + endif +endif + # Use `.auto() or .enabled()` instead of `.allowed()` to keep the minimum meson version as low as possible. # `.allowed()` gets introduced in 0.59.0 if get_option('tests').auto() or get_option('tests').enabled() diff --git a/meson_cross/i586_djgpp_dos.txt b/meson_cross/i586_djgpp_dos.txt new file mode 100644 index 000000000..a1f2401d0 --- /dev/null +++ b/meson_cross/i586_djgpp_dos.txt @@ -0,0 +1,37 @@ +# This file is for cross compiling flashrom for DOS with DJGPP. +# +# Make sure the program names match your toolchain +# +# Make sure pkg-config can find your self compiles libpci +# or add the path of your libpci.pc as 'pkg_config_libdir' +# under [properies] below. +# +# If cross-compiling, you may need to set sys_root in the [properties] +# section because meson otherwise assumes the same sysroot as the +# system on which you're building and will get the wrong include files +# (from /usr/include/x86_64 for example) among other possible issues. + +[binaries] +c = 'i586-pc-msdosdjgpp-gcc' +ar = 'i586-pc-msdosdjgpp-ar' +strip = 'i586-pc-msdosdjgpp-strip' +pkgconfig = 'pkg-config' + +[host_machine] +system = 'dos' +cpu_family = 'x86' +cpu = 'i586' +endian = 'little' + +[built-in options] +c_std = 'gnu99' +default_library = 'static' + +[project options] +tests = 'disabled' +ich_descriptors_tool = 'disabled' +# DOS time resolution is only about 50ms +delay_minimum_sleep_us = 50000 + +[properties] +sys_root = '/usr/local/djgpp' diff --git a/meson_options.txt b/meson_options.txt index 3158448df..a47b5b181 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,20 +1,20 @@ option('classic_cli', type : 'feature', value : 'enabled', description : 'classic flashrom cli binary') -option('classic_cli_print_wiki', type : 'feature', value : 'disabled', description : 'Print Wiki') option('default_programmer_name', type : 'string', description : 'default programmer') option('default_programmer_args', type : 'string', description : 'default programmer arguments') option('ich_descriptors_tool', type : 'feature', value : 'auto', description : 'Build ich_descriptors_tool') +option('bash_completion', type : 'feature', value : 'auto', description : 'Install bash completion') option('tests', type : 'feature', value : 'auto', description : 'Build unit tests') -option('use_internal_dmi', type : 'boolean', value : 'true') +option('use_internal_dmi', type : 'boolean', value : true) option('programmer', type : 'array', value : ['auto'], choices : [ 'auto', 'all', 'group_internal', 'group_external', 'group_ftdi', 'group_i2c', 'group_jlink', 'group_pci', 'group_serial', 'group_usb', - 'atahpt', 'atapromise', 'atavia', 'buspirate_spi', 'ch341a_spi', 'dediprog', 'developerbox_spi', - 'digilent_spi', 'drkaiser', 'dummy', 'ft2232_spi', 'gfxnvidia', 'internal', 'it8212', 'jlink_spi', - 'linux_mtd', 'linux_spi', 'mediatek_i2c_spi', 'mstarddc_spi', 'nic3com', 'nicintel', - 'nicintel_eeprom', 'nicintel_spi', 'nicnatsemi', 'nicrealtek', 'ogp_spi', 'parade_lspcon', - 'pickit2_spi', 'pony_spi', 'raiden_debug_spi', 'rayer_spi', 'realtek_mst_i2c_spi', 'satamv', - 'satasii', 'serprog', 'stlinkv3_spi', 'usbblaster_spi', + 'asm106x', 'atahpt', 'atapromise', 'atavia', 'buspirate_spi', 'ch341a_spi', 'ch347_spi','dediprog', + 'developerbox_spi', 'digilent_spi', 'dirtyjtag_spi', 'drkaiser', 'dummy', 'ft2232_spi', + 'gfxnvidia', 'internal', 'it8212', 'jlink_spi', 'linux_mtd', 'linux_spi', 'mediatek_i2c_spi', + 'mstarddc_spi', 'ni845x_spi', 'nic3com', 'nicintel', 'nicintel_eeprom', 'nicintel_spi', 'nicnatsemi', + 'nicrealtek', 'ogp_spi', 'parade_lspcon', 'pickit2_spi', 'pony_spi', 'raiden_debug_spi', + 'rayer_spi', 'realtek_mst_i2c_spi', 'satamv', 'satasii', 'serprog', 'stlinkv3_spi', 'usbblaster_spi', ], description: 'Active programmers') option('config_atahpt', type : 'boolean', value : false, description : 'Highpoint (HPT) ATA/RAID controllers') @@ -55,3 +55,11 @@ option('config_stlinkv3_spi', type : 'boolean', value : true, description : 'STM option('config_lspcon_i2c_spi', type : 'boolean', value : false, description : 'Parade lspcon USB-C to HDMI protocol translator') option('config_realtek_mst_i2c_spi', type : 'boolean', value : true, description : 'Realtek MultiStream Transport MST') option('config_ite_ec', type : 'boolean', value : true, description : 'Clevo ITE EC') +option('llvm_cov', type : 'feature', value : 'disabled', description : 'build for llvm code coverage') +option('man-pages', type : 'feature', value : 'auto', description : 'build the man-page for classic_cli') +option('documentation', type : 'feature', value : 'auto', description : 'build the html documentation') +option('ni845x_search_path', type : 'string', value : 'C:\Program Files (x86)\National Instruments\Ni-845x\MS Visual C', + description : 'Path to search for the proprietary ni845x library and header (32-bit Windows only)') +option('delay_minimum_sleep_us', type : 'integer', min : 0, value : 100, + description : 'Minimum time in microseconds to suspend execution for (rather than polling) when a delay is required.' + + ' Larger values may perform better on machines with low timer resolution, at the cost of increased power.') diff --git a/mstarddc_spi.c b/mstarddc_spi.c index 0c11717bb..44ebd0545 100644 --- a/mstarddc_spi.c +++ b/mstarddc_spi.c @@ -142,12 +142,9 @@ static const struct spi_master spi_master_mstarddc = { .max_data_read = 256, .max_data_write = 256, .command = mstarddc_spi_send_command, - .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = mstarddc_spi_shutdown, - .probe_opcode = default_spi_probe_opcode, }; /* Returns 0 upon success, a negative number upon errors. */ diff --git a/ni845x_spi.c b/ni845x_spi.c index 2750334b9..1948387bc 100644 --- a/ni845x_spi.c +++ b/ni845x_spi.c @@ -15,6 +15,13 @@ * */ +/* The ni845x header does need the WIN32 symbol to be defined and meson does not do it. + * Define it just here, since this driver will only work on 32-bit Windows. + */ +#ifndef WIN32 +#define WIN32 +#endif + #include #include #include @@ -40,13 +47,14 @@ enum voltage_coerce_mode { USE_HIGHER }; -static unsigned char CS_number; // use chip select 0 as default -static enum USB845x_type device_pid = Unknown_NI845X_Device; - -static uInt32 device_handle; -static NiHandle configuration_handle; -static uint16_t io_voltage_in_mV; -static bool ignore_io_voltage_limits; +struct ni845x_spi_data { + unsigned char CS_number; // use chip select 0 as default + enum USB845x_type device_pid; + uInt32 device_handle; + NiHandle configuration_handle; + uint16_t io_voltage_in_mV; + bool ignore_io_voltage_limits; +}; // USB-8452 supported voltages, keep this array in ascending order! static const uint8_t usb8452_io_voltages_in_100mV[5] = { @@ -128,11 +136,11 @@ static void ni845x_report_warning(const char *const func, const int32 err) * @param opened_handle the opened handle from the ni845xOpen * @return the 0 on successful competition, negative error code on failure positive code on warning */ -static int32 ni845x_spi_open_resource(char *resource_handle, uInt32 *opened_handle) +static int32 ni845x_spi_open_resource(char *resource_handle, uInt32 *opened_handle, enum USB845x_type pid) { // NI-845x driver loads the FPGA bitfile at the first time // which can take couple seconds - if (device_pid == USB8452) + if (pid == USB8452) msg_pwarn("Opening NI-8452, this might take a while for the first time\n"); int32 tmp = ni845xOpen(resource_handle, opened_handle); @@ -148,14 +156,14 @@ static int32 ni845x_spi_open_resource(char *resource_handle, uInt32 *opened_hand * @param serial a null terminated string containing the serial number of the specific device or NULL * @return the 0 on successful completion, negative error code on failure */ -static int ni845x_spi_open(const char *serial, uInt32 *return_handle) +static int ni845x_spi_open(const char *serial, uInt32 *return_handle, enum USB845x_type *pid) { char resource_name[256]; NiHandle device_find_handle; uInt32 found_devices_count = 0; int32 tmp = 0; - unsigned int vid, pid, usb_bus; + unsigned int vid, dev_pid, usb_bus; unsigned long int serial_as_number; int ret = -1; @@ -175,7 +183,7 @@ static int ni845x_spi_open(const char *serial, uInt32 *return_handle) // and the DEADBEEF is the serial of the device if (sscanf(resource_name, "USB%u::0x%04X::0x%04X::%08lX::RAW", - &usb_bus, &vid, &pid, &serial_as_number) != 4) { + &usb_bus, &vid, &dev_pid, &serial_as_number) != 4) { // malformed resource string detected msg_pwarn("Warning: Unable to parse the %s NI-845x resource string.\n", resource_name); @@ -183,9 +191,9 @@ static int ni845x_spi_open(const char *serial, uInt32 *return_handle) continue; } - device_pid = pid; + *pid = dev_pid; - if (!serial || strtol(serial, NULL, 16) == serial_as_number) + if (!serial || strtoul(serial, NULL, 16) == serial_as_number) break; if (found_devices_count > 1) { @@ -198,7 +206,7 @@ static int ni845x_spi_open(const char *serial, uInt32 *return_handle) } if (found_devices_count) - ret = ni845x_spi_open_resource(resource_name, return_handle); + ret = ni845x_spi_open_resource(resource_name, return_handle, *pid); _close_ret: tmp = ni845xCloseFindDeviceHandle(device_find_handle); @@ -220,14 +228,16 @@ static int ni845x_spi_open(const char *serial, uInt32 *return_handle) */ static int usb8452_spi_set_io_voltage(uint16_t requested_io_voltage_mV, uint16_t *set_io_voltage_mV, - enum voltage_coerce_mode coerce_mode) + enum voltage_coerce_mode coerce_mode, + enum USB845x_type pid, + uInt32 device_handle) { - int i = 0; + unsigned int i = 0; uint8_t selected_voltage_100mV = 0; uint8_t requested_io_voltage_100mV = 0; - if (device_pid == USB8451) { - io_voltage_in_mV = 3300; + if (pid == USB8451) { + *set_io_voltage_mV = 3300; msg_pwarn("USB-8451 does not support the changing of the SPI IO voltage\n"); return 0; } @@ -300,7 +310,7 @@ static int usb8452_spi_set_io_voltage(uint16_t requested_io_voltage_mV, * @param SCK_freq_in_KHz SCK speed in KHz * @return */ -static int ni845x_spi_set_speed(uint16_t SCK_freq_in_KHz) +static int ni845x_spi_set_speed(NiHandle configuration_handle, uint16_t SCK_freq_in_KHz) { int32 i = ni845xSpiConfigurationSetClockRate(configuration_handle, SCK_freq_in_KHz); uInt16 clock_freq_read_KHz; @@ -385,94 +395,104 @@ static void ni845x_spi_print_available_devices(void) static int ni845x_spi_shutdown(void *data) { + struct ni845x_spi_data *ni_data = data; int32 ret = 0; - if (configuration_handle != 0) { - ret = ni845xSpiConfigurationClose(configuration_handle); + if (ni_data->configuration_handle != 0) { + ret = ni845xSpiConfigurationClose(ni_data->configuration_handle); if (ret) ni845x_report_error("ni845xSpiConfigurationClose", ret); } - if (device_handle != 0) { - ret = ni845xClose(device_handle); + if (ni_data->device_handle != 0) { + ret = ni845xClose(ni_data->device_handle); if (ret) ni845x_report_error("ni845xClose", ret); } - return 0; + + free(data); + return ret; } static void ni845x_warn_over_max_voltage(const struct flashctx *flash) { - if (device_pid == USB8451) { + const struct ni845x_spi_data *data = flash->mst->spi.data; + + if (data->device_pid == USB8451) { msg_pwarn("The %s chip maximum voltage is %.1fV, while the USB-8451 " "IO voltage levels are 3.3V.\n" "Ignoring this because ignore_io_voltage_limits parameter is set.\n", flash->chip->name, flash->chip->voltage.max / 1000.0f); - } else if (device_pid == USB8452) { + } else if (data->device_pid == USB8452) { msg_pwarn("The %s chip maximum voltage is %.1fV, while the USB-8452 " "IO voltage is set to %.1fV.\n" "Ignoring this because ignore_io_voltage_limits parameter is set.\n", flash->chip->name, flash->chip->voltage.max / 1000.0f, - io_voltage_in_mV / 1000.0f); + data->io_voltage_in_mV / 1000.0f); } } static int ni845x_spi_io_voltage_check(const struct flashctx *flash) { + struct ni845x_spi_data *data = flash->mst->spi.data; static bool first_transmit = true; if (first_transmit && flash->chip) { first_transmit = false; - if (io_voltage_in_mV > flash->chip->voltage.max) { - if (ignore_io_voltage_limits) { + if (data->io_voltage_in_mV > flash->chip->voltage.max) { + if (data->ignore_io_voltage_limits) { ni845x_warn_over_max_voltage(flash); return 0; } - if (device_pid == USB8451) { + if (data->device_pid == USB8451) { msg_perr("The %s chip maximum voltage is %.1fV, while the USB-8451 " "IO voltage levels are 3.3V.\nAborting operations\n", flash->chip->name, flash->chip->voltage.max / 1000.0f); return -1; - } else if (device_pid == USB8452) { + } else if (data->device_pid == USB8452) { msg_perr("Lowering IO voltage because the %s chip maximum voltage is %.1fV, " "(%.1fV was set)\n", flash->chip->name, flash->chip->voltage.max / 1000.0f, - io_voltage_in_mV / 1000.0f); + data->io_voltage_in_mV / 1000.0f); if (usb8452_spi_set_io_voltage(flash->chip->voltage.max, - &io_voltage_in_mV, - USE_LOWER)) { + &data->io_voltage_in_mV, + USE_LOWER, + data->device_pid, + data->device_handle)) { msg_perr("Unable to lower the IO voltage below " "the chip's maximum voltage\n"); return -1; } } - } else if (io_voltage_in_mV < flash->chip->voltage.min) { - if (device_pid == USB8451) { + } else if (data->io_voltage_in_mV < flash->chip->voltage.min) { + if (data->device_pid == USB8451) { msg_pwarn("Flash operations might be unreliable, because the %s chip's " "minimum voltage is %.1fV, while the USB-8451's " "IO voltage levels are 3.3V.\n", flash->chip->name, flash->chip->voltage.min / 1000.0f); - return ignore_io_voltage_limits ? 0 : -1; - } else if (device_pid == USB8452) { + return data->ignore_io_voltage_limits ? 0 : -1; + } else if (data->device_pid == USB8452) { msg_pwarn("Raising the IO voltage because the %s chip's " "minimum voltage is %.1fV, " "(%.1fV was set)\n", flash->chip->name, flash->chip->voltage.min / 1000.0f, - io_voltage_in_mV / 1000.0f); + data->io_voltage_in_mV / 1000.0f); if (usb8452_spi_set_io_voltage(flash->chip->voltage.min, - &io_voltage_in_mV, - USE_HIGHER)) { + &data->io_voltage_in_mV, + USE_HIGHER, + data->device_pid, + data->device_handle)) { msg_pwarn("Unable to raise the IO voltage above the chip's " "minimum voltage\n" "Flash operations might be unreliable.\n"); - return ignore_io_voltage_limits ? 0 : -1; + return data->ignore_io_voltage_limits ? 0 : -1; } } } @@ -486,6 +506,7 @@ static int ni845x_spi_transmit(const struct flashctx *flash, const unsigned char *write_arr, unsigned char *read_arr) { + const struct ni845x_spi_data *data = flash->mst->spi.data; uInt32 read_size = 0; uInt8 *transfer_buffer = NULL; int32 ret = 0; @@ -501,8 +522,8 @@ static int ni845x_spi_transmit(const struct flashctx *flash, memcpy(transfer_buffer, write_arr, write_cnt); - ret = ni845xSpiWriteRead(device_handle, - configuration_handle, + ret = ni845xSpiWriteRead(data->device_handle, + data->configuration_handle, (write_cnt + read_cnt), transfer_buffer, &read_size, transfer_buffer); if (ret < 0) { // Negative specifies an error, meaning the function did not perform the expected behavior. @@ -532,12 +553,9 @@ static const struct spi_master spi_programmer_ni845x = { .max_data_read = MAX_DATA_READ_UNLIMITED, .max_data_write = MAX_DATA_WRITE_UNLIMITED, .command = ni845x_spi_transmit, - .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = ni845x_spi_shutdown, - .probe_opcode = default_spi_probe_opcode, }; static int ni845x_spi_init(const struct programmer_cfg *cfg) @@ -550,14 +568,18 @@ static int ni845x_spi_init(const struct programmer_cfg *cfg) int spi_speed_KHz = 1000; // selecting 1 MHz SCK is a good bet char *serial_number = NULL; // by default open the first connected device char *ignore_io_voltage_limits_str = NULL; + bool ignore_io_voltage_limits; + unsigned char CS_number = 0; + enum USB845x_type device_pid = Unknown_NI845X_Device; + uInt32 device_handle; int32 tmp = 0; // read the cs parameter (which Chip select should we use) CS_str = extract_programmer_param_str(cfg, "cs"); if (CS_str) { - CS_number = CS_str[0] - '0'; + CS_number = strtoul(CS_str, NULL, 10); free(CS_str); - if (strlen(CS_str) > 1 || CS_number < 0 || 7 < CS_number) { + if (CS_number > 7) { msg_perr("Only CS 0-7 supported\n"); return 1; } @@ -592,7 +614,7 @@ static int ni845x_spi_init(const struct programmer_cfg *cfg) ignore_io_voltage_limits = true; } - if (ni845x_spi_open(serial_number, &device_handle)) { + if (ni845x_spi_open(serial_number, &device_handle, &device_pid)) { if (serial_number) { msg_pinfo("Could not find any connected NI USB-8451/8452 with serialnumber: %s!\n", serial_number); @@ -608,26 +630,39 @@ static int ni845x_spi_init(const struct programmer_cfg *cfg) } free(serial_number); + struct ni845x_spi_data *data = calloc(1, sizeof(*data)); + if (!data) { + msg_perr("Unable to allocate space for SPI master data\n"); + return 1; + } + data->CS_number = CS_number; + data->device_pid = device_pid; + data->device_handle = device_handle; + data->ignore_io_voltage_limits = ignore_io_voltage_limits; + // open the SPI config handle - tmp = ni845xSpiConfigurationOpen(&configuration_handle); + tmp = ni845xSpiConfigurationOpen(&data->configuration_handle); if (tmp != 0) { ni845x_report_error("ni845xSpiConfigurationOpen", tmp); - ni845x_spi_shutdown(NULL); - return 1; + goto err; } - if (usb8452_spi_set_io_voltage(requested_io_voltage_mV, &io_voltage_in_mV, USE_LOWER) < 0) { - ni845x_spi_shutdown(NULL); - return 1; // no alert here usb8452_spi_set_io_voltage already printed that + if (usb8452_spi_set_io_voltage(requested_io_voltage_mV, &data->io_voltage_in_mV, + USE_LOWER, data->device_pid, data->device_handle) < 0) { + // no alert here usb8452_spi_set_io_voltage already printed that + goto err; } - if (ni845x_spi_set_speed(spi_speed_KHz)) { + if (ni845x_spi_set_speed(data->configuration_handle, spi_speed_KHz)) { msg_perr("Unable to set SPI speed\n"); - ni845x_spi_shutdown(NULL); - return 1; + goto err; } - return register_spi_master(&spi_programmer_ni845x, NULL); + return register_spi_master(&spi_programmer_ni845x, data); + +err: + ni845x_spi_shutdown(data); + return 1; } const struct programmer_entry programmer_ni845x_spi = { diff --git a/nic3com.c b/nic3com.c index efba9793f..a578d4853 100644 --- a/nic3com.c +++ b/nic3com.c @@ -91,13 +91,7 @@ static int nic3com_shutdown(void *par_data) static const struct par_master par_master_nic3com = { .chip_readb = nic3com_chip_readb, - .chip_readw = fallback_chip_readw, - .chip_readl = fallback_chip_readl, - .chip_readn = fallback_chip_readn, .chip_writeb = nic3com_chip_writeb, - .chip_writew = fallback_chip_writew, - .chip_writel = fallback_chip_writel, - .chip_writen = fallback_chip_writen, .shutdown = nic3com_shutdown, }; diff --git a/nicintel.c b/nicintel.c index 47edbb755..feb07b663 100644 --- a/nicintel.c +++ b/nicintel.c @@ -67,13 +67,7 @@ static int nicintel_shutdown(void *par_data) static const struct par_master par_master_nicintel = { .chip_readb = nicintel_chip_readb, - .chip_readw = fallback_chip_readw, - .chip_readl = fallback_chip_readl, - .chip_readn = fallback_chip_readn, .chip_writeb = nicintel_chip_writeb, - .chip_writew = fallback_chip_writew, - .chip_writel = fallback_chip_writel, - .chip_writen = fallback_chip_writen, .shutdown = nicintel_shutdown, }; diff --git a/nicintel_eeprom.c b/nicintel_eeprom.c index a25442076..6a734b050 100644 --- a/nicintel_eeprom.c +++ b/nicintel_eeprom.c @@ -81,7 +81,7 @@ struct nicintel_eeprom_data { uint32_t eec; /* Intel I210 variable(s) */ - bool done_i20_write; + bool done_i210_write; }; /* @@ -115,8 +115,8 @@ static int nicintel_ee_probe_i210(struct flashctx *flash) /* Emulated eeprom has a fixed size of 4 KB */ flash->chip->total_size = 4; flash->chip->page_size = flash->chip->total_size * 1024; - flash->chip->tested = TEST_OK_PREW; - flash->chip->gran = write_gran_1byte_implicit_erase; + flash->chip->tested = TEST_OK_PREWB; + flash->chip->gran = WRITE_GRAN_1BYTE_IMPLICIT_ERASE; flash->chip->block_erasers->eraseblocks[0].size = flash->chip->page_size; flash->chip->block_erasers->eraseblocks[0].count = 1; @@ -140,14 +140,14 @@ static int nicintel_ee_probe_82580(struct flashctx *flash) flash->chip->total_size = 32; break; default: - msg_cerr("Unsupported chip size 0x%x\n", tmp); + msg_cerr("Unsupported chip size 0x%"PRIx32"\n", tmp); return 0; } } flash->chip->page_size = EE_PAGE_MASK + 1; - flash->chip->tested = TEST_OK_PREW; - flash->chip->gran = write_gran_1byte_implicit_erase; + flash->chip->tested = TEST_OK_PREWB; + flash->chip->gran = WRITE_GRAN_1BYTE_IMPLICIT_ERASE; flash->chip->block_erasers->eraseblocks[0].size = (EE_PAGE_MASK + 1); flash->chip->block_erasers->eraseblocks[0].count = (flash->chip->total_size * 1024) / (EE_PAGE_MASK + 1); @@ -213,7 +213,7 @@ static int nicintel_ee_write_word_i210(uint8_t *eebar, unsigned int addr, uint16 eewr |= BIT(EEWR_CMDV); pci_mmio_writel(eewr, eebar + EEWR); - programmer_delay(5); + default_delay(5); int i; for (i = 0; i < MAX_ATTEMPTS; i++) if (pci_mmio_readl(eebar + EEWR) & BIT(EEWR_DONE)) @@ -225,7 +225,7 @@ static int nicintel_ee_write_i210(struct flashctx *flash, const uint8_t *buf, unsigned int addr, unsigned int len) { struct nicintel_eeprom_data *opaque_data = flash->mst->opaque.data; - opaque_data->done_i20_write = true; + opaque_data->done_i210_write = true; if (addr & 1) { uint16_t data; @@ -338,7 +338,7 @@ static int nicintel_ee_ready(uint8_t *eebar) nicintel_ee_bitbang(eebar, 0x00, &rdsr); nicintel_ee_bitset(eebar, EEC, EE_CS, 1); - programmer_delay(1); + default_delay(1); if (!(rdsr & SPI_SR_WIP)) { return 0; } @@ -379,7 +379,7 @@ static int nicintel_ee_write_82580(struct flashctx *flash, const uint8_t *buf, u nicintel_ee_bitset(eebar, EEC, EE_CS, 0); nicintel_ee_bitbang(eebar, JEDEC_WREN, NULL); nicintel_ee_bitset(eebar, EEC, EE_CS, 1); - programmer_delay(1); + default_delay(1); /* data */ nicintel_ee_bitset(eebar, EEC, EE_CS, 0); @@ -394,7 +394,7 @@ static int nicintel_ee_write_82580(struct flashctx *flash, const uint8_t *buf, u break; } nicintel_ee_bitset(eebar, EEC, EE_CS, 1); - programmer_delay(1); + default_delay(1); if (nicintel_ee_ready(eebar)) goto out; } @@ -414,7 +414,7 @@ static int nicintel_ee_shutdown_i210(void *opaque_data) struct nicintel_eeprom_data *data = opaque_data; int ret = 0; - if (!data->done_i20_write) + if (!data->done_i210_write) goto out; uint32_t flup = pci_mmio_readl(data->nicintel_eebar + EEC); @@ -528,7 +528,7 @@ static int nicintel_ee_init(const struct programmer_cfg *cfg) data->nicintel_pci = dev; data->nicintel_eebar = eebar; data->eec = eec; - data->done_i20_write = false; + data->done_i210_write = false; return register_opaque_master(mst, data); } diff --git a/nicnatsemi.c b/nicnatsemi.c index efa879a3b..65377dc6f 100644 --- a/nicnatsemi.c +++ b/nicnatsemi.c @@ -78,13 +78,7 @@ static int nicnatsemi_shutdown(void *par_data) static const struct par_master par_master_nicnatsemi = { .chip_readb = nicnatsemi_chip_readb, - .chip_readw = fallback_chip_readw, - .chip_readl = fallback_chip_readl, - .chip_readn = fallback_chip_readn, .chip_writeb = nicnatsemi_chip_writeb, - .chip_writew = fallback_chip_writew, - .chip_writel = fallback_chip_writel, - .chip_writen = fallback_chip_writen, .shutdown = nicnatsemi_shutdown, }; diff --git a/nicrealtek.c b/nicrealtek.c index 103ea9ece..5937e35ba 100644 --- a/nicrealtek.c +++ b/nicrealtek.c @@ -87,13 +87,7 @@ static int nicrealtek_shutdown(void *data) static const struct par_master par_master_nicrealtek = { .chip_readb = nicrealtek_chip_readb, - .chip_readw = fallback_chip_readw, - .chip_readl = fallback_chip_readl, - .chip_readn = fallback_chip_readn, .chip_writeb = nicrealtek_chip_writeb, - .chip_writew = fallback_chip_writew, - .chip_writel = fallback_chip_writel, - .chip_writen = fallback_chip_writen, .shutdown = nicrealtek_shutdown, }; diff --git a/parade_lspcon.c b/parade_lspcon.c index a50346e7f..dfcf65962 100644 --- a/parade_lspcon.c +++ b/parade_lspcon.c @@ -432,12 +432,10 @@ static const struct spi_master spi_master_parade_lspcon = { .max_data_read = 16, .max_data_write = 12, .command = parade_lspcon_send_command, - .multicommand = default_spi_send_multicommand, .read = parade_lspcon_read, .write_256 = parade_lspcon_write_256, .write_aai = parade_lspcon_write_aai, .shutdown = parade_lspcon_shutdown, - .probe_opcode = default_spi_probe_opcode, }; static int get_params(const struct programmer_cfg *cfg, bool *allow_brick) diff --git a/parallel.c b/parallel.c index e635088a0..b19372302 100644 --- a/parallel.c +++ b/parallel.c @@ -27,19 +27,49 @@ void chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr) flash->mst->par.chip_writeb(flash, val, addr); } +/* Little-endian fallback for drivers not supporting 16 bit accesses */ +static void fallback_chip_writew(const struct flashctx *flash, uint16_t val, + chipaddr addr) +{ + chip_writeb(flash, val & 0xff, addr); + chip_writeb(flash, (val >> 8) & 0xff, addr + 1); +} + void chip_writew(const struct flashctx *flash, uint16_t val, chipaddr addr) { - flash->mst->par.chip_writew(flash, val, addr); + if (flash->mst->par.chip_writew) + flash->mst->par.chip_writew(flash, val, addr); + fallback_chip_writew(flash, val, addr); +} + +/* Little-endian fallback for drivers not supporting 32 bit accesses */ +static void fallback_chip_writel(const struct flashctx *flash, uint32_t val, + chipaddr addr) +{ + chip_writew(flash, val & 0xffff, addr); + chip_writew(flash, (val >> 16) & 0xffff, addr + 2); } void chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr) { - flash->mst->par.chip_writel(flash, val, addr); + if (flash->mst->par.chip_writel) + flash->mst->par.chip_writel(flash, val, addr); + fallback_chip_writel(flash, val, addr); +} + +static void fallback_chip_writen(const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) + chip_writeb(flash, buf[i], addr + i); + return; } void chip_writen(const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len) { - flash->mst->par.chip_writen(flash, buf, addr, len); + if (flash->mst->par.chip_writen) + flash->mst->par.chip_writen(flash, buf, addr, len); + fallback_chip_writen(flash, buf, addr, len); } uint8_t chip_readb(const struct flashctx *flash, const chipaddr addr) @@ -47,20 +77,53 @@ uint8_t chip_readb(const struct flashctx *flash, const chipaddr addr) return flash->mst->par.chip_readb(flash, addr); } +/* Little-endian fallback for drivers not supporting 16 bit accesses */ +static uint16_t fallback_chip_readw(const struct flashctx *flash, const chipaddr addr) +{ + uint16_t val; + val = chip_readb(flash, addr); + val |= chip_readb(flash, addr + 1) << 8; + return val; +} + uint16_t chip_readw(const struct flashctx *flash, const chipaddr addr) { - return flash->mst->par.chip_readw(flash, addr); + if (flash->mst->par.chip_readw) + return flash->mst->par.chip_readw(flash, addr); + return fallback_chip_readw(flash, addr); +} + +/* Little-endian fallback for drivers not supporting 32 bit accesses */ +static uint32_t fallback_chip_readl(const struct flashctx *flash, const chipaddr addr) +{ + uint32_t val; + val = chip_readw(flash, addr); + val |= chip_readw(flash, addr + 2) << 16; + return val; } uint32_t chip_readl(const struct flashctx *flash, const chipaddr addr) { - return flash->mst->par.chip_readl(flash, addr); + if (flash->mst->par.chip_readl) + return flash->mst->par.chip_readl(flash, addr); + return fallback_chip_readl(flash, addr); +} + +static void fallback_chip_readn(const struct flashctx *flash, uint8_t *buf, + chipaddr addr, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) + buf[i] = chip_readb(flash, addr + i); + return; } void chip_readn(const struct flashctx *flash, uint8_t *buf, chipaddr addr, size_t len) { - flash->mst->par.chip_readn(flash, buf, addr, len); + if (flash->mst->par.chip_readn) + flash->mst->par.chip_readn(flash, buf, addr, len); + fallback_chip_readn(flash, buf, addr, len); } int register_par_master(const struct par_master *mst, @@ -76,7 +139,7 @@ int register_par_master(const struct par_master *mst, } } - /* Bus masters supporting FWH/LPC cannot use fallback_map(), distinct + /* Bus masters supporting FWH/LPC cannot use chip physical maps, distinct * mappings are needed to support chips with FEATURE_REGISTERMAP */ if ((buses & (BUS_FWH | BUS_LPC)) && !mst->map_flash_region) { @@ -87,9 +150,7 @@ int register_par_master(const struct par_master *mst, return ERROR_FLASHROM_BUG; } - if (!mst->chip_writeb || !mst->chip_writew || !mst->chip_writel || - !mst->chip_writen || !mst->chip_readb || !mst->chip_readw || - !mst->chip_readl || !mst->chip_readn) { + if (!mst->chip_writeb || !mst->chip_readb) { msg_perr("%s called with incomplete master definition. " "Please report a bug at flashrom@flashrom.org\n", __func__); diff --git a/pcidev.c b/pcidev.c index d533d6492..ac79079a2 100644 --- a/pcidev.c +++ b/pcidev.c @@ -201,15 +201,7 @@ struct pci_dev *pcidev_find(uint16_t vendor, uint16_t device) struct pci_dev *pcidev_getdevfn(struct pci_dev *dev, const int func) { -#if !defined(OLD_PCI_GET_DEV) struct pci_dev *const new = pci_get_dev(pacc, dev->domain, dev->bus, dev->dev, func); -#else - /* pciutils/libpci before version 2.2 is too old to support - * PCI domains. Such old machines usually don't have domains - * besides domain 0, so this is not a problem. - */ - struct pci_dev *const new = pci_get_dev(pacc, dev->bus, dev->dev, func); -#endif if (new) pci_fill_info(new, PCI_FILL_IDENT); return new; diff --git a/pickit2_spi.c b/pickit2_spi.c index e8c80af9d..a072a2059 100644 --- a/pickit2_spi.c +++ b/pickit2_spi.c @@ -380,12 +380,9 @@ static const struct spi_master spi_master_pickit2 = { .max_data_read = 40, .max_data_write = 40, .command = pickit2_spi_send_command, - .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = pickit2_shutdown, - .probe_opcode = default_spi_probe_opcode, }; static int pickit2_spi_init(const struct programmer_cfg *cfg) diff --git a/pony_spi.c b/pony_spi.c index 3a85eebcf..0647f9121 100644 --- a/pony_spi.c +++ b/pony_spi.c @@ -244,7 +244,7 @@ static int pony_spi_init(const struct programmer_cfg *cfg) for (i = 1; i <= 10; i++) { data_out = i & 1; sp_set_pin(PIN_RTS, data_out); - programmer_delay(1000); + default_delay(1000); /* If DSR does not change, we are not connected to what we think */ if (data_out != sp_get_pin(PIN_DSR)) { diff --git a/print.c b/print.c index 98d31094e..892471d43 100644 --- a/print.c +++ b/print.c @@ -103,6 +103,10 @@ static int print_supported_chips(void) } while (1); s = flashbuses_to_text(chip->bustype); + if (s == NULL) { + msg_gerr("Out of memory!\n"); + return 1; + } maxtypelen = max(maxtypelen, strlen(s)); free(s); } @@ -118,7 +122,7 @@ static int print_supported_chips(void) for (i = strlen("Device"); i < maxchiplen; i++) msg_ginfo(" "); - msg_ginfo("Test"); + msg_ginfo("Test "); for (i = 0; i < border; i++) msg_ginfo(" "); msg_ginfo("Known"); @@ -136,7 +140,7 @@ static int print_supported_chips(void) for (i = 0; i < maxvendorlen + maxchiplen; i++) msg_ginfo(" "); - msg_ginfo("OK "); + msg_ginfo("OK "); for (i = 0; i < border; i++) msg_ginfo(" "); msg_ginfo("Broken"); @@ -147,7 +151,7 @@ static int print_supported_chips(void) msg_ginfo(" "); msg_gdbg("range [V]"); msg_ginfo("\n\n"); - msg_ginfo("(P = PROBE, R = READ, E = ERASE, W = WRITE, - = N/A)\n\n"); + msg_ginfo("(P = PROBE, R = READ, E = ERASE, W = WRITE, B = block-protect, - = N/A)\n\n"); for (chip = flashchips; chip->name != NULL; chip++) { /* Don't print generic entries. */ @@ -238,6 +242,12 @@ static int print_supported_chips(void) msg_ginfo("-"); else msg_ginfo(" "); + if (chip->tested.wp == OK) + msg_ginfo("B"); + else if (chip->tested.wp == NA) + msg_ginfo("-"); + else + msg_ginfo(" "); for (i = 0; i < border; i++) msg_ginfo(" "); @@ -257,6 +267,10 @@ static int print_supported_chips(void) msg_ginfo("W"); else msg_ginfo(" "); + if (chip->tested.wp == BAD) + msg_ginfo("B"); + else + msg_ginfo(" "); for (i = 0; i < border + 1; i++) msg_ginfo(" "); @@ -265,6 +279,12 @@ static int print_supported_chips(void) msg_ginfo(" "); s = flashbuses_to_text(chip->bustype); + if (s == NULL) { + msg_gerr("Out of memory!\n"); + free(ven); + free(dev); + return 1; + } msg_ginfo("%s", s); for (i = strlen(s); i < maxtypelen; i++) msg_ginfo(" "); @@ -434,7 +454,8 @@ static void print_supported_boards_helper(const struct board_info *boards, } #endif -static void print_supported_devs(const struct programmer_entry *const prog, const char *const type) +static void print_supported_devs(const struct programmer_entry *const prog, const char *const type, + int* num_devs) { const struct dev_entry *const devs = prog->devs.dev; msg_ginfo("\nSupported %s devices for the %s programmer:\n", type, prog->name); @@ -470,12 +491,17 @@ static void print_supported_devs(const struct programmer_entry *const prog, cons msg_pinfo(" %04x:%04x %s\n", devs[i].vendor_id, devs[i].device_id, test_state_to_text(devs[i].status)); + if (devs[i].status == OK || devs[i].status == NT || devs[i].status == DEP) + *num_devs += 1; } } int print_supported(void) { unsigned int i; + int num_pci_devs = 0; + int num_usb_devs = 0; + if (print_supported_chips()) return 1; @@ -494,10 +520,10 @@ int print_supported(void) const struct programmer_entry *const prog = programmer_table[i]; switch (prog->type) { case USB: - print_supported_devs(prog, "USB"); + print_supported_devs(prog, "USB", &num_usb_devs); break; case PCI: - print_supported_devs(prog, "PCI"); + print_supported_devs(prog, "PCI", &num_pci_devs); break; case OTHER: if (prog->devs.note != NULL) { @@ -511,6 +537,10 @@ int print_supported(void) break; } } + + msg_ginfo("\nSupported USB devices, total %d\nSupported PCI devices, total %d\n", + num_usb_devs, num_pci_devs); + return 0; } diff --git a/print_wiki.c b/print_wiki.c deleted file mode 100644 index 2c8c10934..000000000 --- a/print_wiki.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - * This file is part of the flashrom project. - * - * Copyright (C) 2009 Uwe Hermann - * Copyright (C) 2009 Carl-Daniel Hailfinger - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include "flash.h" -#include "flashchips.h" -#include "programmer.h" - -static const char wiki_header[] = "= Supported devices =\n\n\ -
\ -\n\ -'''Last update:''' %s (generated by flashrom %s)
\n\ -The tables below are generated from flashrom's source by copying the output of '''flashrom -z'''.

\n\ -A short explanation of the cells representing the support state follows:
\n\ -{| border=\"0\" valign=\"top\"\n\ -! style=\"text-align:left;\" |\n\ -! style=\"text-align:left;\" |\n\ -|-\n\ -|{{OK}}\n\ -| The feature was '''tested and should work''' in general unless there is a bug in flashrom or another component in \ -the system prohibits some functionality.\n\ -|-\n\ -|{{Dep}}\n\ -| '''Configuration-dependent'''. The feature was tested and should work in general but there are common \ -configurations that drastically limit flashrom's capabilities or make it completely stop working.\n\ -|-\n\ -|{{?3}}\n\ -| The feature is '''untested''' but believed to be working.\n\ -|-\n\ -|{{NA}}\n\ -| The feature is '''not applicable''' in this configuration (e.g. write operations on ROM chips).\n\ -|-\n\ -|{{No}}\n\ -| The feature is '''known to not work'''. Don't bother testing (nor reporting. Patches welcome! ;).\n\ -|}\n\ -
\n"; - -static const char th_start[] = "| valign=\"top\"|\n\n\ -{| border=\"0\" style=\"font-size: smaller\" valign=\"top\"\n\ -|- bgcolor=\"#6699dd\"\n"; - -#if CONFIG_INTERNAL == 1 -static const char chipset_th[] = "\ -! align=\"left\" | Vendor\n\ -! align=\"left\" | Southbridge\n\ -! align=\"center\" | PCI IDs\n\ -! align=\"center\" | Status\n\n"; - -static const char board_th[] = "\ -! align=\"left\" | Vendor\n\ -! align=\"left\" | Mainboard\n\ -! align=\"left\" | Required option\n\ -! align=\"center\" | Status\n\n"; - -static const char board_intro[] = "\ -\n== Supported mainboards ==\n\n\ -In general, it is very likely that flashrom works out of the box even if your \ -mainboard is not listed below.\n\nThis is a list of mainboards where we have \ -verified that they either do or do not need any special initialization to \ -make flashrom work (given flashrom supports the respective chipset and flash \ -chip), or that they do not yet work at all. If they do not work, support may \ -or may not be added later.\n\n\ -Mainboards (or individual revisions) which don't appear in the list may or may \ -not work (we don't know, someone has to give it a try). Please report any \ -further verified mainboards on the [[Contact#Mailing_List|mailing list]].\n"; -#endif - -static const char chip_th[] = "\ -! align=\"left\" | Vendor\n\ -! align=\"left\" | Device\n\ -! align=\"center\" | Size [kB]\n\ -! align=\"center\" | Type\n\ -! align=\"center\" colspan=\"4\" | Status\n\ -! align=\"center\" colspan=\"2\" | Voltage [V]\n\n\ -|- bgcolor=\"#6699ff\"\n| colspan=\"4\" |  \n\ -| Probe\n| Read\n| Erase\n| Write\n\ -| align=\"center\" | Min\n| align=\"center\" | Max\n\n"; - -static const char chip_intro[] = "\ -\n== Supported flash chips ==\n\n\ -The list below contains all chips that have some kind of explicit support added to flashrom and their last \ -known test status. Newer SPI flash chips might work even without explicit support if they implement SFDP ([\ -http://www.jedec.org/standards-documents/docs/jesd216 Serial Flash Discoverable Parameters - JESD216]). \ -Flashrom will detect this automatically and inform you about it.\n\n\ -The names used below are designed to be as concise as possible and hence contain only the characters \ -describing properties that are relevant to flashrom. Irrelevant characters specify attributes flashrom can not \ -use or even detect by itself (e.g. the physical package) and have no effect on flashrom's operation. They are \ -replaced by dots ('.') functioning as wildcards (like in Regular Expressions) or are completely omitted at the \ -end of a name.\n"; - -static const char programmer_th[] = "\ -! align=\"left\" | Programmer\n\ -! align=\"left\" | Vendor\n\ -! align=\"left\" | Device\n\ -! align=\"center\" | IDs\n\ -! align=\"center\" | Status\n\n"; - -/* The output of this module relies on MediaWiki templates to select special formatting styles for table cells - * reflecting the test status of the respective hardware. This functions returns the correct template name for - * the supplied enum test_state. */ -static const char *test_state_to_template(enum test_state test_state) -{ - switch (test_state) { - case OK: return "OK"; - case BAD: return "No"; - case NA: return "NA"; - case DEP: return "Dep"; - case NT: - default: return "?3"; - } -} - -#if CONFIG_INTERNAL == 1 -static const char laptop_intro[] = "\n== Supported mobile devices (laptops, tablets etc.) ==\n\n\ -In general, flashing mobile devices is more difficult because they\n\n\ -* often use the flash chip for stuff besides the BIOS,\n\ -* often have special protection stuff which has to be handled by flashrom,\n\ -* often use flash translation circuits which need drivers in flashrom.\n\n\ -
\n\ -'''IMPORTANT:''' At this point we recommend to '''not''' use flashrom on \ -untested mobile devices unless you have a means to recover from a flashing that goes \ -wrong (a working backup flash chip and/or good soldering skills).\n
\n"; - -static void print_supported_chipsets_wiki(int cols) -{ - int i; - unsigned int lines_per_col; - const struct penable *e; - int enablescount = 0, color = 1; - - for (e = chipset_enables; e->vendor_name != NULL; e++) - enablescount++; - - /* +1 to force the resulting number of columns to be < cols */ - lines_per_col = enablescount / cols + ((enablescount%cols) > 0 ? 1 : 0); - - printf("\n== Supported chipsets ==\n\nTotal amount of supported chipsets: '''%d'''\n\n" - "{| border=\"0\" valign=\"top\"\n", enablescount); - - e = chipset_enables; - for (i = 0; e[i].vendor_name != NULL; i++) { - if ((i % lines_per_col) == 0) - printf("%s%s", th_start, chipset_th); - - /* Alternate colors if the vendor changes. */ - if (i > 0 && strcmp(e[i].vendor_name, e[i - 1].vendor_name)) - color = !color; - - printf("|- bgcolor=\"#%s\"\n| %s || %s " - "|| %04x:%04x || {{%s}}\n", (color) ? "eeeeee" : "dddddd", - e[i].vendor_name, e[i].device_name, - e[i].vendor_id, e[i].device_id, - test_state_to_template(e[i].status)); - - if (((i % lines_per_col) + 1) == lines_per_col) - printf("\n|}\n\n"); - } - - /* end inner table if it did not fill the last column fully */ - if (((i % lines_per_col)) > 0) - printf("\n|}\n\n"); - printf("\n\n|}\n"); -} - -static void print_supported_boards_wiki_helper(const char *devicetype, int cols, const struct board_info boards[]) -{ - int i, k; - unsigned int boardcount, lines_per_col; - unsigned int boardcount_good = 0, boardcount_bad = 0, boardcount_nt = 0; - int num_notes = 0, color = 1; - char *notes = calloc(1, 1); - char tmp[900 + 1]; - const struct board_match *b = board_matches; - - for (i = 0; boards[i].vendor != NULL; i++) { - if (boards[i].working == OK) - boardcount_good++; - else if (boards[i].working == NT) - boardcount_nt++; - else - boardcount_bad++; - } - boardcount = boardcount_good + boardcount_nt + boardcount_bad; - - /* +1 to force the resulting number of columns to be < cols */ - lines_per_col = boardcount / cols + ((boardcount%cols) > 0 ? 1 : 0); - - printf("\n\nTotal amount of known good %s: '''%d'''; " - "Untested (e.g. user vanished before testing new code): '''%d'''; " - "Not yet supported (i.e. known-bad): '''%d'''.\n\n" - "{| border=\"0\" valign=\"top\"\n", devicetype, boardcount_good, boardcount_nt, boardcount_bad); - - for (i = 0; boards[i].vendor != NULL; i++) { - if ((i % lines_per_col) == 0) - printf("%s%s", th_start, board_th); - - /* Alternate colors if the vendor changes. */ - if (i > 0 && strcmp(boards[i].vendor, boards[i - 1].vendor)) - color = !color; - - k = 0; - while ((b[k].vendor_name != NULL) && - (strcmp(b[k].vendor_name, boards[i].vendor) || - strcmp(b[k].board_name, boards[i].name))) { - k++; - } - - printf("|- bgcolor=\"#%s\"\n| %s || %s%s %s%s || %s%s%s%s " - "|| {{%s}}", (color) ? "eeeeee" : "dddddd", - boards[i].vendor, - boards[i].url ? "[" : "", - boards[i].url ? boards[i].url : "", - boards[i].name, - boards[i].url ? "]" : "", - b[k].lb_vendor ? "-p internal:mainboard=" : "—", - b[k].lb_vendor ? b[k].lb_vendor : "", - b[k].lb_vendor ? ":" : "", - b[k].lb_vendor ? b[k].lb_part : "", - test_state_to_template(boards[i].working)); - - if (boards[i].note) { - num_notes++; - printf(" [[#%s_note%d|%d]]\n", - devicetype, num_notes, devicetype, num_notes, num_notes); - int ret = snprintf(tmp, sizeof(tmp), - "%d. [[#%s_ref%d|↑]]" - " %s
\n", devicetype, num_notes, num_notes, - devicetype, num_notes, boards[i].note); - if (ret < 0 || (unsigned int)ret >= sizeof(tmp)) { - fprintf(stderr, "Footnote text #%d of %s truncated (ret=%d, sizeof(tmp)=%zu)\n", - num_notes, devicetype, ret, sizeof(tmp)); - } - notes = strcat_realloc(notes, tmp); - } else { - printf("\n"); - } - - if (((i % lines_per_col) + 1) == lines_per_col) - printf("\n|}\n\n"); - } - - /* end inner table if it did not fill the last column fully */ - if (((i % lines_per_col)) > 0) - printf("\n|}\n\n"); - printf("|}\n"); - - if (num_notes > 0) - printf("\n\n%s\n", notes); - free(notes); -} - -static void print_supported_boards_wiki(void) -{ - printf("%s", board_intro); - print_supported_boards_wiki_helper("mainboards", 2, boards_known); - - printf("%s", laptop_intro); - print_supported_boards_wiki_helper("mobile devices", 1, laptops_known); -} -#endif - -static void print_supported_chips_wiki(int cols) -{ - unsigned int lines_per_col; - char *s; - char vmax[6]; - char vmin[6]; - const struct flashchip *f, *old = NULL; - int i = 0, c = 1, chipcount = 0; - - for (f = flashchips; f->name != NULL; f++) { - /* Don't count generic entries. */ - if (!strncmp(f->vendor, "Unknown", 7) || - !strncmp(f->vendor, "Programmer", 10) || - !strncmp(f->name, "unknown", 7)) - continue; - chipcount++; - } - - /* +1 to force the resulting number of columns to be < cols */ - lines_per_col = chipcount / cols + ((chipcount%cols) > 0 ? 1 : 0); - - printf("%s", chip_intro); - printf("\nTotal amount of supported chips: '''%d'''\n\n" - "{| border=\"0\" valign=\"top\"\n", chipcount); - - for (f = flashchips; f->name != NULL; f++) { - /* Don't print generic entries. */ - if (!strncmp(f->vendor, "Unknown", 7) || - !strncmp(f->vendor, "Programmer", 10) || - !strncmp(f->name, "unknown", 7)) - continue; - - if ((i % lines_per_col) == 0) - printf("%s%s", th_start, chip_th); - - /* Alternate colors if the vendor changes. */ - if (old != NULL && strcmp(old->vendor, f->vendor)) - c = !c; - - old = f; - s = flashbuses_to_text(f->bustype); - sprintf(vmin, "%0.03f", f->voltage.min / (double)1000); - sprintf(vmax, "%0.03f", f->voltage.max / (double)1000); - printf("|- bgcolor=\"#%s\"\n| %s || %s || align=\"right\" | %d " - "|| %s || {{%s}} || {{%s}} || {{%s}} || {{%s}}" - "|| %s || %s\n", - (c == 1) ? "eeeeee" : "dddddd", f->vendor, f->name, - f->total_size, s, - test_state_to_template(f->tested.probe), - test_state_to_template(f->tested.read), - test_state_to_template(f->tested.erase), - test_state_to_template(f->tested.write), - f->voltage.min ? vmin : "?", - f->voltage.max ? vmax : "?"); - free(s); - - if (((i % lines_per_col) + 1) == lines_per_col) - printf("\n|}\n\n"); - i++; - } - /* end inner table if it did not fill the last column fully */ - if (((i % lines_per_col)) > 0) - printf("\n|}\n\n"); - printf("|}\n\n"); -} - -/* Following functions are not needed when no PCI/USB programmers are compiled in, - * but since print_wiki code has no size constraints we include it unconditionally. */ -static int count_supported_devs_wiki(const struct dev_entry *devs) -{ - unsigned int count = 0; - unsigned int i = 0; - for (i = 0; devs[i].vendor_id != 0; i++) - count++; - return count; -} - -static void print_supported_devs_wiki_helper(const struct programmer_entry *const prog) -{ - int i = 0; - static int c = 0; - const struct dev_entry *devs = prog->devs.dev; - const unsigned int count = count_supported_devs_wiki(devs); - - /* Alternate colors if the vendor changes. */ - c = !c; - - for (i = 0; devs[i].vendor_id != 0; i++) { - printf("|- bgcolor=\"#%s\"\n", (c) ? "eeeeee" : "dddddd"); - if (i == 0) - printf("| rowspan=\"%u\" | %s |", count, prog->name); - printf("| %s || %s || %04x:%04x || {{%s}}\n", devs[i].vendor_name, devs[i].device_name, - devs[i].vendor_id, devs[i].device_id, test_state_to_template(devs[i].status)); - } -} - -static void print_supported_devs_wiki() -{ - unsigned int pci_count = 0; - unsigned int usb_count = 0; - unsigned int i; - - for (i = 0; i < programmer_table_size; i++) { - const struct programmer_entry *const prog = programmer_table[i]; - switch (prog->type) { - case USB: - usb_count += count_supported_devs_wiki(prog->devs.dev); - break; - case PCI: - pci_count += count_supported_devs_wiki(prog->devs.dev); - break; - case OTHER: - default: - break; - } - } - - printf("\n== PCI Devices ==\n\n" - "Total amount of supported PCI devices flashrom can use as a programmer: '''%d'''\n\n" - "{%s%s", pci_count, th_start, programmer_th); - - for (i = 0; i < programmer_table_size; i++) { - const struct programmer_entry *const prog = programmer_table[i]; - if (prog->type == PCI) { - print_supported_devs_wiki_helper(prog); - } - } - printf("\n|}\n\n|}\n"); - - printf("\n== USB Devices ==\n\n" - "Total amount of supported USB devices flashrom can use as a programmer: '''%d'''\n\n" - "{%s%s", usb_count, th_start, programmer_th); - - for (i = 0; i < programmer_table_size; i++) { - const struct programmer_entry *const prog = programmer_table[i]; - if (prog->type == USB) { - print_supported_devs_wiki_helper(prog); - } - } - printf("\n|}\n\n|}\n"); - - printf("\n== Other programmers ==\n\n" - "{%s", th_start); - printf("! align=\"left\" | Programmer\n" - "! align=\"left\" | Note\n\n"); - - for (i = 0; i < programmer_table_size; i++) { - static int c = 0; - const struct programmer_entry *const prog = programmer_table[i]; - if (prog->type == OTHER && prog->devs.note != NULL) { - c = !c; - printf("|- bgcolor=\"#%s\"\n", (c) ? "eeeeee" : "dddddd"); - printf("| %s || %s", prog->name, prog->devs.note); - } - } - printf("\n|}\n\n|}\n"); -} - -void print_supported_wiki(void) -{ - time_t t = time(NULL); - char buf[sizeof("1986-02-28T12:37:42Z")]; - strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&t)); - - printf(wiki_header, buf, flashrom_version); - print_supported_chips_wiki(2); -#if CONFIG_INTERNAL == 1 - print_supported_chipsets_wiki(3); - print_supported_boards_wiki(); -#endif - print_supported_devs_wiki(); -} diff --git a/printlock.c b/printlock.c new file mode 100644 index 000000000..f6eea7f46 --- /dev/null +++ b/printlock.c @@ -0,0 +1,224 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2000 Silicon Integrated System Corporation + * Copyright (C) 2006 Giampiero Giancipoli + * Copyright (C) 2006 coresystems GmbH + * Copyright (C) 2007-2012 Carl-Daniel Hailfinger + * Copyright (C) 2009 Sean Nelson + * Copyright (C) 2014 Stefan Tauner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "flash.h" +#include "chipdrivers.h" + + +struct unlockblock { + unsigned int size; + unsigned int count; +}; + +typedef int (*unlockblock_func)(const struct flashctx *flash, chipaddr offset); +static int regspace2_walk_unlockblocks(const struct flashctx *flash, const struct unlockblock *block, unlockblock_func func) +{ + chipaddr off = flash->virtual_registers + 2; + while (block->count != 0) { + unsigned int j; + for (j = 0; j < block->count; j++) { + if (func(flash, off)) + return -1; + off += block->size; + } + block++; + } + return 0; +} + +#define REG2_RWLOCK ((1 << 2) | (1 << 0)) +#define REG2_LOCKDOWN (1 << 1) +#define REG2_MASK (REG2_RWLOCK | REG2_LOCKDOWN) + +static int printlock_regspace2_block(const struct flashctx *flash, chipaddr lockreg) +{ + uint8_t state = chip_readb(flash, lockreg); + msg_cdbg("Lock status of block at 0x%0*" PRIxPTR " is ", PRIxPTR_WIDTH, lockreg); + switch (state & REG2_MASK) { + case 0: + msg_cdbg("Full Access.\n"); + break; + case 1: + msg_cdbg("Write Lock (Default State).\n"); + break; + case 2: + msg_cdbg("Locked Open (Full Access, Locked Down).\n"); + break; + case 3: + msg_cdbg("Write Lock, Locked Down.\n"); + break; + case 4: + msg_cdbg("Read Lock.\n"); + break; + case 5: + msg_cdbg("Read/Write Lock.\n"); + break; + case 6: + msg_cdbg("Read Lock, Locked Down.\n"); + break; + case 7: + msg_cdbg("Read/Write Lock, Locked Down.\n"); + break; + } + return 0; +} + +static int printlock_regspace2_uniform(struct flashctx *flash, unsigned long block_size) +{ + const unsigned int elems = flash->chip->total_size * 1024 / block_size; + struct unlockblock blocks[2] = {{.size = block_size, .count = elems}}; + return regspace2_walk_unlockblocks(flash, blocks, &printlock_regspace2_block); +} + +int printlock_regspace2_uniform_64k(struct flashctx *flash) +{ + return printlock_regspace2_uniform(flash, 64 * 1024); +} + +int printlock_regspace2_block_eraser_0(struct flashctx *flash) +{ + // FIXME: this depends on the eraseblocks not to be filled up completely (i.e. to be null-terminated). + const struct unlockblock *unlockblocks = + (const struct unlockblock *)flash->chip->block_erasers[0].eraseblocks; + return regspace2_walk_unlockblocks(flash, unlockblocks, &printlock_regspace2_block); +} + +int printlock_regspace2_block_eraser_1(struct flashctx *flash) +{ + // FIXME: this depends on the eraseblocks not to be filled up completely (i.e. to be null-terminated). + const struct unlockblock *unlockblocks = + (const struct unlockblock *)flash->chip->block_erasers[1].eraseblocks; + return regspace2_walk_unlockblocks(flash, unlockblocks, &printlock_regspace2_block); +} + +/* Try to change the lock register at address lockreg from cur to new. + * + * - Try to unlock the lock bit if requested and it is currently set (although this is probably futile). + * - Try to change the read/write bits if requested. + * - Try to set the lockdown bit if requested. + * Return an error immediately if any of this fails. */ +static int changelock_regspace2_block(const struct flashctx *flash, chipaddr lockreg, uint8_t cur, uint8_t new) +{ + /* Only allow changes to known read/write/lockdown bits */ + if (((cur ^ new) & ~REG2_MASK) != 0) { + msg_cerr("Invalid lock change from 0x%02x to 0x%02x requested at 0x%0*" PRIxPTR "!\n" + "Please report a bug at flashrom@flashrom.org\n", + cur, new, PRIxPTR_WIDTH, lockreg); + return -1; + } + + /* Exit early if no change (of read/write/lockdown bits) was requested. */ + if (((cur ^ new) & REG2_MASK) == 0) { + msg_cdbg2("Lock bits at 0x%0*" PRIxPTR " not changed.\n", PRIxPTR_WIDTH, lockreg); + return 0; + } + + /* Normally the lockdown bit can not be cleared. Try nevertheless if requested. */ + if ((cur & REG2_LOCKDOWN) && !(new & REG2_LOCKDOWN)) { + chip_writeb(flash, cur & ~REG2_LOCKDOWN, lockreg); + cur = chip_readb(flash, lockreg); + if ((cur & REG2_LOCKDOWN) == REG2_LOCKDOWN) { + msg_cwarn("Lockdown can't be removed at 0x%0*" PRIxPTR "! New value: 0x%02x.\n", + PRIxPTR_WIDTH, lockreg, cur); + return -1; + } + } + + /* Change read and/or write bit */ + if ((cur ^ new) & REG2_RWLOCK) { + /* Do not lockdown yet. */ + uint8_t wanted = (cur & ~REG2_RWLOCK) | (new & REG2_RWLOCK); + chip_writeb(flash, wanted, lockreg); + cur = chip_readb(flash, lockreg); + if (cur != wanted) { + msg_cerr("Changing lock bits failed at 0x%0*" PRIxPTR "! New value: 0x%02x.\n", + PRIxPTR_WIDTH, lockreg, cur); + return -1; + } + msg_cdbg("Changed lock bits at 0x%0*" PRIxPTR " to 0x%02x.\n", + PRIxPTR_WIDTH, lockreg, cur); + } + + /* Eventually, enable lockdown if requested. */ + if (!(cur & REG2_LOCKDOWN) && (new & REG2_LOCKDOWN)) { + chip_writeb(flash, new, lockreg); + cur = chip_readb(flash, lockreg); + if (cur != new) { + msg_cerr("Enabling lockdown FAILED at 0x%0*" PRIxPTR "! New value: 0x%02x.\n", + PRIxPTR_WIDTH, lockreg, cur); + return -1; + } + msg_cdbg("Enabled lockdown at 0x%0*" PRIxPTR ".\n", PRIxPTR_WIDTH, lockreg); + } + + return 0; +} + +static int unlock_regspace2_block_generic(const struct flashctx *flash, chipaddr lockreg) +{ + uint8_t old = chip_readb(flash, lockreg); + /* We don't care for the lockdown bit as long as the RW locks are 0 after we're done */ + return changelock_regspace2_block(flash, lockreg, old, old & ~REG2_RWLOCK); +} + +static int unlock_regspace2_uniform(struct flashctx *flash, unsigned long block_size) +{ + const unsigned int elems = flash->chip->total_size * 1024 / block_size; + struct unlockblock blocks[2] = {{.size = block_size, .count = elems}}; + return regspace2_walk_unlockblocks(flash, blocks, &unlock_regspace2_block_generic); +} + +static int unlock_regspace2_uniform_64k(struct flashctx *flash) +{ + return unlock_regspace2_uniform(flash, 64 * 1024); +} + +static int unlock_regspace2_uniform_32k(struct flashctx *flash) +{ + return unlock_regspace2_uniform(flash, 32 * 1024); +} + +static int unlock_regspace2_block_eraser_0(struct flashctx *flash) +{ + // FIXME: this depends on the eraseblocks not to be filled up completely (i.e. to be null-terminated). + const struct unlockblock *unlockblocks = + (const struct unlockblock *)flash->chip->block_erasers[0].eraseblocks; + return regspace2_walk_unlockblocks(flash, unlockblocks, &unlock_regspace2_block_generic); +} + +static int unlock_regspace2_block_eraser_1(struct flashctx *flash) +{ + // FIXME: this depends on the eraseblocks not to be filled up completely (i.e. to be null-terminated). + const struct unlockblock *unlockblocks = + (const struct unlockblock *)flash->chip->block_erasers[1].eraseblocks; + return regspace2_walk_unlockblocks(flash, unlockblocks, &unlock_regspace2_block_generic); +} + +blockprotect_func_t *lookup_jedec_blockprotect_func_ptr(const struct flashchip *const chip) +{ + switch (chip->unlock) { + case UNLOCK_REGSPACE2_BLOCK_ERASER_0: return unlock_regspace2_block_eraser_0; + case UNLOCK_REGSPACE2_BLOCK_ERASER_1: return unlock_regspace2_block_eraser_1; + case UNLOCK_REGSPACE2_UNIFORM_32K: return unlock_regspace2_uniform_32k; + case UNLOCK_REGSPACE2_UNIFORM_64K: return unlock_regspace2_uniform_64k; + default: return NULL; /* fallthough */ + }; +} diff --git a/programmer.c b/programmer.c index 939d8c2d7..15fd1b88b 100644 --- a/programmer.c +++ b/programmer.c @@ -17,74 +17,6 @@ #include "flash.h" #include "programmer.h" -/* Fallback map() for programmers which don't need special handling */ -void *fallback_map(const char *descr, uintptr_t phys_addr, size_t len) -{ - /* A result of NULL causes mapped addresses to be chip physical - * addresses, assuming only a single region is mapped (the entire flash - * space). Chips with a second region (like a register map) require a - * real memory mapping to distinguish the different ranges. Those chips - * are FWH/LPC, so the bus master provides a real mapping. - */ - return NULL; -} - -/* No-op/fallback unmap() for programmers which don't need special handling */ -void fallback_unmap(void *virt_addr, size_t len) -{ -} - -/* Little-endian fallback for drivers not supporting 16 bit accesses */ -void fallback_chip_writew(const struct flashctx *flash, uint16_t val, - chipaddr addr) -{ - chip_writeb(flash, val & 0xff, addr); - chip_writeb(flash, (val >> 8) & 0xff, addr + 1); -} - -/* Little-endian fallback for drivers not supporting 16 bit accesses */ -uint16_t fallback_chip_readw(const struct flashctx *flash, const chipaddr addr) -{ - uint16_t val; - val = chip_readb(flash, addr); - val |= chip_readb(flash, addr + 1) << 8; - return val; -} - -/* Little-endian fallback for drivers not supporting 32 bit accesses */ -void fallback_chip_writel(const struct flashctx *flash, uint32_t val, - chipaddr addr) -{ - chip_writew(flash, val & 0xffff, addr); - chip_writew(flash, (val >> 16) & 0xffff, addr + 2); -} - -/* Little-endian fallback for drivers not supporting 32 bit accesses */ -uint32_t fallback_chip_readl(const struct flashctx *flash, const chipaddr addr) -{ - uint32_t val; - val = chip_readw(flash, addr); - val |= chip_readw(flash, addr + 2) << 16; - return val; -} - -void fallback_chip_writen(const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len) -{ - size_t i; - for (i = 0; i < len; i++) - chip_writeb(flash, buf[i], addr + i); - return; -} - -void fallback_chip_readn(const struct flashctx *flash, uint8_t *buf, - chipaddr addr, size_t len) -{ - size_t i; - for (i = 0; i < len; i++) - buf[i] = chip_readb(flash, addr + i); - return; -} - /* The limit of 4 is totally arbitrary. */ #define MASTERS_MAX 4 struct registered_master registered_masters[MASTERS_MAX]; diff --git a/programmer_table.c b/programmer_table.c index 9761bb9fc..1f7472fbd 100644 --- a/programmer_table.c +++ b/programmer_table.c @@ -60,6 +60,10 @@ const struct programmer_entry *const programmer_table[] = { &programmer_ast2400, #endif +#if CONFIG_ASM106X == 1 + &programmer_asm106x, +#endif + #if CONFIG_ATAHPT == 1 &programmer_atahpt, #endif @@ -160,6 +164,10 @@ const struct programmer_entry *const programmer_table[] = { &programmer_ch341a_spi, #endif +#if CONFIG_CH347_SPI == 1 + &programmer_ch347_spi, +#endif + #if CONFIG_DIGILENT_SPI == 1 &programmer_digilent_spi, #endif @@ -175,9 +183,14 @@ const struct programmer_entry *const programmer_table[] = { #if CONFIG_STLINKV3_SPI == 1 &programmer_stlinkv3_spi, #endif + #if CONFIG_ITE_EC == 1 &programmer_ite_ec, #endif + +#if CONFIG_DIRTYJTAG_SPI == 1 + &programmer_dirtyjtag_spi, +#endif }; const size_t programmer_table_size = ARRAY_SIZE(programmer_table); diff --git a/raiden_debug_spi.c b/raiden_debug_spi.c index a2e5e842c..8fd5f7464 100644 --- a/raiden_debug_spi.c +++ b/raiden_debug_spi.c @@ -350,7 +350,11 @@ #include #include -/* FIXME: Add some programmer IDs here */ +/* + * Table is empty as raiden_debug_spi matches against the class and + * subclass of the connected USB devices, rather than looking for a + * device with a specific vid:pid. + */ static const struct dev_entry devs_raiden[] = { {0}, }; @@ -888,7 +892,7 @@ static int send_command_v1(const struct flashctx *flash, /* Reattempting will not result in a recovery. */ return status; } - programmer_delay(RETRY_INTERVAL_US); + default_delay(RETRY_INTERVAL_US); continue; } @@ -923,7 +927,7 @@ static int send_command_v1(const struct flashctx *flash, /* Reattempting will not result in a recovery. */ return status; } - programmer_delay(RETRY_INTERVAL_US); + default_delay(RETRY_INTERVAL_US); } } @@ -958,7 +962,7 @@ static int get_spi_config_v2(struct raiden_debug_spi_data *ctx_data) " config attempt = %d\n" " status = 0x%05x\n", config_attempt + 1, status); - programmer_delay(RETRY_INTERVAL_US); + default_delay(RETRY_INTERVAL_US); continue; } @@ -968,7 +972,7 @@ static int get_spi_config_v2(struct raiden_debug_spi_data *ctx_data) " config attempt = %d\n" " status = 0x%05x\n", config_attempt + 1, status); - programmer_delay(RETRY_INTERVAL_US); + default_delay(RETRY_INTERVAL_US); continue; } @@ -1012,7 +1016,7 @@ static int get_spi_config_v2(struct raiden_debug_spi_data *ctx_data) config_attempt + 1, rsp_config.packet_v2.packet_id, rsp_config.packet_size); - programmer_delay(RETRY_INTERVAL_US); + default_delay(RETRY_INTERVAL_US); } return USB_SPI_HOST_INIT_FAILURE; } @@ -1236,7 +1240,7 @@ static int send_command_v2(const struct flashctx *flash, /* Reattempting will not result in a recovery. */ return status; } - programmer_delay(RETRY_INTERVAL_US); + default_delay(RETRY_INTERVAL_US); continue; } for (read_attempt = 0; read_attempt < READ_RETRY_ATTEMPTS; @@ -1273,7 +1277,7 @@ static int send_command_v2(const struct flashctx *flash, } /* Device needs to reset its transmit index. */ restart_response_v2(ctx_data); - programmer_delay(RETRY_INTERVAL_US); + default_delay(RETRY_INTERVAL_US); } } } @@ -1316,12 +1320,9 @@ static const struct spi_master spi_master_raiden_debug = { .max_data_read = 0, .max_data_write = 0, .command = NULL, - .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = raiden_debug_spi_shutdown, - .probe_opcode = default_spi_probe_opcode, }; static int match_endpoint(struct libusb_endpoint_descriptor const *descriptor, @@ -1449,29 +1450,43 @@ static int get_ap_request_type(const struct programmer_cfg *cfg) return ap_request; } -static int get_target(const struct programmer_cfg *cfg) +static int decode_programmer_param(const struct programmer_cfg *cfg, uint8_t *request, + uint16_t *request_parameter) { /** * REQ_ENABLE doesn't specify a target bus, and will be rejected * by adapters that support more than one target. */ - int request_enable = RAIDEN_DEBUG_SPI_REQ_ENABLE; + uint8_t request_enable = RAIDEN_DEBUG_SPI_REQ_ENABLE; + uint16_t parameter = 0; + int ret = 0; char *target_str = extract_programmer_param_str(cfg, "target"); + printf("FISK: %s\n", target_str); + if (target_str) { - if (!strcasecmp(target_str, "ap")) + char *endptr; + int index = strtol(target_str, &endptr, 0); + if (*target_str && !*endptr && index >= 0 && index < 256) { + request_enable = RAIDEN_DEBUG_SPI_REQ_ENABLE; + parameter = index; + } else if (!strcasecmp(target_str, "ap")) request_enable = get_ap_request_type(cfg); else if (!strcasecmp(target_str, "ec")) request_enable = RAIDEN_DEBUG_SPI_REQ_ENABLE_EC; else { msg_perr("Invalid target: %s\n", target_str); - request_enable = -1; + ret = 1; } } free(target_str); - msg_pinfo("Raiden target: %d\n", request_enable); + if (ret == 0) { + msg_pinfo("Raiden target: %d,%d\n", request_enable, parameter); - return request_enable; + *request = request_enable; + *request_parameter = parameter; + } + return ret; } static void free_dev_list(struct usb_device **dev_lst) @@ -1492,10 +1507,12 @@ static int raiden_debug_spi_init(const struct programmer_cfg *cfg) bool found = false; int ret; - int request_enable = get_target(cfg); - if (request_enable < 0) { + uint8_t request_enable; + uint16_t request_parameter; + ret = decode_programmer_param(cfg, &request_enable, &request_parameter); + if (ret != 0) { free(serial); - return 1; + return ret; } usb_match_init(cfg, &match); @@ -1587,7 +1604,7 @@ static int raiden_debug_spi_init(const struct programmer_cfg *cfg) LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_INTERFACE, request_enable, - 0, + request_parameter, device->interface_descriptor->bInterfaceNumber, NULL, 0, diff --git a/rayer_spi.c b/rayer_spi.c index 8fdcc01cd..27caf2be1 100644 --- a/rayer_spi.c +++ b/rayer_spi.c @@ -174,16 +174,6 @@ static const struct rayer_pinout spi_tt = { .miso_bit = 7, }; -static const struct rayer_programmer rayer_spi_types[] = { - {"rayer", NT, "RayeR SPIPGM", &rayer_spipgm}, - {"xilinx", NT, "Xilinx Parallel Cable III (DLC 5)", &xilinx_dlc5}, - {"byteblastermv", OK, "Altera ByteBlasterMV", &altera_byteblastermv}, - {"stk200", NT, "Atmel STK200/300 adapter", &atmel_stk200}, - {"wiggler", OK, "Wiggler LPT", &wiggler_lpt}, - {"spi_tt", NT, "SPI Tiny Tools (SPI_TT LPT)", &spi_tt}, - {0}, -}; - static void rayer_bitbang_set_cs(int val, void *spi_data) { struct rayer_spi_data *data = spi_data; @@ -235,20 +225,48 @@ static const struct bitbang_spi_master bitbang_spi_master_rayer = { .half_period = 0, }; -static int rayer_spi_init(const struct programmer_cfg *cfg) +static const struct rayer_programmer *find_progtype(const char *prog_type) { + static const struct rayer_programmer rayer_spi_types[] = { + {"rayer", NT, "RayeR SPIPGM", &rayer_spipgm}, + {"xilinx", NT, "Xilinx Parallel Cable III (DLC 5)", &xilinx_dlc5}, + {"byteblastermv", OK, "Altera ByteBlasterMV", &altera_byteblastermv}, + {"stk200", NT, "Atmel STK200/300 adapter", &atmel_stk200}, + {"wiggler", OK, "Wiggler LPT", &wiggler_lpt}, + {"spi_tt", NT, "SPI Tiny Tools (SPI_TT LPT)", &spi_tt}, + {0}, + }; + if (!prog_type) + return &rayer_spi_types[0]; + const struct rayer_programmer *prog = rayer_spi_types; - char *arg = NULL; - struct rayer_pinout *pinout = NULL; - uint16_t lpt_iobase; - uint8_t lpt_outbyte; + for (; prog->type != NULL; prog++) { + if (strcasecmp(prog_type, prog->type) == 0) { + break; + } + } + + if (!prog->type) { + msg_perr("Error: Invalid device type specified.\n"); + return NULL; + } + + return prog; +} + +static int get_params(const struct programmer_cfg *cfg, uint16_t *lpt_iobase, + const struct rayer_programmer **prog) +{ + /* Pick a default value for the I/O base. */ + *lpt_iobase = 0x378; + /* no programmer type specified. */ + *prog = NULL; /* Non-default port requested? */ - arg = extract_programmer_param_str(cfg, "iobase"); + char *arg = extract_programmer_param_str(cfg, "iobase"); if (arg) { char *endptr = NULL; - unsigned long tmp; - tmp = strtoul(arg, &endptr, 0); + unsigned long tmp = strtoul(arg, &endptr, 0); /* Port 0, port >0x10000, unaligned ports and garbage strings * are rejected. */ @@ -262,44 +280,40 @@ static int rayer_spi_init(const struct programmer_cfg *cfg) "given was invalid.\nIt must be a multiple of " "0x4 and lie between 0x100 and 0xfffc.\n"); free(arg); - return 1; + return -1; } else { - lpt_iobase = (uint16_t)tmp; + *lpt_iobase = (uint16_t)tmp; msg_pinfo("Non-default I/O base requested. This will " "not change the hardware settings.\n"); } - } else { - /* Pick a default value for the I/O base. */ - lpt_iobase = 0x378; + free(arg); } + + arg = extract_programmer_param_str(cfg, "type"); + *prog = find_progtype(arg); free(arg); + return *prog ? 0 : -1; +} + +static int rayer_spi_init(const struct programmer_cfg *cfg) +{ + const struct rayer_programmer *prog; + struct rayer_pinout *pinout = NULL; + uint16_t lpt_iobase; + + if (get_params(cfg, &lpt_iobase, &prog) < 0) + return 1; + msg_pdbg("Using address 0x%x as I/O base for parallel port access.\n", lpt_iobase); - arg = extract_programmer_param_str(cfg, "type"); - if (arg) { - for (; prog->type != NULL; prog++) { - if (strcasecmp(arg, prog->type) == 0) { - break; - } - } - if (prog->type == NULL) { - msg_perr("Error: Invalid device type specified.\n"); - free(arg); - return 1; - } - free(arg); - } msg_pinfo("Using %s pinout.\n", prog->description); pinout = (struct rayer_pinout *)prog->dev_data; if (rget_io_perms()) return 1; - /* Get the initial value before writing to any line. */ - lpt_outbyte = INB(lpt_iobase); - struct rayer_spi_data *data = calloc(1, sizeof(*data)); if (!data) { msg_perr("Unable to allocate space for SPI master data\n"); @@ -307,7 +321,8 @@ static int rayer_spi_init(const struct programmer_cfg *cfg) } data->pinout = pinout; data->lpt_iobase = lpt_iobase; - data->lpt_outbyte = lpt_outbyte; + /* Get the initial value before writing to any line. */ + data->lpt_outbyte = INB(lpt_iobase); if (pinout->shutdown) register_shutdown(pinout->shutdown, data); diff --git a/realtek_mst_i2c_spi.c b/realtek_mst_i2c_spi.c index 2a5d5ed6a..57677ec67 100644 --- a/realtek_mst_i2c_spi.c +++ b/realtek_mst_i2c_spi.c @@ -436,12 +436,10 @@ static const struct spi_master spi_master_i2c_realtek_mst = { .max_data_read = 16, .max_data_write = 8, .command = realtek_mst_i2c_spi_send_command, - .multicommand = default_spi_send_multicommand, .read = realtek_mst_i2c_spi_read, .write_256 = realtek_mst_i2c_spi_write_256, .write_aai = realtek_mst_i2c_spi_write_aai, .shutdown = realtek_mst_i2c_spi_shutdown, - .probe_opcode = default_spi_probe_opcode, }; static int get_params(const struct programmer_cfg *cfg, bool *reset, bool *enter_isp, bool *allow_brick) diff --git a/s25f.c b/s25f.c index 1133ef87a..b0f2438d1 100644 --- a/s25f.c +++ b/s25f.c @@ -21,6 +21,7 @@ * TODO: Implement fancy hybrid sector architecture helpers. */ +#include #include #include "chipdrivers.h" @@ -93,7 +94,7 @@ static int s25f_legacy_software_reset(const struct flashctx *flash) /* Allow time for reset command to execute. The datasheet specifies * Trph = 35us, double that to be safe. */ - programmer_delay(T_RPH * 2); + programmer_delay(flash, T_RPH * 2); return 0; } @@ -126,7 +127,7 @@ static int s25fs_software_reset(struct flashctx *flash) } /* Allow time for reset command to execute. Double tRPH to be safe. */ - programmer_delay(T_RPH * 2); + programmer_delay(flash, T_RPH * 2); return 0; } @@ -160,7 +161,7 @@ static int s25f_poll_status(const struct flashctx *flash) return -1; } - programmer_delay(1000 * 10); + programmer_delay(flash, 1000 * 10); } return 0; @@ -183,7 +184,7 @@ static int s25fs_read_cr(const struct flashctx *flash, uint32_t addr) int result = spi_send_command(flash, sizeof(read_cr_cmd), 1, read_cr_cmd, &cfg); if (result) { - msg_cerr("%s failed during command execution at address 0x%x\n", + msg_cerr("%s failed during command execution at address 0x%"PRIx32"\n", __func__, addr); return -1; } @@ -221,19 +222,22 @@ static int s25fs_write_cr(const struct flashctx *flash, int result = spi_send_multicommand(flash, cmds); if (result) { - msg_cerr("%s failed during command execution at address 0x%x\n", + msg_cerr("%s failed during command execution at address 0x%"PRIx32"\n", __func__, addr); return -1; } - programmer_delay(T_W); + programmer_delay(flash, T_W); return s25f_poll_status(flash); } -static int s25fs_restore_cr3nv(struct flashctx *flash, uint8_t cfg) +static int s25fs_restore_cr3nv(struct flashctx *flash, void *data) { int ret = 0; + uint8_t cfg = *(uint8_t *)data; + free(data); + msg_cdbg("Restoring CR3NV value to 0x%02x\n", cfg); ret |= s25fs_write_cr(flash, CR3NV_ADDR, cfg); ret |= s25fs_software_reset(flash); @@ -285,8 +289,15 @@ int s25fs_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int msg_cdbg("\n%s: CR3NV updated (0x%02x -> 0x%02x)\n", __func__, cfg, s25fs_read_cr(flash, CR3NV_ADDR)); + /* Restore CR3V when flashrom exits */ - register_chip_restore(s25fs_restore_cr3nv, flash, cfg); + uint8_t *data = calloc(1, sizeof(uint8_t)); + if (!data) { + msg_cerr("Out of memory!\n"); + return 1; + } + *data = cfg; + register_chip_restore(s25fs_restore_cr3nv, flash, data); } cr3nv_checked = 1; @@ -299,7 +310,7 @@ int s25fs_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int return result; } - programmer_delay(S25FS_T_SE); + programmer_delay(flash, S25FS_T_SE); return s25f_poll_status(flash); } @@ -337,7 +348,7 @@ int s25fl_block_erase(struct flashctx *flash, unsigned int addr, unsigned int bl return result; } - programmer_delay(S25FL_T_SE); + programmer_delay(flash, S25FL_T_SE); return s25f_poll_status(flash); } diff --git a/satamv.c b/satamv.c index dcd53c753..1b8640a84 100644 --- a/satamv.c +++ b/satamv.c @@ -88,13 +88,7 @@ static int satamv_shutdown(void *par_data) static const struct par_master par_master_satamv = { .chip_readb = satamv_chip_readb, - .chip_readw = fallback_chip_readw, - .chip_readl = fallback_chip_readl, - .chip_readn = fallback_chip_readn, .chip_writeb = satamv_chip_writeb, - .chip_writew = fallback_chip_writew, - .chip_writel = fallback_chip_writel, - .chip_writen = fallback_chip_writen, .shutdown = satamv_shutdown, }; @@ -140,38 +134,38 @@ static int satamv_init(const struct programmer_cfg *cfg) tmp = pci_mmio_readl(bar + FLASH_PARAM); msg_pspew("Flash Parameters:\n"); - msg_pspew("TurnOff=0x%01x\n", (tmp >> 0) & 0x7); - msg_pspew("Acc2First=0x%01x\n", (tmp >> 3) & 0xf); - msg_pspew("Acc2Next=0x%01x\n", (tmp >> 7) & 0xf); - msg_pspew("ALE2Wr=0x%01x\n", (tmp >> 11) & 0x7); - msg_pspew("WrLow=0x%01x\n", (tmp >> 14) & 0x7); - msg_pspew("WrHigh=0x%01x\n", (tmp >> 17) & 0x7); - msg_pspew("Reserved[21:20]=0x%01x\n", (tmp >> 20) & 0x3); - msg_pspew("TurnOffExt=0x%01x\n", (tmp >> 22) & 0x1); - msg_pspew("Acc2FirstExt=0x%01x\n", (tmp >> 23) & 0x1); - msg_pspew("Acc2NextExt=0x%01x\n", (tmp >> 24) & 0x1); - msg_pspew("ALE2WrExt=0x%01x\n", (tmp >> 25) & 0x1); - msg_pspew("WrLowExt=0x%01x\n", (tmp >> 26) & 0x1); - msg_pspew("WrHighExt=0x%01x\n", (tmp >> 27) & 0x1); - msg_pspew("Reserved[31:28]=0x%01x\n", (tmp >> 28) & 0xf); + msg_pspew("TurnOff=0x%01"PRIx32"\n", (tmp >> 0) & 0x7); + msg_pspew("Acc2First=0x%01"PRIx32"\n", (tmp >> 3) & 0xf); + msg_pspew("Acc2Next=0x%01"PRIx32"\n", (tmp >> 7) & 0xf); + msg_pspew("ALE2Wr=0x%01"PRIx32"\n", (tmp >> 11) & 0x7); + msg_pspew("WrLow=0x%01"PRIx32"\n", (tmp >> 14) & 0x7); + msg_pspew("WrHigh=0x%01"PRIx32"\n", (tmp >> 17) & 0x7); + msg_pspew("Reserved[21:20]=0x%01"PRIx32"\n", (tmp >> 20) & 0x3); + msg_pspew("TurnOffExt=0x%01"PRIx32"\n", (tmp >> 22) & 0x1); + msg_pspew("Acc2FirstExt=0x%01"PRIx32"\n", (tmp >> 23) & 0x1); + msg_pspew("Acc2NextExt=0x%01"PRIx32"\n", (tmp >> 24) & 0x1); + msg_pspew("ALE2WrExt=0x%01"PRIx32"\n", (tmp >> 25) & 0x1); + msg_pspew("WrLowExt=0x%01"PRIx32"\n", (tmp >> 26) & 0x1); + msg_pspew("WrHighExt=0x%01"PRIx32"\n", (tmp >> 27) & 0x1); + msg_pspew("Reserved[31:28]=0x%01"PRIx32"\n", (tmp >> 28) & 0xf); tmp = pci_mmio_readl(bar + EXPANSION_ROM_BAR_CONTROL); msg_pspew("Expansion ROM BAR Control:\n"); - msg_pspew("ExpROMSz=0x%01x\n", (tmp >> 19) & 0x7); + msg_pspew("ExpROMSz=0x%01"PRIx32"\n", (tmp >> 19) & 0x7); /* Enable BAR2 mapping to flash */ tmp = pci_mmio_readl(bar + PCI_BAR2_CONTROL); msg_pspew("PCI BAR2 (Flash/NVRAM) Control:\n"); - msg_pspew("Bar2En=0x%01x\n", (tmp >> 0) & 0x1); - msg_pspew("BAR2TransAttr=0x%01x\n", (tmp >> 1) & 0x1f); - msg_pspew("BAR2Sz=0x%01x\n", (tmp >> 19) & 0x7); + msg_pspew("Bar2En=0x%01"PRIx32"\n", (tmp >> 0) & 0x1); + msg_pspew("BAR2TransAttr=0x%01"PRIx32"\n", (tmp >> 1) & 0x1f); + msg_pspew("BAR2Sz=0x%01"PRIx32"\n", (tmp >> 19) & 0x7); tmp &= 0xffffffc0; tmp |= 0x0000001f; pci_rmmio_writel(tmp, bar + PCI_BAR2_CONTROL); /* Enable flash: GPIO Port Control Register 0x104f0 */ tmp = pci_mmio_readl(bar + GPIO_PORT_CONTROL); - msg_pspew("GPIOPortMode=0x%01x\n", (tmp >> 0) & 0x3); + msg_pspew("GPIOPortMode=0x%01"PRIx32"\n", (tmp >> 0) & 0x3); if (((tmp >> 0) & 0x3) != 0x2) msg_pinfo("Warning! Either the straps are incorrect or you " "have no flash or someone overwrote the strap " diff --git a/satasii.c b/satasii.c index 011562ef3..ad872bfc9 100644 --- a/satasii.c +++ b/satasii.c @@ -46,7 +46,7 @@ static uint32_t satasii_wait_done(const uint8_t *bar) int i = 0; while ((ctrl_reg = pci_mmio_readl(bar)) & (1 << 25)) { if (++i > 10000) { - msg_perr("%s: control register stuck at %08x, ignoring.\n", + msg_perr("%s: control register stuck at %08"PRIx32", ignoring.\n", __func__, pci_mmio_readl(bar)); break; } @@ -95,13 +95,7 @@ static int satasii_shutdown(void *par_data) static const struct par_master par_master_satasii = { .chip_readb = satasii_chip_readb, - .chip_readw = fallback_chip_readw, - .chip_readl = fallback_chip_readl, - .chip_readn = fallback_chip_readn, .chip_writeb = satasii_chip_writeb, - .chip_writew = fallback_chip_writew, - .chip_writel = fallback_chip_writel, - .chip_writen = fallback_chip_writen, .shutdown = satasii_shutdown, }; diff --git a/sb600spi.c b/sb600spi.c index 2fbaf4c97..d6dc00e85 100644 --- a/sb600spi.c +++ b/sb600spi.c @@ -609,42 +609,33 @@ static const struct spi_master spi_master_sb600 = { .max_data_read = FIFO_SIZE_OLD, .max_data_write = FIFO_SIZE_OLD - 3, .command = sb600_spi_send_command, - .multicommand = default_spi_send_multicommand, .map_flash_region = physmap, .unmap_flash_region = physunmap, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = sb600spi_shutdown, - .probe_opcode = default_spi_probe_opcode, }; static const struct spi_master spi_master_yangtze = { .max_data_read = FIFO_SIZE_YANGTZE - 3, /* Apparently the big SPI 100 buffer is not a ring buffer. */ .max_data_write = FIFO_SIZE_YANGTZE - 3, .command = spi100_spi_send_command, - .multicommand = default_spi_send_multicommand, .map_flash_region = physmap, .unmap_flash_region = physunmap, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = sb600spi_shutdown, - .probe_opcode = default_spi_probe_opcode, }; static const struct spi_master spi_master_promontory = { .max_data_read = MAX_DATA_READ_UNLIMITED, .max_data_write = FIFO_SIZE_YANGTZE - 3, .command = spi100_spi_send_command, - .multicommand = default_spi_send_multicommand, .map_flash_region = physmap, .unmap_flash_region = physunmap, .read = promontory_read_memmapped, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = sb600spi_shutdown, - .probe_opcode = default_spi_probe_opcode, }; int sb600_probe_spi(const struct programmer_cfg *cfg, struct pci_dev *dev) @@ -656,7 +647,7 @@ int sb600_probe_spi(const struct programmer_cfg *cfg, struct pci_dev *dev) enum amd_chipset amd_gen = determine_generation(dev); if (amd_gen == CHIPSET_AMD_UNKNOWN) - return ERROR_NONFATAL; + return ERROR_FLASHROM_NONFATAL; /* Read SPI_BaseAddr */ tmp = pci_read_long(dev, 0xa0); @@ -674,7 +665,7 @@ int sb600_probe_spi(const struct programmer_cfg *cfg, struct pci_dev *dev) /* Physical memory has to be mapped at page (4k) boundaries. */ sb600_spibar = rphysmap("SB600 SPI registers", tmp & 0xfffff000, 0x1000); if (sb600_spibar == ERROR_PTR) - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; /* The low bits of the SPI base address are used as offset into * the mapped page. @@ -699,14 +690,14 @@ int sb600_probe_spi(const struct programmer_cfg *cfg, struct pci_dev *dev) */ if (amd_gen >= CHIPSET_SB7XX) { tmp = pci_read_long(dev, 0xa0); - msg_pdbg("SpiRomEnable=%i", (tmp >> 1) & 0x1); + msg_pdbg("SpiRomEnable=%"PRIi32"", (tmp >> 1) & 0x1); if (amd_gen == CHIPSET_SB7XX) - msg_pdbg(", AltSpiCSEnable=%i, AbortEnable=%i", tmp & 0x1, (tmp >> 2) & 0x1); + msg_pdbg(", AltSpiCSEnable=%"PRIi32", AbortEnable=%"PRIi32"", tmp & 0x1, (tmp >> 2) & 0x1); else if (amd_gen >= CHIPSET_YANGTZE) - msg_pdbg(", RouteTpm2Sp=%i", (tmp >> 3) & 0x1); + msg_pdbg(", RouteTpm2Sp=%"PRIi32"", (tmp >> 3) & 0x1); tmp = pci_read_byte(dev, 0xba); - msg_pdbg(", PrefetchEnSPIFromIMC=%i", (tmp & 0x4) >> 2); + msg_pdbg(", PrefetchEnSPIFromIMC=%"PRIi32"", (tmp & 0x4) >> 2); tmp = pci_read_byte(dev, 0xbb); /* FIXME: Set bit 3,6,7 if not already set. @@ -714,8 +705,8 @@ int sb600_probe_spi(const struct programmer_cfg *cfg, struct pci_dev *dev) * See doc 42413 AMD SB700/710/750 RPR. */ if (amd_gen == CHIPSET_SB7XX) - msg_pdbg(", SpiOpEnInLpcMode=%i", (tmp >> 5) & 0x1); - msg_pdbg(", PrefetchEnSPIFromHost=%i\n", tmp & 0x1); + msg_pdbg(", SpiOpEnInLpcMode=%"PRIi32"", (tmp >> 5) & 0x1); + msg_pdbg(", PrefetchEnSPIFromHost=%"PRIi32"\n", tmp & 0x1); } /* Chipset support matrix for SPI_Cntrl0 (spibar + 0x0) @@ -737,25 +728,25 @@ int sb600_probe_spi(const struct programmer_cfg *cfg, struct pci_dev *dev) * <1> see handle_speed */ tmp = mmio_readl(sb600_spibar + 0x00); - msg_pdbg("(0x%08" PRIx32 ") SpiArbEnable=%i", tmp, (tmp >> 19) & 0x1); + msg_pdbg("(0x%08" PRIx32 ") SpiArbEnable=%"PRIi32"", tmp, (tmp >> 19) & 0x1); if (amd_gen >= CHIPSET_YANGTZE) - msg_pdbg(", IllegalAccess=%i", (tmp >> 21) & 0x1); + msg_pdbg(", IllegalAccess=%"PRIi32"", (tmp >> 21) & 0x1); - msg_pdbg(", SpiAccessMacRomEn=%i, SpiHostAccessRomEn=%i, ArbWaitCount=%i", + msg_pdbg(", SpiAccessMacRomEn=%"PRIi32", SpiHostAccessRomEn=%"PRIi32", ArbWaitCount=%"PRIi32"", (tmp >> 22) & 0x1, (tmp >> 23) & 0x1, (tmp >> 24) & 0x7); if (amd_gen < CHIPSET_YANGTZE) - msg_pdbg(", SpiBridgeDisable=%i", (tmp >> 27) & 0x1); + msg_pdbg(", SpiBridgeDisable=%"PRIi32"", (tmp >> 27) & 0x1); switch (amd_gen) { case CHIPSET_SB7XX: - msg_pdbg(", DropOneClkOnRd/SpiClkGate=%i", (tmp >> 28) & 0x1); + msg_pdbg(", DropOneClkOnRd/SpiClkGate=%"PRIi32"", (tmp >> 28) & 0x1); /* Fall through. */ case CHIPSET_SB89XX: case CHIPSET_HUDSON234: case CHIPSET_YANGTZE: case CHIPSET_PROMONTORY: - msg_pdbg(", SpiBusy=%i", (tmp >> 31) & 0x1); + msg_pdbg(", SpiBusy=%"PRIi32"", (tmp >> 31) & 0x1); default: break; } msg_pdbg("\n"); @@ -766,7 +757,7 @@ int sb600_probe_spi(const struct programmer_cfg *cfg, struct pci_dev *dev) * errors with illegal access bit */ if (amd_gen < CHIPSET_YANGTZE) - return ERROR_NONFATAL; + return ERROR_FLASHROM_NONFATAL; } if (amd_gen >= CHIPSET_SB89XX) { @@ -782,7 +773,7 @@ int sb600_probe_spi(const struct programmer_cfg *cfg, struct pci_dev *dev) smbus_dev = pcidev_find(0x1022, 0x790b); /* AMD FP4 */ if (!smbus_dev) { msg_perr("ERROR: SMBus device not found. Not enabling SPI.\n"); - return ERROR_NONFATAL; + return ERROR_FLASHROM_NONFATAL; } /* Note about the bit tests below: If a bit is zero, the GPIO is SPI. */ @@ -815,10 +806,10 @@ int sb600_probe_spi(const struct programmer_cfg *cfg, struct pci_dev *dev) } if (handle_speed(cfg, dev, amd_gen, sb600_spibar) != 0) - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; if (handle_imc(cfg, dev, amd_gen) != 0) - return ERROR_FATAL; + return ERROR_FLASHROM_FATAL; struct sb600spi_data *data = calloc(1, sizeof(*data)); if (!data) { diff --git a/scripts/llvm-cov b/scripts/llvm-cov new file mode 100755 index 000000000..b512b3dee --- /dev/null +++ b/scripts/llvm-cov @@ -0,0 +1,6 @@ +#!/bin/sh + +cd "${MESON_BUILD_ROOT}" +llvm-profdata merge -sparse default.profraw -o default.profdata +llvm-cov show -instr-profile=default.profdata -format=html -output-dir=. "$@" +echo "file://${MESON_BUILD_ROOT}/index.html" diff --git a/serial.c b/serial.c index 72f9ef686..577ccf43c 100644 --- a/serial.c +++ b/serial.c @@ -47,6 +47,10 @@ fdtype sp_fd = SER_INV_FD; * On Linux there is a non-standard way to use arbitrary baud rates that we use if there is no * matching standard rate, see custom_baud.c * + * On Darwin there is also a non-standard ioctl() to set arbitrary baud rates + * and any above 230400, see custom_baud_darwin.c and + * https://opensource.apple.com/source/IOSerialFamily/IOSerialFamily-91/tests/IOSerialTestLib.c.auto.html + * * On Windows there exist similar macros (starting with CBR_ instead of B) but they are only defined for * backwards compatibility and the API supports arbitrary baud rates in the same manner as the macros, see * http://msdn.microsoft.com/en-us/library/windows/desktop/aa363214(v=vs.85).aspx @@ -179,6 +183,7 @@ int serialport_config(fdtype fd, int baud) } msg_pdbg("Baud rate is %ld.\n", dcb.BaudRate); #else + int custom_baud = (baud >= 0 && use_custom_baud(baud, sp_baudtable)); struct termios wanted, observed; if (tcgetattr(fd, &observed) != 0) { msg_perr_strerror("Could not fetch original serial port configuration: "); @@ -186,8 +191,8 @@ int serialport_config(fdtype fd, int baud) } wanted = observed; if (baud >= 0) { - if (use_custom_baud(baud, sp_baudtable)) { - if (set_custom_baudrate(fd, baud)) { + if (custom_baud) { + if (set_custom_baudrate(fd, baud, BEFORE_FLAGS, NULL)) { msg_perr_strerror("Could not set custom baudrate: "); return 1; } @@ -198,7 +203,6 @@ int serialport_config(fdtype fd, int baud) msg_perr_strerror("Could not fetch serial port configuration: "); return 1; } - msg_pdbg("Using custom baud rate.\n"); } else { const struct baudentry *entry = round_baud(baud); if (cfsetispeed(&wanted, entry->flag) != 0 || cfsetospeed(&wanted, entry->flag) != 0) { @@ -212,6 +216,10 @@ int serialport_config(fdtype fd, int baud) wanted.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN); wanted.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL | IGNCR | INLCR); wanted.c_oflag &= ~OPOST; + if (custom_baud && set_custom_baudrate(fd, baud, WITH_FLAGS, &wanted)) { + msg_perr_strerror("Could not set custom baudrate: "); + return 1; + } if (tcsetattr(fd, TCSANOW, &wanted) != 0) { msg_perr_strerror("Could not change serial port configuration: "); return 1; @@ -236,6 +244,13 @@ int serialport_config(fdtype fd, int baud) (long)observed.c_oflag, (long)wanted.c_oflag ); } + if (custom_baud) { + if (set_custom_baudrate(fd, baud, AFTER_FLAGS, &wanted)) { + msg_perr_strerror("Could not set custom baudrate: "); + return 1; + } + msg_pdbg("Using custom baud rate.\n"); + } if (cfgetispeed(&observed) != cfgetispeed(&wanted) || cfgetospeed(&observed) != cfgetospeed(&wanted)) { msg_pwarn("Could not set baud rates exactly.\n"); @@ -362,10 +377,26 @@ void sp_flush_incoming(void) #if IS_WINDOWS PurgeComm(sp_fd, PURGE_RXCLEAR); #else - /* FIXME: error handling */ - tcflush(sp_fd, TCIFLUSH); + if (!tcflush(sp_fd, TCIFLUSH)) + return; + + if (errno == ENOTTY) { // TCP socket case: sp_fd is not a terminal descriptor - tcflush is not supported + unsigned char c; + int ret; + + do { + ret = serialport_read_nonblock(&c, 1, 1, NULL); + } while (ret == 0); + + // positive error code indicates no data available immediately - similar to EAGAIN/EWOULDBLOCK + // i.e. all buffered data was read + // negative error code indicates a permanent error + if (ret < 0) + msg_perr("Could not flush serial port incoming buffer: read has failed"); + } else { // any other errno indicates an unrecoverable sp_fd state + msg_perr_strerror("Could not flush serial port incoming buffer: "); + } #endif - return; } int serialport_shutdown(void *data) @@ -403,7 +434,7 @@ int serialport_write(const unsigned char *buf, unsigned int writecnt) if (!tmp) { msg_pdbg2("Empty write\n"); empty_writes--; - internal_delay(500); + default_delay(500); if (empty_writes == 0) { msg_perr("Serial port is unresponsive!\n"); return 1; @@ -510,7 +541,7 @@ int serialport_read_nonblock(unsigned char *c, unsigned int readcnt, unsigned in ret = 0; break; } - internal_delay(1000); /* 1ms units */ + default_delay(1000); /* 1ms units */ } if (really_read != NULL) *really_read = rd_bytes; @@ -596,7 +627,7 @@ int serialport_write_nonblock(const unsigned char *buf, unsigned int writecnt, u break; } } - internal_delay(1000); /* 1ms units */ + default_delay(1000); /* 1ms units */ } if (really_wrote != NULL) *really_wrote = wr_bytes; diff --git a/serprog.c b/serprog.c index a3a3db3e5..f738ef356 100644 --- a/serprog.c +++ b/serprog.c @@ -3,6 +3,7 @@ * * Copyright (C) 2009, 2011 Urja Rannikko * Copyright (C) 2009 Carl-Daniel Hailfinger + * Copyright (C) 2024 Riku Viitanen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -63,6 +64,7 @@ #define S_CMD_O_SPIOP 0x13 /* Perform SPI operation. */ #define S_CMD_S_SPI_FREQ 0x14 /* Set SPI clock frequency */ #define S_CMD_S_PIN_STATE 0x15 /* Enable/disable output drivers */ +#define S_CMD_S_SPI_CS 0x16 /* Set SPI chip select to use */ #define MSGHEADER "serprog: " @@ -157,7 +159,7 @@ static int sp_synchronize(void) goto err_out; } /* A second should be enough to get all the answers to the buffer */ - internal_delay(1000 * 1000); + default_delay(1000 * 1000); sp_flush_incoming(); /* Then try up to 8 times to send syncnop and get the correct special * @@ -453,17 +455,17 @@ static void *serprog_map(const char *descr, uintptr_t phys_addr, size_t len) return NULL; } +static void serprog_delay(const struct flashctx *flash, unsigned int usecs); + static struct spi_master spi_master_serprog = { .map_flash_region = serprog_map, .features = SPI_MASTER_4BA, .max_data_read = MAX_DATA_READ_UNLIMITED, .max_data_write = MAX_DATA_WRITE_UNLIMITED, .command = serprog_spi_send_command, - .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, - .probe_opcode = default_spi_probe_opcode, + .delay = serprog_delay, }; static int sp_check_opbuf_usage(int bytes_to_be_added) @@ -568,16 +570,33 @@ static void serprog_chip_readn(const struct flashctx *flash, uint8_t * buf, sp_do_read_n(&(buf[addrm-addr]), addrm, lenm); // FIXME: return error } +static void serprog_delay(const struct flashctx *flash, unsigned int usecs) +{ + unsigned char buf[4]; + msg_pspew("%s usecs=%d\n", __func__, usecs); + if (!sp_check_commandavail(S_CMD_O_DELAY)) { + msg_pdbg2("serprog_delay used, but programmer doesn't support delays natively - emulating\n"); + default_delay(usecs); + return; + } + if ((sp_max_write_n) && (sp_write_n_bytes)) + sp_pass_writen(); + sp_check_opbuf_usage(5); + buf[0] = ((usecs >> 0) & 0xFF); + buf[1] = ((usecs >> 8) & 0xFF); + buf[2] = ((usecs >> 16) & 0xFF); + buf[3] = ((usecs >> 24) & 0xFF); + sp_stream_buffer_op(S_CMD_O_DELAY, 4, buf); + sp_opbuf_usage += 5; + sp_prev_was_write = 0; +} + static const struct par_master par_master_serprog = { .map_flash_region = serprog_map, .chip_readb = serprog_chip_readb, - .chip_readw = fallback_chip_readw, - .chip_readl = fallback_chip_readl, .chip_readn = serprog_chip_readn, .chip_writeb = serprog_chip_writeb, - .chip_writew = fallback_chip_writew, - .chip_writel = fallback_chip_writel, - .chip_writen = fallback_chip_writen, + .delay = serprog_delay, }; static enum chipbustype serprog_buses_supported = BUS_NONE; @@ -725,7 +744,7 @@ static int serprog_init(const struct programmer_cfg *cfg) /* Check for the minimum operational set of commands. */ if (serprog_buses_supported & BUS_SPI) { uint8_t bt = BUS_SPI; - char *spispeed; + char *spispeed, *cs; if (sp_check_commandavail(S_CMD_O_SPIOP) == 0) { msg_perr("Error: SPI operation not supported while the " "bustype is SPI\n"); @@ -805,6 +824,33 @@ static int serprog_init(const struct programmer_cfg *cfg) } } free(spispeed); + cs = extract_programmer_param_str(cfg, "cs"); + if (cs && strlen(cs)) { + char *endptr = NULL; + errno = 0; + unsigned long cs_num = strtoul(cs, &endptr, 0); + if (errno || *endptr || cs_num > 255) { + msg_perr("Error: Invalid chip select requested! " + "Only 0-255 are valid.\n"); + free(cs); + goto init_err_cleanup_exit; + } + if (!sp_check_commandavail(S_CMD_S_SPI_CS)) { + msg_perr("Error: Setting SPI chip select is not supported!\n"); + free(cs); + goto init_err_cleanup_exit; + } + msg_pdbg(MSGHEADER "Requested to use chip select %lu.\n", cs_num); + uint8_t cs_num8 = cs_num; + if (sp_docommand(S_CMD_S_SPI_CS, 1, &cs_num8, 0, NULL)) { + msg_perr("Error: Chip select %u not supported " + "by programmer!\n", cs_num8); + free(cs); + goto init_err_cleanup_exit; + } + } + free(cs); + bt = serprog_buses_supported; if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL)) goto init_err_cleanup_exit; @@ -941,32 +987,10 @@ static int serprog_init(const struct programmer_cfg *cfg) return 1; } -static void serprog_delay(unsigned int usecs) -{ - unsigned char buf[4]; - msg_pspew("%s usecs=%d\n", __func__, usecs); - if (!sp_check_commandavail(S_CMD_O_DELAY)) { - msg_pdbg2("serprog_delay used, but programmer doesn't support delays natively - emulating\n"); - internal_delay(usecs); - return; - } - if ((sp_max_write_n) && (sp_write_n_bytes)) - sp_pass_writen(); - sp_check_opbuf_usage(5); - buf[0] = ((usecs >> 0) & 0xFF); - buf[1] = ((usecs >> 8) & 0xFF); - buf[2] = ((usecs >> 16) & 0xFF); - buf[3] = ((usecs >> 24) & 0xFF); - sp_stream_buffer_op(S_CMD_O_DELAY, 4, buf); - sp_opbuf_usage += 5; - sp_prev_was_write = 0; -} - const struct programmer_entry programmer_serprog = { .name = "serprog", .type = OTHER, /* FIXME */ .devs.note = "All programmer devices speaking the serprog protocol\n", .init = serprog_init, - .delay = serprog_delay, }; diff --git a/sfdp.c b/sfdp.c index b5494177d..868377933 100644 --- a/sfdp.c +++ b/sfdp.c @@ -35,7 +35,7 @@ static int spi_sfdp_read_sfdp_chunk(struct flashctx *flash, uint32_t address, ui */ 0 }; - msg_cspew("%s: addr=0x%x, len=%d, data:\n", __func__, address, len); + msg_cspew("%s: addr=0x%"PRIx32", len=%d, data:\n", __func__, address, len); newbuf = malloc(len + 1); if (!newbuf) return SPI_PROGRAMMER_ERROR; @@ -81,9 +81,9 @@ static int sfdp_add_uniform_eraser(struct flashchip *chip, uint8_t opcode, uint3 { int i; uint32_t total_size = chip->total_size * 1024; - erasefunc_t *erasefn = spi_get_erasefn_from_opcode(opcode); + enum block_erase_func erasefn = spi25_get_erasefn_from_opcode(opcode); - if (erasefn == NULL || total_size == 0 || block_size == 0 || + if (erasefn == NO_BLOCK_ERASE_FUNC || total_size == 0 || block_size == 0 || total_size % block_size != 0) { msg_cdbg("%s: invalid input, please report to " "flashrom@flashrom.org\n", __func__); @@ -96,12 +96,12 @@ static int sfdp_add_uniform_eraser(struct flashchip *chip, uint8_t opcode, uint3 if (eraser->eraseblocks[0].size == block_size && eraser->block_erase == erasefn) { msg_cdbg2(" Tried to add a duplicate block eraser: " - "%d x %d B with opcode 0x%02x.\n", + "%"PRId32" x %"PRId32" B with opcode 0x%02x.\n", total_size/block_size, block_size, opcode); return 1; } if (eraser->eraseblocks[0].size != 0 || - eraser->block_erase != NULL) { + eraser->block_erase != NO_BLOCK_ERASE_FUNC) { msg_cspew(" Block Eraser %d is already occupied.\n", i); continue; @@ -110,7 +110,7 @@ static int sfdp_add_uniform_eraser(struct flashchip *chip, uint8_t opcode, uint3 eraser->block_erase = erasefn; eraser->eraseblocks[0].size = block_size; eraser->eraseblocks[0].count = total_size/block_size; - msg_cdbg2(" Block eraser %d: %d x %d B with opcode " + msg_cdbg2(" Block eraser %d: %"PRId32" x %"PRId32" B with opcode " "0x%02x\n", i, total_size/block_size, block_size, opcode); return 0; @@ -179,11 +179,11 @@ static int sfdp_fill_flash(struct flashchip *chip, uint8_t *buf, uint16_t len) if (tmp32 & (1 << 2)) { msg_cdbg2("at least 64 B.\n"); chip->page_size = 64; - chip->write = spi_chip_write_256; + chip->write = SPI_CHIP_WRITE256; } else { msg_cdbg2("1 B only.\n"); chip->page_size = 256; - chip->write = spi_chip_write_1; + chip->write = SPI_CHIP_WRITE1; } if ((tmp32 & 0x3) == 0x1) { @@ -274,7 +274,7 @@ int probe_spi_sfdp(struct flashctx *flash) tmp32 |= ((unsigned int)buf[3]) << 24; if (tmp32 != 0x50444653) { - msg_cdbg2("Signature = 0x%08x (should be 0x50444653)\n", tmp32); + msg_cdbg2("Signature = 0x%08"PRIx32" (should be 0x50444653)\n", tmp32); msg_cdbg("No SFDP signature found.\n"); return 0; } @@ -320,7 +320,7 @@ int probe_spi_sfdp(struct flashctx *flash) hdrs[i].v_major, hdrs[i].v_minor); len = hdrs[i].len * 4; tmp32 = hdrs[i].ptp; - msg_cdbg2(" Length %d B, Parameter Table Pointer 0x%06x\n", + msg_cdbg2(" Length %d B, Parameter Table Pointer 0x%06"PRIx32"\n", len, tmp32); if (tmp32 + len >= (1 << 24)) { @@ -345,7 +345,7 @@ int probe_spi_sfdp(struct flashctx *flash) msg_cspew(" Parameter table contents:\n"); for (tmp32 = 0; tmp32 < len; tmp32++) { if ((tmp32 % 8) == 0) { - msg_cspew(" 0x%04x: ", tmp32); + msg_cspew(" 0x%04"PRIx32": ", tmp32); } msg_cspew(" %02x", tbuf[tmp32]); if ((tmp32 % 8) == 7) { diff --git a/sio.c b/sio.c index 845b57a04..2850595cc 100644 --- a/sio.c +++ b/sio.c @@ -18,31 +18,6 @@ #include "programmer.h" #include "hwaccess_x86_io.h" -void probe_superio(void) -{ - probe_superio_winbond(); - /* ITE probe causes SMSC LPC47N217 to power off the serial UART. - * Always probe for SMSC first, and if a SMSC Super I/O is detected - * at a given I/O port, do _not_ probe that port with the ITE probe. - * This means SMSC probing must be done before ITE probing. - */ - //probe_superio_smsc(); - probe_superio_ite(); -} - -int superio_count = 0; -#define SUPERIO_MAX_COUNT 3 - -struct superio superios[SUPERIO_MAX_COUNT]; - -int register_superio(struct superio s) -{ - if (superio_count == SUPERIO_MAX_COUNT) - return 1; - superios[superio_count++] = s; - return 0; -} - /* Generic Super I/O helper functions */ uint8_t sio_read(uint16_t port, uint8_t reg) { diff --git a/spi.c b/spi.c index 38d8d01a0..3554befd9 100644 --- a/spi.c +++ b/spi.c @@ -26,20 +26,7 @@ #include "programmer.h" #include "spi.h" -int spi_send_command(const struct flashctx *flash, unsigned int writecnt, - unsigned int readcnt, const unsigned char *writearr, - unsigned char *readarr) -{ - return flash->mst->spi.command(flash, writecnt, readcnt, writearr, - readarr); -} - -int spi_send_multicommand(const struct flashctx *flash, struct spi_command *cmds) -{ - return flash->mst->spi.multicommand(flash, cmds); -} - -int default_spi_send_command(const struct flashctx *flash, unsigned int writecnt, +static int default_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr) @@ -60,7 +47,7 @@ int default_spi_send_command(const struct flashctx *flash, unsigned int writecnt return spi_send_multicommand(flash, cmd); } -int default_spi_send_multicommand(const struct flashctx *flash, +static int default_spi_send_multicommand(const struct flashctx *flash, struct spi_command *cmds) { int result = 0; @@ -71,6 +58,22 @@ int default_spi_send_multicommand(const struct flashctx *flash, return result; } +int spi_send_command(const struct flashctx *flash, unsigned int writecnt, + unsigned int readcnt, const unsigned char *writearr, + unsigned char *readarr) +{ + if (flash->mst->spi.command) + return flash->mst->spi.command(flash, writecnt, readcnt, writearr, readarr); + return default_spi_send_command(flash, writecnt, readcnt, writearr, readarr); +} + +int spi_send_multicommand(const struct flashctx *flash, struct spi_command *cmds) +{ + if (flash->mst->spi.multicommand) + return flash->mst->spi.multicommand(flash, cmds); + return default_spi_send_multicommand(flash, cmds); +} + int default_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len) { @@ -131,12 +134,16 @@ int spi_chip_write_256(struct flashctx *flash, const uint8_t *buf, unsigned int int spi_aai_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) { - return flash->mst->spi.write_aai(flash, buf, start, len); + if (flash->mst->spi.write_aai) + return flash->mst->spi.write_aai(flash, buf, start, len); + return default_spi_write_aai(flash, buf, start, len); } -bool default_spi_probe_opcode(struct flashctx *flash, uint8_t opcode) +bool spi_probe_opcode(const struct flashctx *flash, uint8_t opcode) { - return true; + if (!flash->mst->spi.probe_opcode) + return true; /* no probe_opcode implies default of supported. */ + return flash->mst->spi.probe_opcode(flash, opcode); } int register_spi_master(const struct spi_master *mst, void *data) @@ -150,10 +157,7 @@ int register_spi_master(const struct spi_master *mst, void *data) } } - if (!mst->write_aai || !mst->write_256 || !mst->read || !mst->command || - !mst->multicommand || !mst->probe_opcode || - ((mst->command == default_spi_send_command) && - (mst->multicommand == default_spi_send_multicommand))) { + if (!mst->write_256 || !mst->read || (!mst->command && !mst->multicommand)) { msg_perr("%s called with incomplete master definition. " "Please report a bug at flashrom@flashrom.org\n", __func__); @@ -167,3 +171,64 @@ int register_spi_master(const struct spi_master *mst, void *data) rmst.spi.data = data; return register_master(&rmst); } + +/* + * The following array has erasefn and opcode list pair. The opcode list pair is + * 0 termintated and must have size one more than the maximum number of opcodes + * used by any erasefn. Also the opcodes must be in increasing order. + */ +static const struct { + enum block_erase_func func; + uint8_t opcode[3]; +} function_opcode_list[] = { + {SPI_BLOCK_ERASE_20, {0x20}}, + {SPI_BLOCK_ERASE_21, {0x21}}, + {SPI_BLOCK_ERASE_50, {0x50}}, + {SPI_BLOCK_ERASE_52, {0x52}}, + {SPI_BLOCK_ERASE_53, {0x53}}, + {SPI_BLOCK_ERASE_5C, {0x5c}}, + {SPI_BLOCK_ERASE_60, {0x60}}, + {SPI_BLOCK_ERASE_62, {0x62}}, + {SPI_BLOCK_ERASE_81, {0x81}}, + {SPI_BLOCK_ERASE_C4, {0xc4}}, + {SPI_BLOCK_ERASE_C7, {0xc7}}, + {SPI_BLOCK_ERASE_D7, {0xd7}}, + {SPI_BLOCK_ERASE_D8, {0xd8}}, + {SPI_BLOCK_ERASE_DB, {0xdb}}, + {SPI_BLOCK_ERASE_DC, {0xdc}}, + //AT45CS1282 + {SPI_ERASE_AT45CS_SECTOR, {0x50, 0x7c, 0}}, + //AT45DB** + {SPI_ERASE_AT45DB_PAGE, {0x81}}, + {SPI_ERASE_AT45DB_BLOCK, {0x50}}, + {SPI_ERASE_AT45DB_SECTOR, {0x7c}}, + {SPI_ERASE_AT45DB_CHIP, {0xc7}}, + //SF25F** + {S25FL_BLOCK_ERASE, {0xdc}}, + {S25FS_BLOCK_ERASE_D8, {0xd8}}, +}; + +/* + * @brief Get erase function pointer from passed opcode list. + * + * Get the pointer to the erase function which uses passed opcodes and is used + * by the passed flashcip. The passed opcode_list must have opcodes in + * increasing order. + * + * @param chip Pointer to the flashchip structure. + * @param opcode_list Pointer to the array of opcodes. + * @param opcode_count Number of opcodes in 'opcode_list' + * + * @result Pointer to erase function matching 'chip' and 'opcode_list' or NULL on failure + */ +const uint8_t *spi_get_opcode_from_erasefn(enum block_erase_func func) +{ + size_t i; + for (i = 0; i < ARRAY_SIZE(function_opcode_list); i++) { + if (function_opcode_list[i].func == func) + return function_opcode_list[i].opcode; + } + msg_cinfo("%s: unknown erase function (0x%d). Please report " + "this at flashrom@flashrom.org\n", __func__, func); + return NULL; +} diff --git a/spi25.c b/spi25.c index 6d160ebbb..6a6ee75da 100644 --- a/spi25.c +++ b/spi25.c @@ -141,7 +141,7 @@ static int compare_id(const struct flashctx *flash, uint32_t id1, uint32_t id2) { const struct flashchip *chip = flash->chip; - msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2); + msg_cdbg("%s: id1 0x%02"PRIx32", id2 0x%02"PRIx32"\n", __func__, id1, id2); if (id1 == chip->manufacture_id && id2 == chip->model_id) return 1; @@ -232,7 +232,7 @@ int probe_spi_res1(struct flashctx *flash) id2 = readarr[0]; - msg_cdbg("%s: id 0x%x\n", __func__, id2); + msg_cdbg("%s: id 0x%"PRIx32"\n", __func__, id2); if (id2 != flash->chip->model_id) return 0; @@ -252,7 +252,7 @@ int probe_spi_res2(struct flashctx *flash) id1 = id_cache[RES2].bytes[0]; id2 = id_cache[RES2].bytes[1]; - msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2); + msg_cdbg("%s: id1 0x%"PRIx32", id2 0x%"PRIx32"\n", __func__, id1, id2); if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id) return 0; @@ -272,7 +272,7 @@ int probe_spi_res3(struct flashctx *flash) id1 = (id_cache[RES3].bytes[0] << 8) | id_cache[RES3].bytes[1]; id2 = id_cache[RES3].bytes[3]; - msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2); + msg_cdbg("%s: id1 0x%"PRIx32", id2 0x%"PRIx32"\n", __func__, id1, id2); if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id) return 0; @@ -294,7 +294,7 @@ int probe_spi_at25f(struct flashctx *flash) id1 = readarr[0]; id2 = readarr[1]; - msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2); + msg_cdbg("%s: id1 0x%02"PRIx32", id2 0x%02"PRIx32"\n", __func__, id1, id2); if (id1 == flash->chip->manufacture_id && id2 == flash->chip->model_id) return 1; @@ -313,7 +313,7 @@ static int spi_poll_wip(struct flashctx *const flash, const unsigned int poll_de if (!(status & SPI_SR_WIP)) return 0; - programmer_delay(poll_delay); + programmer_delay(flash, poll_delay); } } @@ -619,48 +619,36 @@ int spi_block_erase_dc(struct flashctx *flash, unsigned int addr, unsigned int b } static const struct { - erasefunc_t *func; + enum block_erase_func func; uint8_t opcode; -} function_opcode_list[] = { - {&spi_block_erase_20, 0x20}, - {&spi_block_erase_21, 0x21}, - {&spi_block_erase_50, 0x50}, - {&spi_block_erase_52, 0x52}, - {&spi_block_erase_53, 0x53}, - {&spi_block_erase_5c, 0x5c}, - {&spi_block_erase_60, 0x60}, - {&spi_block_erase_62, 0x62}, - {&spi_block_erase_81, 0x81}, - {&spi_block_erase_c4, 0xc4}, - {&spi_block_erase_c7, 0xc7}, - {&spi_block_erase_d7, 0xd7}, - {&spi_block_erase_d8, 0xd8}, - {&spi_block_erase_db, 0xdb}, - {&spi_block_erase_dc, 0xdc}, +} spi25_function_opcode_list[] = { + {SPI_BLOCK_ERASE_20, 0x20}, + {SPI_BLOCK_ERASE_21, 0x21}, + {SPI_BLOCK_ERASE_50, 0x50}, + {SPI_BLOCK_ERASE_52, 0x52}, + {SPI_BLOCK_ERASE_53, 0x53}, + {SPI_BLOCK_ERASE_5C, 0x5c}, + {SPI_BLOCK_ERASE_60, 0x60}, + {SPI_BLOCK_ERASE_62, 0x62}, + {SPI_BLOCK_ERASE_81, 0x81}, + {SPI_BLOCK_ERASE_C4, 0xc4}, + {SPI_BLOCK_ERASE_C7, 0xc7}, + {SPI_BLOCK_ERASE_D7, 0xd7}, + {SPI_BLOCK_ERASE_D8, 0xd8}, + {SPI_BLOCK_ERASE_DB, 0xdb}, + {SPI_BLOCK_ERASE_DC, 0xdc}, }; -erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode) +enum block_erase_func spi25_get_erasefn_from_opcode(uint8_t opcode) { size_t i; - for (i = 0; i < ARRAY_SIZE(function_opcode_list); i++) { - if (function_opcode_list[i].opcode == opcode) - return function_opcode_list[i].func; + for (i = 0; i < ARRAY_SIZE(spi25_function_opcode_list); i++) { + if (spi25_function_opcode_list[i].opcode == opcode) + return spi25_function_opcode_list[i].func; } msg_cinfo("%s: unknown erase opcode (0x%02x). Please report " "this at flashrom@flashrom.org\n", __func__, opcode); - return NULL; -} - -uint8_t spi_get_opcode_from_erasefn(erasefunc_t *func) -{ - size_t i; - for (i = 0; i < ARRAY_SIZE(function_opcode_list); i++) { - if (function_opcode_list[i].func == func) - return function_opcode_list[i].opcode; - } - msg_cinfo("%s: unknown erase function (0x%p). Please report " - "this at flashrom@flashrom.org\n", __func__, func); - return 0x00; //Assuming 0x00 is not a erase function opcode + return NO_BLOCK_ERASE_FUNC; } static int spi_nbyte_program(struct flashctx *flash, unsigned int addr, const uint8_t *bytes, unsigned int len) diff --git a/spi25_statusreg.c b/spi25_statusreg.c index 5dbba75ca..ceb2c7796 100644 --- a/spi25_statusreg.c +++ b/spi25_statusreg.c @@ -17,8 +17,11 @@ * GNU General Public License for more details. */ +#include + #include "flash.h" #include "chipdrivers.h" +#include "programmer.h" #include "spi.h" /* === Generic functions === */ @@ -100,11 +103,40 @@ int spi_write_register(const struct flashctx *flash, enum flash_reg reg, uint8_t } msg_cerr("Cannot write SR3: unsupported by chip\n"); return 1; + case SECURITY: + /* + * Security register doesn't have a normal write operation. Instead, + * there are separate commands that set individual OTP bits. + */ + msg_cerr("Cannot write SECURITY: unsupported by design\n"); + return 1; + case CONFIG: + /* + * This one is read via a separate command, but written as if it's SR2 + * in FEATURE_WRSR_EXT2 case of WRSR command. + */ + if (feature_bits & FEATURE_CFGR) { + write_cmd[0] = JEDEC_WRSR; + if (spi_read_register(flash, STATUS1, &write_cmd[1])) { + msg_cerr("Writing CONFIG failed: failed to read SR1 for writeback.\n"); + return 1; + } + write_cmd[2] = value; + write_cmd_len = 3; + break; + } + msg_cerr("Cannot write CONFIG: unsupported by chip\n"); + return 1; default: msg_cerr("Cannot write register: unknown register\n"); return 1; } + if (!spi_probe_opcode(flash, write_cmd[0])) { + msg_pdbg("%s: write to register %d not supported by programmer, ignoring.\n", __func__, reg); + return SPI_INVALID_OPCODE; + } + uint8_t enable_cmd; if (feature_bits & FEATURE_WRSR_WREN) { enable_cmd = JEDEC_WREN; @@ -152,7 +184,7 @@ int spi_write_register(const struct flashctx *flash, enum flash_reg reg, uint8_t */ int delay_ms = 5000; if (reg == STATUS1) { - programmer_delay(100 * 1000); + programmer_delay(flash, 100 * 1000); delay_ms -= 100; } @@ -163,7 +195,7 @@ int spi_write_register(const struct flashctx *flash, enum flash_reg reg, uint8_t return result; if ((status & SPI_SR_WIP) == 0) return 0; - programmer_delay(10 * 1000); + programmer_delay(flash, 10 * 1000); } @@ -195,11 +227,30 @@ int spi_read_register(const struct flashctx *flash, enum flash_reg reg, uint8_t } msg_cerr("Cannot read SR3: unsupported by chip\n"); return 1; + case SECURITY: + if (feature_bits & FEATURE_SCUR) { + read_cmd = JEDEC_RDSCUR; + break; + } + msg_cerr("Cannot read SECURITY: unsupported by chip\n"); + return 1; + case CONFIG: + if (feature_bits & FEATURE_CFGR) { + read_cmd = JEDEC_RDCR; + break; + } + msg_cerr("Cannot read CONFIG: unsupported by chip\n"); + return 1; default: msg_cerr("Cannot read register: unknown register\n"); return 1; } + if (!spi_probe_opcode(flash, read_cmd)) { + msg_pdbg("%s: read from register %d not supported by programmer.\n", __func__, reg); + return SPI_INVALID_OPCODE; + } + /* FIXME: No workarounds for driver/hardware bugs in generic code. */ /* JEDEC_RDSR_INSIZE=1 but wbsio needs 2 */ uint8_t readarr[2]; @@ -211,11 +262,15 @@ int spi_read_register(const struct flashctx *flash, enum flash_reg reg, uint8_t } *value = readarr[0]; + msg_cspew("%s: read_cmd 0x%02x returned 0x%02x\n", __func__, read_cmd, readarr[0]); return 0; } -static int spi_restore_status(struct flashctx *flash, uint8_t status) +static int spi_restore_status(struct flashctx *flash, void *data) { + uint8_t status = *(uint8_t *)data; + free(data); + msg_cdbg("restoring chip status (0x%02x)\n", status); return spi_write_register(flash, STATUS1, status); } @@ -255,7 +310,13 @@ static int spi_disable_blockprotect_generic(struct flashctx *flash, uint8_t bp_m } /* Restore status register content upon exit in finalize_flash_access(). */ - register_chip_restore(spi_restore_status, flash, status); + uint8_t *data = calloc(1, sizeof(uint8_t)); + if (!data) { + msg_cerr("Out of memory!\n"); + return 1; + } + *data = status; + register_chip_restore(spi_restore_status, flash, data); msg_cdbg("Some block protection in effect, disabling... "); if ((status & lock_mask) != 0) { @@ -294,8 +355,9 @@ static int spi_disable_blockprotect_generic(struct flashctx *flash, uint8_t bp_m if ((status & bp_mask) != 0) { msg_cerr("Block protection could not be disabled!\n"); - if (flash->chip->printlock) - flash->chip->printlock(flash); + printlockfunc_t *printlock = lookup_printlock_func_ptr(flash); + if (printlock) + printlock(flash); return 1; } msg_cdbg("disabled.\n"); @@ -303,12 +365,12 @@ static int spi_disable_blockprotect_generic(struct flashctx *flash, uint8_t bp_m } /* A common block protection disable that tries to unset the status register bits masked by 0x3C. */ -int spi_disable_blockprotect(struct flashctx *flash) +static int spi_disable_blockprotect(struct flashctx *flash) { return spi_disable_blockprotect_generic(flash, 0x3C, 0, 0, 0xFF); } -int spi_disable_blockprotect_sst26_global_unprotect(struct flashctx *flash) +static int spi_disable_blockprotect_sst26_global_unprotect(struct flashctx *flash) { int result = spi_write_enable(flash); if (result) @@ -323,7 +385,7 @@ int spi_disable_blockprotect_sst26_global_unprotect(struct flashctx *flash) /* A common block protection disable that tries to unset the status register bits masked by 0x0C (BP0-1) and * protected/locked by bit #7. Useful when bits 4-5 may be non-0). */ -int spi_disable_blockprotect_bp1_srwd(struct flashctx *flash) +static int spi_disable_blockprotect_bp1_srwd(struct flashctx *flash) { return spi_disable_blockprotect_generic(flash, 0x0C, 1 << 7, 0, 0xFF); } @@ -331,21 +393,21 @@ int spi_disable_blockprotect_bp1_srwd(struct flashctx *flash) /* A common block protection disable that tries to unset the status register bits masked by 0x1C (BP0-2) and * protected/locked by bit #7. Useful when bit #5 is neither a protection bit nor reserved (and hence possibly * non-0). */ -int spi_disable_blockprotect_bp2_srwd(struct flashctx *flash) +static int spi_disable_blockprotect_bp2_srwd(struct flashctx *flash) { return spi_disable_blockprotect_generic(flash, 0x1C, 1 << 7, 0, 0xFF); } /* A common block protection disable that tries to unset the status register bits masked by 0x3C (BP0-3) and * protected/locked by bit #7. */ -int spi_disable_blockprotect_bp3_srwd(struct flashctx *flash) +static int spi_disable_blockprotect_bp3_srwd(struct flashctx *flash) { return spi_disable_blockprotect_generic(flash, 0x3C, 1 << 7, 0, 0xFF); } /* A common block protection disable that tries to unset the status register bits masked by 0x7C (BP0-4) and * protected/locked by bit #7. */ -int spi_disable_blockprotect_bp4_srwd(struct flashctx *flash) +static int spi_disable_blockprotect_bp4_srwd(struct flashctx *flash) { return spi_disable_blockprotect_generic(flash, 0x7C, 1 << 7, 0, 0xFF); } @@ -410,7 +472,7 @@ void spi_prettyprint_status_register_bit(uint8_t status, int bit) msg_cdbg("Chip status register: Bit %i is %sset\n", bit, (status & (1 << bit)) ? "" : "not "); } -int spi_prettyprint_status_register_plain(struct flashctx *flash) +static int spi_prettyprint_status_register_plain(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -421,7 +483,7 @@ int spi_prettyprint_status_register_plain(struct flashctx *flash) } /* Print the plain hex value and the welwip bits only. */ -int spi_prettyprint_status_register_default_welwip(struct flashctx *flash) +static int spi_prettyprint_status_register_default_welwip(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -437,7 +499,7 @@ int spi_prettyprint_status_register_default_welwip(struct flashctx *flash) * AMIC A25L series * and MX MX25L512 */ -int spi_prettyprint_status_register_bp1_srwd(struct flashctx *flash) +static int spi_prettyprint_status_register_bp1_srwd(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -458,7 +520,7 @@ int spi_prettyprint_status_register_bp1_srwd(struct flashctx *flash) * AMIC A25L series * PMC Pm25LD series */ -int spi_prettyprint_status_register_bp2_srwd(struct flashctx *flash) +static int spi_prettyprint_status_register_bp2_srwd(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -478,7 +540,7 @@ int spi_prettyprint_status_register_bp2_srwd(struct flashctx *flash) * ST M25P series * MX MX25L series */ -int spi_prettyprint_status_register_bp3_srwd(struct flashctx *flash) +static int spi_prettyprint_status_register_bp3_srwd(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -493,7 +555,7 @@ int spi_prettyprint_status_register_bp3_srwd(struct flashctx *flash) return 0; } -int spi_prettyprint_status_register_bp4_srwd(struct flashctx *flash) +static int spi_prettyprint_status_register_bp4_srwd(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -507,7 +569,7 @@ int spi_prettyprint_status_register_bp4_srwd(struct flashctx *flash) return 0; } -int spi_prettyprint_status_register_bp2_bpl(struct flashctx *flash) +static int spi_prettyprint_status_register_bp2_bpl(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -523,7 +585,7 @@ int spi_prettyprint_status_register_bp2_bpl(struct flashctx *flash) return 0; } -int spi_prettyprint_status_register_bp2_tb_bpl(struct flashctx *flash) +static int spi_prettyprint_status_register_bp2_tb_bpl(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -539,16 +601,7 @@ int spi_prettyprint_status_register_bp2_tb_bpl(struct flashctx *flash) return 0; } -/* === Amic === - * FIXME: spi_disable_blockprotect is incorrect but works fine for chips using - * spi_prettyprint_status_register_bp1_srwd or - * spi_prettyprint_status_register_bp2_srwd. - * FIXME: spi_disable_blockprotect is incorrect and will fail for chips using - * spi_prettyprint_status_register_amic_a25l032 if those have locks controlled - * by the second status register. - */ - -int spi_prettyprint_status_register_amic_a25l032(struct flashctx *flash) +static int spi_prettyprint_status_register_srwd_sec_tb_bp2_welwip(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -607,7 +660,7 @@ static void spi_prettyprint_status_register_atmel_at25_swp(uint8_t status) } } -int spi_prettyprint_status_register_at25df(struct flashctx *flash) +static int spi_prettyprint_status_register_at25df(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -624,7 +677,7 @@ int spi_prettyprint_status_register_at25df(struct flashctx *flash) return 0; } -int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash) +static int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash) { /* FIXME: We should check the security lockdown. */ msg_cdbg("Ignoring security lockdown (if present)\n"); @@ -633,7 +686,7 @@ int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash) } /* used for AT25F512, AT25F1024(A), AT25F2048 */ -int spi_prettyprint_status_register_at25f(struct flashctx *flash) +static int spi_prettyprint_status_register_at25f(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -651,7 +704,7 @@ int spi_prettyprint_status_register_at25f(struct flashctx *flash) return 0; } -int spi_prettyprint_status_register_at25f512a(struct flashctx *flash) +static int spi_prettyprint_status_register_at25f512a(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -670,7 +723,7 @@ int spi_prettyprint_status_register_at25f512a(struct flashctx *flash) return 0; } -int spi_prettyprint_status_register_at25f512b(struct flashctx *flash) +static int spi_prettyprint_status_register_at25f512b(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -687,7 +740,7 @@ int spi_prettyprint_status_register_at25f512b(struct flashctx *flash) return 0; } -int spi_prettyprint_status_register_at25f4096(struct flashctx *flash) +static int spi_prettyprint_status_register_at25f4096(struct flashctx *flash) { uint8_t status; @@ -705,7 +758,7 @@ int spi_prettyprint_status_register_at25f4096(struct flashctx *flash) return 0; } -int spi_prettyprint_status_register_at25fs010(struct flashctx *flash) +static int spi_prettyprint_status_register_at25fs010(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -728,7 +781,7 @@ int spi_prettyprint_status_register_at25fs010(struct flashctx *flash) return 0; } -int spi_prettyprint_status_register_at25fs040(struct flashctx *flash) +static int spi_prettyprint_status_register_at25fs040(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -743,7 +796,7 @@ int spi_prettyprint_status_register_at25fs040(struct flashctx *flash) return 0; } -int spi_prettyprint_status_register_at26df081a(struct flashctx *flash) +static int spi_prettyprint_status_register_at26df081a(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -765,46 +818,46 @@ int spi_prettyprint_status_register_at26df081a(struct flashctx *flash) * sectors at once by writing 0 not only the protection bits (2 and 3) but also completely unrelated bits (4 and * 5) which normally are not touched. * Affected are all known Atmel chips matched by AT2[56]D[FLQ]..1A? but the AT26DF041. */ -int spi_disable_blockprotect_at2x_global_unprotect(struct flashctx *flash) +static int spi_disable_blockprotect_at2x_global_unprotect(struct flashctx *flash) { return spi_disable_blockprotect_generic(flash, 0x0C, 1 << 7, 1 << 4, 0x00); } -int spi_disable_blockprotect_at2x_global_unprotect_sec(struct flashctx *flash) +static int spi_disable_blockprotect_at2x_global_unprotect_sec(struct flashctx *flash) { /* FIXME: We should check the security lockdown. */ msg_cinfo("Ignoring security lockdown (if present)\n"); return spi_disable_blockprotect_at2x_global_unprotect(flash); } -int spi_disable_blockprotect_at25f(struct flashctx *flash) +static int spi_disable_blockprotect_at25f(struct flashctx *flash) { return spi_disable_blockprotect_generic(flash, 0x0C, 1 << 7, 0, 0xFF); } -int spi_disable_blockprotect_at25f512a(struct flashctx *flash) +static int spi_disable_blockprotect_at25f512a(struct flashctx *flash) { return spi_disable_blockprotect_generic(flash, 0x04, 1 << 7, 0, 0xFF); } -int spi_disable_blockprotect_at25f512b(struct flashctx *flash) +static int spi_disable_blockprotect_at25f512b(struct flashctx *flash) { return spi_disable_blockprotect_generic(flash, 0x04, 1 << 7, 1 << 4, 0xFF); } -int spi_disable_blockprotect_at25fs010(struct flashctx *flash) +static int spi_disable_blockprotect_at25fs010(struct flashctx *flash) { return spi_disable_blockprotect_generic(flash, 0x6C, 1 << 7, 0, 0xFF); } -int spi_disable_blockprotect_at25fs040(struct flashctx *flash) +static int spi_disable_blockprotect_at25fs040(struct flashctx *flash) { return spi_disable_blockprotect_generic(flash, 0x7C, 1 << 7, 0, 0xFF); } /* === Eon === */ -int spi_prettyprint_status_register_en25s_wp(struct flashctx *flash) +static int spi_prettyprint_status_register_en25s_wp(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -821,12 +874,12 @@ int spi_prettyprint_status_register_en25s_wp(struct flashctx *flash) /* === Intel/Numonyx/Micron - Spansion === */ -int spi_disable_blockprotect_n25q(struct flashctx *flash) +static int spi_disable_blockprotect_n25q(struct flashctx *flash) { return spi_disable_blockprotect_generic(flash, 0x5C, 1 << 7, 0, 0xFF); } -int spi_prettyprint_status_register_n25q(struct flashctx *flash) +static int spi_prettyprint_status_register_n25q(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -848,13 +901,54 @@ int spi_prettyprint_status_register_n25q(struct flashctx *flash) /* Used by Intel/Numonyx S33 and Spansion S25FL-S chips */ /* TODO: Clear P_FAIL and E_FAIL with Clear SR Fail Flags Command (30h) here? */ -int spi_disable_blockprotect_bp2_ep_srwd(struct flashctx *flash) +static int spi_disable_blockprotect_bp2_ep_srwd(struct flashctx *flash) { return spi_disable_blockprotect_bp2_srwd(flash); } +blockprotect_func_t *lookup_blockprotect_func_ptr(const struct flashchip *const chip) +{ + switch (chip->unlock) { + case SPI_DISABLE_BLOCKPROTECT: return spi_disable_blockprotect; + case SPI_DISABLE_BLOCKPROTECT_BP2_EP_SRWD: return spi_disable_blockprotect_bp2_ep_srwd; + case SPI_DISABLE_BLOCKPROTECT_BP1_SRWD: return spi_disable_blockprotect_bp1_srwd; + case SPI_DISABLE_BLOCKPROTECT_BP2_SRWD: return spi_disable_blockprotect_bp2_srwd; + case SPI_DISABLE_BLOCKPROTECT_BP3_SRWD: return spi_disable_blockprotect_bp3_srwd; + case SPI_DISABLE_BLOCKPROTECT_BP4_SRWD: return spi_disable_blockprotect_bp4_srwd; + case SPI_DISABLE_BLOCKPROTECT_AT45DB: return spi_disable_blockprotect_at45db; /* at45db.c */ + case SPI_DISABLE_BLOCKPROTECT_AT25F: return spi_disable_blockprotect_at25f; + case SPI_DISABLE_BLOCKPROTECT_AT25FS010: return spi_disable_blockprotect_at25fs010; + case SPI_DISABLE_BLOCKPROTECT_AT25FS040: return spi_disable_blockprotect_at25fs040; + case SPI_DISABLE_BLOCKPROTECT_AT25F512A: return spi_disable_blockprotect_at25f512a; + case SPI_DISABLE_BLOCKPROTECT_AT25F512B: return spi_disable_blockprotect_at25f512b; + case SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT: return spi_disable_blockprotect_at2x_global_unprotect; + case SPI_DISABLE_BLOCKPROTECT_AT2X_GLOBAL_UNPROTECT_SEC: return spi_disable_blockprotect_at2x_global_unprotect_sec; + case SPI_DISABLE_BLOCKPROTECT_SST26_GLOBAL_UNPROTECT: return spi_disable_blockprotect_sst26_global_unprotect; + case SPI_DISABLE_BLOCKPROTECT_N25Q: return spi_disable_blockprotect_n25q; + /* fallthough to lookup_jedec_blockprotect_func_ptr() */ + case UNLOCK_REGSPACE2_BLOCK_ERASER_0: + case UNLOCK_REGSPACE2_BLOCK_ERASER_1: + case UNLOCK_REGSPACE2_UNIFORM_32K: + case UNLOCK_REGSPACE2_UNIFORM_64K: + return lookup_jedec_blockprotect_func_ptr(chip); + /* fallthough to lookup_82802ab_blockprotect_func_ptr() */ + case UNLOCK_28F004S5: + case UNLOCK_LH28F008BJT: + return lookup_82802ab_blockprotect_func_ptr(chip); + case UNLOCK_SST_FWHUB: return unlock_sst_fwhub; /* sst_fwhub.c */ + case UNPROTECT_28SF040: return unprotect_28sf040; /* sst28sf040.c */ + /* default: non-total function, 0 indicates no unlock function set. + * We explicitly do not want a default catch-all case in the switch + * to ensure unhandled enum's are compiler warnings. + */ + case NO_BLOCKPROTECT_FUNC: return NULL; + }; + + return NULL; +} + /* Used by Intel/Numonyx S33 and Spansion S25FL-S chips */ -int spi_prettyprint_status_register_bp2_ep_srwd(struct flashctx *flash) +static int spi_prettyprint_status_register_bp2_ep_srwd(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -885,7 +979,7 @@ static void spi_prettyprint_status_register_sst25_common(uint8_t status) spi_prettyprint_status_register_welwip(status); } -int spi_prettyprint_status_register_sst25(struct flashctx *flash) +static int spi_prettyprint_status_register_sst25(struct flashctx *flash) { uint8_t status; int ret = spi_read_register(flash, STATUS1, &status); @@ -895,7 +989,7 @@ int spi_prettyprint_status_register_sst25(struct flashctx *flash) return 0; } -int spi_prettyprint_status_register_sst25vf016(struct flashctx *flash) +static int spi_prettyprint_status_register_sst25vf016(struct flashctx *flash) { static const char *const bpt[] = { "none", @@ -915,7 +1009,7 @@ int spi_prettyprint_status_register_sst25vf016(struct flashctx *flash) return 0; } -int spi_prettyprint_status_register_sst25vf040b(struct flashctx *flash) +static int spi_prettyprint_status_register_sst25vf040b(struct flashctx *flash) { static const char *const bpt[] = { "none", @@ -932,3 +1026,58 @@ int spi_prettyprint_status_register_sst25vf040b(struct flashctx *flash) msg_cdbg("Resulting block protection : %s\n", bpt[(status & 0x1c) >> 2]); return 0; } + +printlockfunc_t *lookup_printlock_func_ptr(struct flashctx *flash) +{ + switch (flash->chip->printlock) { + case PRINTLOCK_AT49F: return &printlock_at49f; + case PRINTLOCK_REGSPACE2_BLOCK_ERASER_0: return &printlock_regspace2_block_eraser_0; + case PRINTLOCK_REGSPACE2_BLOCK_ERASER_1: return &printlock_regspace2_block_eraser_1; + case PRINTLOCK_SST_FWHUB: return &printlock_sst_fwhub; + case PRINTLOCK_W39F010: return &printlock_w39f010; + case PRINTLOCK_W39L010: return &printlock_w39l010; + case PRINTLOCK_W39L020: return &printlock_w39l020; + case PRINTLOCK_W39L040: return &printlock_w39l040; + case PRINTLOCK_W39V040A: return &printlock_w39v040a; + case PRINTLOCK_W39V040B: return &printlock_w39v040b; + case PRINTLOCK_W39V040C: return &printlock_w39v040c; + case PRINTLOCK_W39V040FA: return &printlock_w39v040fa; + case PRINTLOCK_W39V040FB: return &printlock_w39v040fb; + case PRINTLOCK_W39V040FC: return &printlock_w39v040fc; + case PRINTLOCK_W39V080A: return &printlock_w39v080a; + case PRINTLOCK_W39V080FA: return &printlock_w39v080fa; + case PRINTLOCK_W39V080FA_DUAL: return &printlock_w39v080fa_dual; + case SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF: return &spi_prettyprint_status_register_at25df; + case SPI_PRETTYPRINT_STATUS_REGISTER_AT25DF_SEC: return &spi_prettyprint_status_register_at25df_sec; + case SPI_PRETTYPRINT_STATUS_REGISTER_AT25F: return &spi_prettyprint_status_register_at25f; + case SPI_PRETTYPRINT_STATUS_REGISTER_AT25F4096: return &spi_prettyprint_status_register_at25f4096; + case SPI_PRETTYPRINT_STATUS_REGISTER_AT25F512A: return &spi_prettyprint_status_register_at25f512a; + case SPI_PRETTYPRINT_STATUS_REGISTER_AT25F512B: return &spi_prettyprint_status_register_at25f512b; + case SPI_PRETTYPRINT_STATUS_REGISTER_AT25FS010: return &spi_prettyprint_status_register_at25fs010; + case SPI_PRETTYPRINT_STATUS_REGISTER_AT25FS040: return &spi_prettyprint_status_register_at25fs040; + case SPI_PRETTYPRINT_STATUS_REGISTER_AT26DF081A: return &spi_prettyprint_status_register_at26df081a; + case SPI_PRETTYPRINT_STATUS_REGISTER_AT45DB: return &spi_prettyprint_status_register_at45db; + case SPI_PRETTYPRINT_STATUS_REGISTER_BP1_SRWD: return &spi_prettyprint_status_register_bp1_srwd; + case SPI_PRETTYPRINT_STATUS_REGISTER_BP2_BPL: return &spi_prettyprint_status_register_bp2_bpl; + case SPI_PRETTYPRINT_STATUS_REGISTER_BP2_EP_SRWD: return &spi_prettyprint_status_register_bp2_ep_srwd; + case SPI_PRETTYPRINT_STATUS_REGISTER_BP2_SRWD: return &spi_prettyprint_status_register_bp2_srwd; + case SPI_PRETTYPRINT_STATUS_REGISTER_BP2_TB_BPL: return &spi_prettyprint_status_register_bp2_tb_bpl; + case SPI_PRETTYPRINT_STATUS_REGISTER_SRWD_SEC_TB_BP2_WELWIP: return &spi_prettyprint_status_register_srwd_sec_tb_bp2_welwip; + case SPI_PRETTYPRINT_STATUS_REGISTER_BP3_SRWD: return &spi_prettyprint_status_register_bp3_srwd; + case SPI_PRETTYPRINT_STATUS_REGISTER_BP4_SRWD: return &spi_prettyprint_status_register_bp4_srwd; + case SPI_PRETTYPRINT_STATUS_REGISTER_DEFAULT_WELWIP: return &spi_prettyprint_status_register_default_welwip; + case SPI_PRETTYPRINT_STATUS_REGISTER_EN25S_WP: return &spi_prettyprint_status_register_en25s_wp; + case SPI_PRETTYPRINT_STATUS_REGISTER_N25Q: return &spi_prettyprint_status_register_n25q; + case SPI_PRETTYPRINT_STATUS_REGISTER_PLAIN: return &spi_prettyprint_status_register_plain; + case SPI_PRETTYPRINT_STATUS_REGISTER_SST25: return &spi_prettyprint_status_register_sst25; + case SPI_PRETTYPRINT_STATUS_REGISTER_SST25VF016: return &spi_prettyprint_status_register_sst25vf016; + case SPI_PRETTYPRINT_STATUS_REGISTER_SST25VF040B: return &spi_prettyprint_status_register_sst25vf040b; + /* default: non-total function, 0 indicates no unlock function set. + * We explicitly do not want a default catch-all case in the switch + * to ensure unhandled enum's are compiler warnings. + */ + case NO_PRINTLOCK_FUNC: return NULL; + }; + + return NULL; +} diff --git a/spi95.c b/spi95.c index 976f99a11..d1f0ba130 100644 --- a/spi95.c +++ b/spi95.c @@ -46,7 +46,7 @@ int probe_spi_st95(struct flashctx *flash) id1 = readarr[0]; // manufacture id id2 = (readarr[1] << 8) | readarr[2]; // SPI family code + model id - msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2); + msg_cdbg("%s: id1 0x%02"PRIx32", id2 0x%02"PRIx32"\n", __func__, id1, id2); if (id1 == flash->chip->manufacture_id && id2 == flash->chip->model_id) return 1; diff --git a/sst28sf040.c b/sst28sf040.c index 9a08d6b61..9080684b5 100644 --- a/sst28sf040.c +++ b/sst28sf040.c @@ -105,7 +105,7 @@ static int erase_28sf040(struct flashctx *flash) chip_writeb(flash, CHIP_ERASE, bios); chip_writeb(flash, CHIP_ERASE, bios); - programmer_delay(10); + programmer_delay(flash, 10); toggle_ready_jedec(flash, bios); /* FIXME: Check the status register for errors. */ diff --git a/stlinkv3_spi.c b/stlinkv3_spi.c index 9ae3df5fa..29aa8d3cf 100644 --- a/stlinkv3_spi.c +++ b/stlinkv3_spi.c @@ -115,7 +115,7 @@ enum spi_nss_level { #define USB_TIMEOUT_IN_MS 5000 static const struct dev_entry devs_stlinkv3_spi[] = { - {0x0483, 0x374E, NT, "STMicroelectronics", "STLINK-V3E"}, + {0x0483, 0x374E, BAD, "STMicroelectronics", "STLINK-V3E"}, {0x0483, 0x374F, OK, "STMicroelectronics", "STLINK-V3S"}, {0x0483, 0x3753, OK, "STMicroelectronics", "STLINK-V3 dual VCP"}, {0x0483, 0x3754, NT, "STMicroelectronics", "STLINK-V3 no MSD"}, @@ -466,12 +466,9 @@ static const struct spi_master spi_programmer_stlinkv3 = { .max_data_read = UINT16_MAX, .max_data_write = UINT16_MAX, .command = stlinkv3_spi_transmit, - .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = stlinkv3_spi_shutdown, - .probe_opcode = default_spi_probe_opcode, }; static int stlinkv3_spi_init(const struct programmer_cfg *cfg) @@ -482,7 +479,8 @@ static int stlinkv3_spi_init(const struct programmer_cfg *cfg) int ret = 1; int devIndex = 0; struct libusb_context *usb_ctx; - libusb_device_handle *stlinkv3_handle; + /* Initialize stlinkv3_handle to NULL for suppressing scan-build false positive core.uninitialized.Branch */ + libusb_device_handle *stlinkv3_handle = NULL; struct stlinkv3_spi_data *stlinkv3_data; if (libusb_init(&usb_ctx)) { @@ -500,8 +498,14 @@ static int stlinkv3_spi_init(const struct programmer_cfg *cfg) devs_stlinkv3_spi[devIndex].vendor_id, devs_stlinkv3_spi[devIndex].device_id, param_str); - if (stlinkv3_handle) + if (stlinkv3_handle) { + if (devs_stlinkv3_spi[devIndex].status == BAD) { + msg_perr("The STLINK-V3 Mini/MiniE does not support the bridge interface\n"); + free(param_str); + goto init_err_exit; + } break; + } devIndex++; } diff --git a/stm50.c b/stm50.c index 37e560c05..d495e0954 100644 --- a/stm50.c +++ b/stm50.c @@ -34,7 +34,7 @@ static int stm50_erase_sector(struct flashctx *flash, unsigned int addr) // now start it chip_writeb(flash, 0x32, bios); chip_writeb(flash, 0xd0, bios); - programmer_delay(10); + programmer_delay(flash, 10); uint8_t status = wait_82802ab(flash); print_status_82802ab(status); diff --git a/subprojects/cmocka.wrap b/subprojects/cmocka.wrap index 21e84f996..4d1cf2729 100644 --- a/subprojects/cmocka.wrap +++ b/subprojects/cmocka.wrap @@ -5,6 +5,4 @@ source_url = https://cmocka.org/files/1.1/cmocka-1.1.5.tar.xz source_filename = cmocka-1.1.5.tar.xz source_hash = f0ccd8242d55e2fd74b16ba518359151f6f8383ff8aef4976e48393f77bba8b6 -patch_url = https://wrapdb.mesonbuild.com/v1/projects/cmocka/1.1.5/3/get_zip -patch_filename = cmocka-1.1.5-3-wrap.zip -patch_hash = 81ce48613680d3c3a0b396ac570c852b290adcd18202fb16aaf703a9493f4348 +patch_directory = cmocka-1.1.5 diff --git a/subprojects/packagefiles/cmocka-1.1.5/LICENSE.build b/subprojects/packagefiles/cmocka-1.1.5/LICENSE.build new file mode 100644 index 000000000..ec288041f --- /dev/null +++ b/subprojects/packagefiles/cmocka-1.1.5/LICENSE.build @@ -0,0 +1,19 @@ +Copyright (c) 2018 The Meson development team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/subprojects/packagefiles/cmocka-1.1.5/meson.build b/subprojects/packagefiles/cmocka-1.1.5/meson.build new file mode 100644 index 000000000..16245d1cb --- /dev/null +++ b/subprojects/packagefiles/cmocka-1.1.5/meson.build @@ -0,0 +1,213 @@ +# Copyright © 2018 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +project( + 'cmocka', + ['c'], + version : '1.1.5', + license : 'APLv2', + meson_version : '>= 0.48.0', + default_options : ['c_std=c99', 'buildtype=debugoptimized'], +) + +lib_version = '0.5.0' + +# TODO: pkg-config +# TODO: cmake-config + +inc_include = include_directories('include') + +##################### +# Config Generation # +##################### + +cc_dict = { + 'compiler': meson.get_compiler('c'), + 'machine': host_machine, + 'config_h_subdir': 'private', + 'native': false +} + +cc_native_dict = { + 'compiler': meson.get_compiler('c', native: true), + 'machine': build_machine, + 'config_h_subdir': 'private_native', + 'native': true +} + +configurations = [cc_dict, cc_native_dict] + +foreach entry : configurations + compiler = entry.get('compiler') + is_native = entry.get('native') + machine = entry.get('machine') + + config = configuration_data() + + if ['gcc', 'clang'].contains(compiler.get_id()) + add_project_arguments( + # I've explicitly skipped the duplicated -W versions when they also test + # for the -Werror version + compiler.get_supported_arguments( + '-Wshadow', + '-Wmissing-prototypes', + '-Wcast-align', + '-Werror=address', + '-Werror=strict-prototypes', + '-Werror=write-strings', + '-Werror=implicit-function-declaration', + '-Werror=pointer-arith', + '-Werror=declaration-after-statement', + '-Werror=return-type', + '-Werror=uninitialized', + '-Wimplicit-fallthrough', + '-Werror=strict-overflow', + '-Wstrict-overflow=2', + '-Wno-format-zero-length', + '-Wformat', + '-Werror=format-security', + '-Wno-gnu-zero-variadic-macro-arguments', + '-fno-common', + ), + language : ['c'], + native: is_native + ) + # We can't test the build type, so we can' add -D_FORTIFY_SOURCE=2 here + if machine.system() == 'darwin' + if compiler.has_argument('-Wno-deprecated-declarations') + add_project_arguments('-Wno-deprecated-declarations', language : ['c'], native: is_native) + endif + endif + elif compiler.get_id() == 'msvc' + add_project_arguments( + '/D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1', + '/D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1', + '/D_CRT_NONSTDC_NO_WARNINGS=1', + '/D_CRT_SECURE_NO_WARNINGS=1', + language : ['c'], + native: is_native + ) + endif + + # TODO: solaris extensions + + foreach h : ['assert.h', 'inttypes.h', 'io.h', 'malloc.h', 'memory.h', + 'setjmp.h', 'signal.h', 'stdarg.h', 'stddef.h', 'stdint.h', + 'stdio.h', 'stdlib.h', 'string.h', 'strings.h', 'sys/stat.h', + 'sys/types.h', 'time.h', 'unistd.h'] + if compiler.check_header(h) + config.set('HAVE_@0@'.format(h.underscorify().to_upper()), 1) + endif + endforeach + + if config.get('HAVE_TIME_H', 0) == 1 + if compiler.has_member('struct timespec', 'tv_sec', prefix : '#include ') + config.set('HAVE_STRUCT_TIMESPEC', 1) + endif + endif + + foreach f : ['calloc', 'exit', 'fprintf', 'free', 'longjmp', 'siglongjmp', + 'malloc', 'memcpy', 'memset', 'printf', 'setjmp', 'signal', + 'strsignal', 'strcmp', 'clock_gettime'] + if compiler.has_function(f) + config.set('HAVE_@0@'.format(f.underscorify().to_upper()), 1) + endif + endforeach + + if machine.system() == 'windows' + foreach f : ['_vsnprintf_s', '_vsnprtinf', '_snprintf_s', '_snprintf'] + if compiler.has_function(f) + config.set('HAVE_@0@'.format(f.underscorify().to_upper()), 1) + endif + endforeach + foreach f : ['snprintf', 'vsnprintf'] + if compiler.has_header_symbol('stdio.h', f) + config.set('HAVE_@0@'.format(f.underscorify().to_upper()), 1) + endif + endforeach +else + foreach f : ['snprintf', 'vsnprintf'] + if compiler.has_function(f) + config.set('HAVE_@0@'.format(f.underscorify().to_upper()), 1) + endif + endforeach +endif + + if machine.system() == 'windows' + if compiler.compiles(''' + __declspec(thread) int tls; + + int main(void) { + return 0; + }''', + name : 'Thread Local Storage') + config.set('HAVE_MSVC_THREAD_LOCAL_STORAGE', 1) + endif + else + if compiler.compiles(''' + __thread int tls; + + int main(void) { + return 0; + }''', + name : 'Thread Local Storage') + config.set('HAVE_GCC_THREAD_LOCAL_STORAGE', 1) + endif + endif + + if (config.get('HAVE_TIME_H', 0) == 1 and + config.get('HAVE_STRUCT_TIMESPEC', 0) == 1 and + config.get('HAVE_CLOCK_GETTIME', 0) == 1) + if compiler.has_header_symbol('time.h', 'CLOCK_REALTIME') + config.set('HAVE_CLOCK_REALTIME', 1) + endif + endif + + config.set('WORDS_SIZEOF_VOID_P', compiler.sizeof('void *')) + if machine.endian() == 'big' + config.set('WORDS_BIGENDIAN', 1) + endif + + # Execute subdir to create config.h for this pass + # This requires the use of the variable named "config" for configuration_data(), + # as this variable is used in each configuration header subdirectory. + subdir(entry.get('config_h_subdir')) + +endforeach + +########################### +# Subdirectory Processing # +########################### + +subdir('src') + +###################### +# Dependency Targets # +###################### + +# TODO: doc, include, tests, example +# Since we're using this as a wrap, and it's a unit test framework we're not +# going to install it. + +cmocka_dep = declare_dependency( + link_with : libcmocka, + include_directories : inc_include, + version : meson.project_version(), +) + +cmocka_native_dep = declare_dependency( + link_with : libcmocka_native, + include_directories : inc_include, + version : meson.project_version(), +) diff --git a/subprojects/packagefiles/cmocka-1.1.5/private/meson.build b/subprojects/packagefiles/cmocka-1.1.5/private/meson.build new file mode 100644 index 000000000..ca5bf09dc --- /dev/null +++ b/subprojects/packagefiles/cmocka-1.1.5/private/meson.build @@ -0,0 +1,23 @@ +# Copyright © 2018 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +## This file sets the config.h header for standard builds (e.g., not native: true) + +config_h = configure_file( + configuration : config, + output : 'config.h', +) + +inc_private = include_directories('.') diff --git a/subprojects/packagefiles/cmocka-1.1.5/private_native/meson.build b/subprojects/packagefiles/cmocka-1.1.5/private_native/meson.build new file mode 100644 index 000000000..81b923cf9 --- /dev/null +++ b/subprojects/packagefiles/cmocka-1.1.5/private_native/meson.build @@ -0,0 +1,23 @@ +# Copyright © 2018 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +## This file sets the config.h header for standard builds (e.g., not native: true) + +config_h_native = configure_file( + configuration : config, + output : 'config.h', +) + +inc_private_native = include_directories('.') diff --git a/subprojects/packagefiles/cmocka-1.1.5/src/meson.build b/subprojects/packagefiles/cmocka-1.1.5/src/meson.build new file mode 100644 index 000000000..e46904907 --- /dev/null +++ b/subprojects/packagefiles/cmocka-1.1.5/src/meson.build @@ -0,0 +1,46 @@ +# Copyright © 2018 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# cmocka rather annoyingly uses different standards for different platforms. +_overrides = [] +if host_machine.system() != 'windows' + _overrides += 'c_std=gnu99' +endif + +libcmocka = library( + 'cmocka', + ['cmocka.c'], + c_args : '-DHAVE_CONFIG_H=1', + include_directories : [inc_include, inc_private], + vs_module_defs : 'cmocka.def', + soversion : host_machine.system() != 'windows' ? lib_version.split('.')[0] : '', + version : lib_version, + install : false, + override_options : _overrides, + build_by_default: false, +) + +libcmocka_native = library( + 'cmocka_native', + ['cmocka.c'], + c_args : '-DHAVE_CONFIG_H=1', + include_directories : [inc_include, inc_private_native], + vs_module_defs : 'cmocka.def', + soversion : build_machine.system() != 'windows' ? lib_version.split('.')[0] : '', + version : lib_version, + install : false, # Cannot install native targets in cross builds + override_options : _overrides, + native: true, + build_by_default: false, +) diff --git a/superio.c b/superio.c new file mode 100644 index 000000000..3121578d9 --- /dev/null +++ b/superio.c @@ -0,0 +1,42 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2009 Carl-Daniel Hailfinger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "programmer.h" + +int superio_count = 0; +#define SUPERIO_MAX_COUNT 3 + +struct superio superios[SUPERIO_MAX_COUNT]; + +int register_superio(struct superio s) +{ + if (superio_count == SUPERIO_MAX_COUNT) + return 1; + superios[superio_count++] = s; + return 0; +} + +void probe_superio(void) +{ + probe_superio_winbond(); + /* ITE probe causes SMSC LPC47N217 to power off the serial UART. + * Always probe for SMSC first, and if a SMSC Super I/O is detected + * at a given I/O port, do _not_ probe that port with the ITE probe. + * This means SMSC probing must be done before ITE probing. + */ + //probe_superio_smsc(); + probe_superio_ite(); +} diff --git a/test_build.sh b/test_build.sh index 717df00c0..8c041f0c4 100755 --- a/test_build.sh +++ b/test_build.sh @@ -5,20 +5,13 @@ set -e is_scan_build_env=0 -make_programmer_opts="INTERNAL INTERNAL_X86 SERPROG RAYER_SPI RAIDEN_DEBUG_SPI PONY_SPI NIC3COM \ - GFXNVIDIA SATASII ATAHPT ATAVIA ATAPROMISE FT2232_SPI USBBLASTER_SPI MSTARDDC_SPI \ - PICKIT2_SPI STLINKV3_SPI PARADE_LSPCON MEDIATEK_I2C_SPI REALTEK_MST_I2C_SPI DUMMY \ - DRKAISER NICREALTEK NICNATSEMI NICINTEL NICINTEL_SPI NICINTEL_EEPROM OGP_SPI \ - BUSPIRATE_SPI DEDIPROG DEVELOPERBOX_SPI SATAMV LINUX_MTD LINUX_SPI IT8212 \ - CH341A_SPI DIGILENT_SPI JLINK_SPI" - -meson_programmer_opts="all auto group_ftdi group_i2c group_jlink group_pci group_serial group_usb \ - atahpt atapromise atavia buspirate_spi ch341a_spi dediprog developerbox_spi \ - digilent_spi drkaiser dummy ft2232_spi gfxnvidia internal it8212 \ - jlink_spi linux_mtd linux_spi parade_lspcon mediatek_i2c_spi mstarddc_spi \ - nic3com nicintel nicintel_eeprom nicintel_spi nicnatsemi nicrealtek \ - ogp_spi pickit2_spi pony_spi raiden_debug_spi rayer_spi realtek_mst_i2c_spi \ - satamv satasii serprog stlinkv3_spi usbblaster_spi" +meson_programmer_opts="all auto group_ftdi group_i2c group_jlink group_pci group_serial group_usb \ + atahpt atapromise atavia buspirate_spi ch341a_spi ch347_spi dediprog \ + developerbox_spi digilent_spi dirtyjtag_spi drkaiser dummy ft2232_spi \ + gfxnvidia internal it8212 jlink_spi linux_mtd linux_spi parade_lspcon \ + mediatek_i2c_spi mstarddc_spi nic3com nicintel nicintel_eeprom nicintel_spi \ + nicnatsemi nicrealtek ogp_spi pickit2_spi pony_spi raiden_debug_spi rayer_spi \ + realtek_mst_i2c_spi satamv satasii serprog stlinkv3_spi usbblaster_spi asm106x" if [ "$(basename "${CC}")" = "ccc-analyzer" ] || [ -n "${COVERITY_OUTPUT}" ]; then @@ -26,27 +19,14 @@ if [ "$(basename "${CC}")" = "ccc-analyzer" ] || [ -n "${COVERITY_OUTPUT}" ]; th fi -build_make () { - make clean - make -j $(nproc) CONFIG_EVERYTHING=yes - - # In case of clang analyzer we don't want to run it on - # each programmer individually. Thus, just return here. - if [ ${is_scan_build_env} -eq 1 ]; then - return - fi - - for option in ${make_programmer_opts}; do - echo "Building ${option}" - make clean - make -j $(nproc) CONFIG_NOTHING=yes CONFIG_${option}=yes - done +run_linter() { + ./util/lint/lint-extended-020-signed-off-by } build_meson () { build_dir=out - meson_opts="-Dtests=enabled" + meson_opts="-Dtests=enabled -Dman-pages=enabled -Ddocumentation=enabled" ninja_opts="-j $(nproc)" rm -rf ${build_dir} @@ -60,12 +40,13 @@ build_meson () { return fi - meson ${programmer_dir} ${meson_opts} -Dprogrammer=${programmer} + meson setup ${programmer_dir} ${meson_opts} -Dprogrammer=${programmer} ninja ${ninja_opts} -C ${programmer_dir} ninja ${ninja_opts} -C ${programmer_dir} test done } -build_make +run_linter + build_meson diff --git a/tests/ch341a_spi.c b/tests/ch341a_spi.c new file mode 100644 index 000000000..50b3d11db --- /dev/null +++ b/tests/ch341a_spi.c @@ -0,0 +1,138 @@ +/* + * This file is part of the flashrom project. + * + * Copyright 2022 Alexander Goncharov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +#include "lifecycle.h" + +#if CONFIG_CH341A_SPI == 1 + +/* Same macro as in ch341a_spi.c programmer. */ +#define WRITE_EP 0x02 +#define READ_EP 0x82 + +struct ch341a_spi_io_state { + struct libusb_transfer *transfer_out; + /* + * Since the test transfers a data that fits in one CH341 packet, we + * don't need an array of these transfers (as is done in the driver code). + */ + struct libusb_transfer *transfer_in; +}; + +static struct libusb_transfer *ch341a_libusb_alloc_transfer(void *state, int iso_packets) +{ + return calloc(1, sizeof(struct libusb_transfer)); +} + +/* + * The libusb code stores submitted transfers in their own context. But this + * function doesn't require a context pointer because libusb stores context + * pointers in libusb_transfer instances. Since our ch341 driver is using + * the default context, we store the transfer in our own. + */ +static int ch341a_libusb_submit_transfer(void *state, struct libusb_transfer *transfer) +{ + struct ch341a_spi_io_state *io_state = state; + + assert_true(transfer->endpoint == WRITE_EP || transfer->endpoint == READ_EP); + + if (transfer->endpoint == WRITE_EP) { + assert_null(io_state->transfer_out); + io_state->transfer_out = transfer; + } else if (transfer->endpoint == READ_EP) { + assert_null(io_state->transfer_in); + io_state->transfer_in = transfer; + } + + return 0; +} + +static void ch341a_libusb_free_transfer(void *state, struct libusb_transfer *transfer) +{ + free(transfer); +} + +/* + * Handle submitted transfers by pretending that a transfer is completed and + * invoking its callback (that is the flashrom code). + */ +static int ch341a_libusb_handle_events_timeout(void *state, libusb_context *ctx, struct timeval *tv) +{ + struct ch341a_spi_io_state *io_state = state; + + if (io_state->transfer_out) { + io_state->transfer_out->status = LIBUSB_TRANSFER_COMPLETED; + io_state->transfer_out->actual_length = io_state->transfer_out->length; + io_state->transfer_out->callback(io_state->transfer_out); + io_state->transfer_out = NULL; + } + + if (io_state->transfer_in) { + io_state->transfer_in->buffer[1] = reverse_byte(0xEF); /* WINBOND_NEX_ID */ + io_state->transfer_in->buffer[2] = reverse_byte(0x40); /* WINBOND_NEX_W25Q128_V left byte */ + io_state->transfer_in->buffer[3] = reverse_byte(0x18); /* WINBOND_NEX_W25Q128_V right byte */ + + io_state->transfer_in->status = LIBUSB_TRANSFER_COMPLETED; + io_state->transfer_in->actual_length = io_state->transfer_in->length; + io_state->transfer_in->callback(io_state->transfer_in); + io_state->transfer_in = NULL; + } + + return 0; +} + +void ch341a_spi_basic_lifecycle_test_success(void **state) +{ + struct ch341a_spi_io_state ch341a_spi_io_state = { 0 }; + struct io_mock_fallback_open_state ch341a_spi_fallback_open_state = { + .noc = 0, + .paths = { NULL }, + }; + const struct io_mock ch341a_spi_io = { + .state = &ch341a_spi_io_state, + .libusb_alloc_transfer = &ch341a_libusb_alloc_transfer, + .libusb_submit_transfer = &ch341a_libusb_submit_transfer, + .libusb_free_transfer = &ch341a_libusb_free_transfer, + .libusb_handle_events_timeout = &ch341a_libusb_handle_events_timeout, + .fallback_open_state = &ch341a_spi_fallback_open_state, + }; + + run_basic_lifecycle(state, &ch341a_spi_io, &programmer_ch341a_spi, ""); +} + +void ch341a_spi_probe_lifecycle_test_success(void **state) +{ + struct ch341a_spi_io_state ch341a_spi_io_state = { 0 }; + struct io_mock_fallback_open_state ch341a_spi_fallback_open_state = { + .noc = 0, + .paths = { NULL }, + }; + const struct io_mock ch341a_spi_io = { + .state = &ch341a_spi_io_state, + .libusb_alloc_transfer = &ch341a_libusb_alloc_transfer, + .libusb_submit_transfer = &ch341a_libusb_submit_transfer, + .libusb_free_transfer = &ch341a_libusb_free_transfer, + .libusb_handle_events_timeout = &ch341a_libusb_handle_events_timeout, + .fallback_open_state = &ch341a_spi_fallback_open_state, + }; + + run_probe_lifecycle(state, &ch341a_spi_io, &programmer_ch341a_spi, "", "W25Q128.V"); +} + +#else + SKIP_TEST(ch341a_spi_basic_lifecycle_test_success) + SKIP_TEST(ch341a_spi_probe_lifecycle_test_success) +#endif /* CONFIG_CH341A_SPI */ diff --git a/tests/chip.c b/tests/chip.c index 6f0317264..604d79e4d 100644 --- a/tests/chip.c +++ b/tests/chip.c @@ -20,13 +20,14 @@ * Example of test: erase_chip_test_success. * * 2) Mock chip operations backed by `dummyflasher` emulation. - * Dummyflasher controls chip state and emulates read/write/unlock/erase. + * Dummyflasher controls chip state and emulates read/write/erase. * `g_chip_state` is NOT used for this type of tests. * Example of test: erase_chip_with_dummyflasher_test_success. */ #include #include +#include #include #include "tests.h" @@ -37,23 +38,17 @@ #include "programmer.h" #define MOCK_CHIP_SIZE (8*MiB) -#define MOCK_CHIP_CONTENT 0xff +#define MOCK_CHIP_CONTENT 0xCC /* 0x00 is a zeroed heap and 0xFF is an erased chip. */ static struct { - unsigned int unlock_calls; /* how many times unlock function was called */ uint8_t buf[MOCK_CHIP_SIZE]; /* buffer of total size of chip, to emulate a chip */ } g_chip_state = { - .unlock_calls = 0, .buf = { 0 }, }; static int read_chip(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len) { printf("Read chip called with start=0x%x, len=0x%x\n", start, len); - if (!g_chip_state.unlock_calls) { - printf("Error while reading chip: unlock was not called.\n"); - return 1; - } assert_in_range(start + len, 0, MOCK_CHIP_SIZE); @@ -64,10 +59,6 @@ static int read_chip(struct flashctx *flash, uint8_t *buf, unsigned int start, u static int write_chip(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) { printf("Write chip called with start=0x%x, len=0x%x\n", start, len); - if (!g_chip_state.unlock_calls) { - printf("Error while writing chip: unlock was not called.\n"); - return 1; - } assert_in_range(start + len, 0, MOCK_CHIP_SIZE); @@ -75,26 +66,9 @@ static int write_chip(struct flashctx *flash, const uint8_t *buf, unsigned int s return 0; } -static int unlock_chip(struct flashctx *flash) -{ - printf("Unlock chip called\n"); - g_chip_state.unlock_calls++; - - if (g_chip_state.unlock_calls > 1) { - printf("Error: Unlock called twice\n"); - return -1; - } - - return 0; -} - static int block_erase_chip(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen) { printf("Block erase called with blockaddr=0x%x, blocklen=0x%x\n", blockaddr, blocklen); - if (!g_chip_state.unlock_calls) { - printf("Error while erasing chip: unlock was not called.\n"); - return 1; - } assert_in_range(blockaddr + blocklen, 0, MOCK_CHIP_SIZE); @@ -109,7 +83,6 @@ static void setup_chip(struct flashrom_flashctx *flashctx, struct flashrom_layou flashctx->chip = chip; - g_chip_state.unlock_calls = 0; memset(g_chip_state.buf, MOCK_CHIP_CONTENT, sizeof(g_chip_state.buf)); printf("Creating layout with one included region... "); @@ -150,43 +123,60 @@ static const struct flashchip chip_8MiB = { .vendor = "aklm", .total_size = MOCK_CHIP_SIZE / KiB, .tested = TEST_OK_PREW, - .read = read_chip, - .write = write_chip, - .unlock = unlock_chip, + .read = TEST_READ_INJECTOR, + .write = TEST_WRITE_INJECTOR, .block_erasers = {{ /* All blocks within total size of the chip. */ .eraseblocks = { {2 * MiB, 4} }, - .block_erase = block_erase_chip, + .block_erase = TEST_ERASE_INJECTOR_1, }}, }; +/* Chip expected to be processed with dummyflasher, so using real op functions. */ +static const struct flashchip chip_no_erase = { + .vendor = "aklm&dummyflasher", + .total_size = 16 * 1024, + .tested = TEST_OK_PREW, + .read = SPI_CHIP_READ, + .write = SPI_CHIP_WRITE256, + .page_size = 256, + .feature_bits = FEATURE_NO_ERASE | FEATURE_ERASED_ZERO, + .block_erasers = + { + { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + /* Special erase fn for chips without erase capability. */ + .block_erase = SPI_BLOCK_ERASE_EMULATION, + } + }, +}; + /* Setup the struct for W25Q128.V, all values come from flashchips.c */ static const struct flashchip chip_W25Q128_V = { .vendor = "aklm&dummyflasher", .total_size = 16 * 1024, .tested = TEST_OK_PREW, - .read = spi_chip_read, - .write = spi_chip_write_256, - .unlock = spi_disable_blockprotect, + .read = SPI_CHIP_READ, + .write = SPI_CHIP_WRITE256, .page_size = 256, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, }; @@ -203,6 +193,9 @@ void erase_chip_test_success(void **state) .fallback_open_state = &data, }; + g_test_write_injector = write_chip; + g_test_read_injector = read_chip; + g_test_erase_injector[0] = block_erase_chip; struct flashrom_flashctx flashctx = { 0 }; struct flashrom_layout *layout; struct flashchip mock_chip = chip_8MiB; @@ -236,7 +229,7 @@ void erase_chip_with_dummyflasher_test_success(void **state) * Dummyflasher is capable to emulate W25Q128.V, so we ask it to do this. * Nothing to mock, dummy is taking care of this already. */ - char *param_dup = strdup("bus=spi,emulate=W25Q128FV"); + const char *param_dup = "bus=spi,emulate=W25Q128FV"; setup_chip(&flashctx, &layout, &mock_chip, param_dup, &chip_io); @@ -245,8 +238,6 @@ void erase_chip_with_dummyflasher_test_success(void **state) printf("Erase chip operation done.\n"); teardown(&layout); - - free(param_dup); } void read_chip_test_success(void **state) @@ -261,6 +252,9 @@ void read_chip_test_success(void **state) .fallback_open_state = &data, }; + g_test_write_injector = write_chip; + g_test_read_injector = read_chip; + g_test_erase_injector[0] = block_erase_chip; struct flashrom_flashctx flashctx = { 0 }; struct flashrom_layout *layout; struct flashchip mock_chip = chip_8MiB; @@ -271,6 +265,7 @@ void read_chip_test_success(void **state) const char *const filename = "read_chip.test"; unsigned long size = mock_chip.total_size * 1024; unsigned char *buf = calloc(size, sizeof(unsigned char)); + assert_non_null(buf); printf("Read chip operation started.\n"); assert_int_equal(0, flashrom_image_read(&flashctx, buf, size)); @@ -301,13 +296,14 @@ void read_chip_with_dummyflasher_test_success(void **state) * Dummyflasher is capable to emulate W25Q128.V, so we ask it to do this. * Nothing to mock, dummy is taking care of this already. */ - char *param_dup = strdup("bus=spi,emulate=W25Q128FV"); + const char *param_dup = "bus=spi,emulate=W25Q128FV"; setup_chip(&flashctx, &layout, &mock_chip, param_dup, &chip_io); const char *const filename = "read_chip.test"; unsigned long size = mock_chip.total_size * 1024; unsigned char *buf = calloc(size, sizeof(unsigned char)); + assert_non_null(buf); printf("Read chip operation started.\n"); assert_int_equal(0, flashrom_image_read(&flashctx, buf, size)); @@ -316,7 +312,6 @@ void read_chip_with_dummyflasher_test_success(void **state) teardown(&layout); - free(param_dup); free(buf); } @@ -332,6 +327,9 @@ void write_chip_test_success(void **state) .fallback_open_state = &data, }; + g_test_write_injector = write_chip; + g_test_read_injector = read_chip; + g_test_erase_injector[0] = block_erase_chip; struct flashrom_flashctx flashctx = { 0 }; struct flashrom_layout *layout; struct flashchip mock_chip = chip_8MiB; @@ -355,6 +353,7 @@ void write_chip_test_success(void **state) const char *const filename = "-"; unsigned long size = mock_chip.total_size * 1024; uint8_t *const newcontents = malloc(size); + assert_non_null(newcontents); printf("Write chip operation started.\n"); assert_int_equal(0, read_buf_from_file(newcontents, size, filename)); @@ -385,7 +384,7 @@ void write_chip_with_dummyflasher_test_success(void **state) * Dummyflasher is capable to emulate W25Q128.V, so we ask it to do this. * Nothing to mock, dummy is taking care of this already. */ - char *param_dup = strdup("bus=spi,emulate=W25Q128FV"); + const char *param_dup = "bus=spi,emulate=W25Q128FV"; setup_chip(&flashctx, &layout, &mock_chip, param_dup, &chip_io); @@ -393,6 +392,7 @@ void write_chip_with_dummyflasher_test_success(void **state) const char *const filename = "-"; unsigned long size = mock_chip.total_size * 1024; uint8_t *const newcontents = malloc(size); + assert_non_null(newcontents); printf("Write chip operation started.\n"); assert_int_equal(0, read_buf_from_file(newcontents, size, filename)); @@ -401,7 +401,138 @@ void write_chip_with_dummyflasher_test_success(void **state) teardown(&layout); - free(param_dup); + free(newcontents); +} + +void write_chip_feature_no_erase(void **state) +{ + (void) state; /* unused */ + + static struct io_mock_fallback_open_state data = { + .noc = 0, + .paths = { NULL }, + }; + const struct io_mock chip_io = { + .fallback_open_state = &data, + }; + + struct flashrom_flashctx flashctx = { 0 }; + struct flashrom_layout *layout; + + /* + * Tricking the dummyflasher by asking to emulate W25Q128FV but giving to it + * mock chip with FEATURE_NO_ERASE. + * As long as chip size is the same, this is fine. + */ + struct flashchip mock_chip = chip_no_erase; + const char *param_dup = "bus=spi,emulate=W25Q128FV"; + + setup_chip(&flashctx, &layout, &mock_chip, param_dup, &chip_io); + + /* See comment in write_chip_test_success */ + const char *const filename = "-"; + unsigned long size = mock_chip.total_size * 1024; + uint8_t *const newcontents = malloc(size); + assert_non_null(newcontents); + + printf("Write chip operation started.\n"); + assert_int_equal(0, read_buf_from_file(newcontents, size, filename)); + assert_int_equal(0, flashrom_image_write(&flashctx, newcontents, size, NULL)); + assert_int_equal(0, flashrom_image_verify(&flashctx, newcontents, size)); + printf("Write chip operation done.\n"); + + teardown(&layout); + + free(newcontents); +} + +void write_nonaligned_region_with_dummyflasher_test_success(void **state) +{ + (void) state; /* unused */ + + static struct io_mock_fallback_open_state data = { + .noc = 0, + .paths = { NULL }, + }; + const struct io_mock chip_io = { + .fallback_open_state = &data, + }; + + struct flashrom_flashctx flashctx = { 0 }; + struct flashrom_layout *layout; + struct flashchip mock_chip = chip_W25Q128_V; + const uint32_t mock_chip_size = mock_chip.total_size * KiB; + /* + * Dummyflasher is capable to emulate W25Q128.V, so we ask it to do this. + * Nothing to mock, dummy is taking care of this already. + */ + const char *param_dup = "bus=spi,emulate=W25Q128FV"; + + /* FIXME: MOCK_CHIP_CONTENT is buggy within setup_chip, it should also + * not be either 0x00 or 0xFF as those are specific values related to + * either a erased chip or zero'ed heap thus ambigous. + */ +#define MOCK_CHIP_SUBREGION_CONTENTS 0xCC + /** + * Step 0 - Prepare newcontents as contiguous sample data bytes as follows: + * {MOCK_CHIP_SUBREGION_CONTENTS, [..]}. + */ + uint8_t *newcontents = calloc(1, mock_chip_size); + assert_non_null(newcontents); + memset(newcontents, MOCK_CHIP_SUBREGION_CONTENTS, mock_chip_size); + + setup_chip(&flashctx, &layout, &mock_chip, param_dup, &chip_io); + /* Expect to verify only the non-aligned write operation within the region. */ + flashrom_flag_set(&flashctx, FLASHROM_FLAG_VERIFY_AFTER_WRITE, true); + flashrom_flag_set(&flashctx, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, false); + + /** + * Prepare mock chip content and release setup_chip() layout for our + * custom ones. + */ + assert_int_equal(0, flashrom_image_write(&flashctx, newcontents, mock_chip_size, NULL)); + flashrom_layout_release(layout); + + /** + * Create region smaller than erase granularity of chip. + */ + printf("Creating custom region layout... "); + assert_int_equal(0, flashrom_layout_new(&layout)); + printf("Adding and including region0... "); + assert_int_equal(0, flashrom_layout_add_region(layout, 0, (1 * KiB), "region0")); + assert_int_equal(0, flashrom_layout_include_region(layout, "region0")); + flashrom_layout_set(&flashctx, layout); + printf("Subregion layout configuration done.\n"); + + /** + * Step 1 - Modify newcontents as non-contiguous sample data bytes as follows: + * 0xAA 0xAA {MOCK_CHIP_SUBREGION_CONTENTS}, [..]}. + */ + printf("Subregion chip write op..\n"); + memset(newcontents, 0xAA, 2); + assert_int_equal(0, flashrom_image_write(&flashctx, newcontents, mock_chip_size, NULL)); + printf("Subregion chip write op done.\n"); + + /** + * FIXME: A 'NULL' layout should indicate a default layout however this + * causes a crash for a unknown reason. For now prepare a new default + * layout of the entire chip. flashrom_layout_set(&flashctx, NULL); // use default layout. + */ + flashrom_layout_release(layout); + assert_int_equal(0, flashrom_layout_new(&layout)); + assert_int_equal(0, flashrom_layout_add_region(layout, 0, mock_chip_size - 1, "entire")); + assert_int_equal(0, flashrom_layout_include_region(layout, "entire")); + flashrom_layout_set(&flashctx, layout); + + /** + * Expect a verification pass that the previous content within the region, however + * outside the region write length, is untouched. + */ + printf("Entire chip verify op..\n"); + assert_int_equal(0, flashrom_image_verify(&flashctx, newcontents, mock_chip_size)); + printf("Entire chip verify op done.\n"); + + teardown(&layout); free(newcontents); } @@ -425,10 +556,13 @@ void verify_chip_test_success(void **state) .paths = { NULL }, }; const struct io_mock verify_chip_io = { - .fread = verify_chip_fread, + .iom_fread = verify_chip_fread, .fallback_open_state = &data, }; + g_test_write_injector = write_chip; + g_test_read_injector = read_chip; + g_test_erase_injector[0] = block_erase_chip; struct flashrom_flashctx flashctx = { 0 }; struct flashrom_layout *layout; struct flashchip mock_chip = chip_8MiB; @@ -440,6 +574,7 @@ void verify_chip_test_success(void **state) const char *const filename = "-"; unsigned long size = mock_chip.total_size * 1024; uint8_t *const newcontents = malloc(size); + assert_non_null(newcontents); printf("Verify chip operation started.\n"); assert_int_equal(0, read_buf_from_file(newcontents, size, filename)); @@ -460,7 +595,7 @@ void verify_chip_with_dummyflasher_test_success(void **state) .paths = { NULL }, }; const struct io_mock verify_chip_io = { - .fread = verify_chip_fread, + .iom_fread = verify_chip_fread, .fallback_open_state = &data, }; @@ -471,7 +606,7 @@ void verify_chip_with_dummyflasher_test_success(void **state) * Dummyflasher is capable to emulate W25Q128.V, so we ask it to do this. * Nothing to mock, dummy is taking care of this already. */ - char *param_dup = strdup("bus=spi,emulate=W25Q128FV"); + const char *param_dup = "bus=spi,emulate=W25Q128FV"; setup_chip(&flashctx, &layout, &mock_chip, param_dup, &verify_chip_io); @@ -479,6 +614,7 @@ void verify_chip_with_dummyflasher_test_success(void **state) const char *const filename = "-"; unsigned long size = mock_chip.total_size * 1024; uint8_t *const newcontents = malloc(size); + assert_non_null(newcontents); /* * Dummyflasher controls chip state and fully emulates reads and writes, @@ -498,6 +634,5 @@ void verify_chip_with_dummyflasher_test_success(void **state) teardown(&layout); - free(param_dup); free(newcontents); } diff --git a/tests/chip_wp.c b/tests/chip_wp.c index 95e6b05ce..4f0162d33 100644 --- a/tests/chip_wp.c +++ b/tests/chip_wp.c @@ -16,6 +16,7 @@ #include #include +#include #include #include "chipdrivers.h" @@ -24,6 +25,12 @@ #include "programmer.h" #include "tests.h" +static int unittest_print_cb(enum flashrom_log_level level, const char *fmt, va_list ap) +{ + if (level > FLASHROM_MSG_INFO) return 0; + return vfprintf(stderr, fmt, ap); +} + /* * Tests in this file do not use any mocking, because using write-protect * emulation in dummyflasher programmer is sufficient @@ -47,6 +54,8 @@ static void setup_chip(struct flashrom_flashctx *flash, struct flashrom_layout * flashrom_layout_set(flash, *layout); } + flashrom_set_log_callback((flashrom_log_callback *)&unittest_print_cb); + assert_int_equal(0, programmer_init(&programmer_dummy, programmer_param)); /* Assignment below normally happens while probing, but this test is not probing. */ flash->mst = ®istered_masters[0]; @@ -63,28 +72,29 @@ static void teardown(struct flashrom_layout **layout) static const struct flashchip chip_W25Q128_V = { .vendor = "aklm&dummyflasher", .total_size = 16 * 1024, + .page_size = 1024, .tested = TEST_OK_PREW, - .read = spi_chip_read, - .write = spi_chip_write_256, - .unlock = spi_disable_blockprotect, + .read = SPI_CHIP_READ, + .write = SPI_CHIP_WRITE256, + .unlock = SPI_DISABLE_BLOCKPROTECT, .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2 | FEATURE_WRSR2 | FEATURE_WRSR3, .block_erasers = { { .eraseblocks = { {4 * 1024, 4096} }, - .block_erase = spi_block_erase_20, + .block_erase = SPI_BLOCK_ERASE_20, }, { .eraseblocks = { {32 * 1024, 512} }, - .block_erase = spi_block_erase_52, + .block_erase = SPI_BLOCK_ERASE_52, }, { .eraseblocks = { {64 * 1024, 256} }, - .block_erase = spi_block_erase_d8, + .block_erase = SPI_BLOCK_ERASE_D8, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_60, + .block_erase = SPI_BLOCK_ERASE_60, }, { .eraseblocks = { {16 * 1024 * 1024, 1} }, - .block_erase = spi_block_erase_c7, + .block_erase = SPI_BLOCK_ERASE_C7, } }, .reg_bits = @@ -97,7 +107,7 @@ static const struct flashchip chip_W25Q128_V = { .cmp = {STATUS2, 6, RW}, .wps = {STATUS3, 2, RW}, }, - .decode_range = decode_range_spi25, + .decode_range = DECODE_RANGE_SPI25, }; /* Trying to set an unsupported WP range fails */ @@ -105,7 +115,7 @@ void invalid_wp_range_dummyflasher_test_success(void **state) { (void) state; /* unused */ - char *param_dup = strdup("bus=spi,emulate=W25Q128FV,hwwp=no"); + const char *param_dup = "bus=spi,emulate=W25Q128FV,hwwp=no"; struct flashrom_flashctx flash = { 0 }; struct flashchip mock_chip = chip_W25Q128_V; @@ -122,7 +132,6 @@ void invalid_wp_range_dummyflasher_test_success(void **state) teardown(NULL); flashrom_wp_cfg_release(wp_cfg); - free(param_dup); } /* Enabling hardware WP with a valid range succeeds */ @@ -130,7 +139,7 @@ void set_wp_range_dummyflasher_test_success(void **state) { (void) state; /* unused */ - char *param_dup = strdup("bus=spi,emulate=W25Q128FV,hwwp=no"); + const char *param_dup = "bus=spi,emulate=W25Q128FV,hwwp=no"; struct flashrom_flashctx flash = { 0 }; struct flashchip mock_chip = chip_W25Q128_V; @@ -157,7 +166,6 @@ void set_wp_range_dummyflasher_test_success(void **state) teardown(NULL); flashrom_wp_cfg_release(wp_cfg); - free(param_dup); } /* Enable hardware WP and verify that it can not be unset */ @@ -165,7 +173,7 @@ void switch_wp_mode_dummyflasher_test_success(void **state) { (void) state; /* unused */ - char *param_dup = strdup("bus=spi,emulate=W25Q128FV,hwwp=yes"); + const char *param_dup = "bus=spi,emulate=W25Q128FV,hwwp=yes"; struct flashrom_flashctx flash = { 0 }; struct flashchip mock_chip = chip_W25Q128_V; @@ -197,7 +205,6 @@ void switch_wp_mode_dummyflasher_test_success(void **state) teardown(NULL); flashrom_wp_cfg_release(wp_cfg); - free(param_dup); } /* WP state is decoded correctly from status registers */ @@ -219,7 +226,7 @@ void wp_init_from_status_dummyflasher_test_success(void **state) * Multiplaying that by base unit gives 16 KiB protected region at the * bottom (start of the chip), which is then complemented. */ - char *param_dup = strdup("bus=spi,emulate=W25Q128FV,spi_status=0x41ec"); + const char *param_dup = "bus=spi,emulate=W25Q128FV,spi_status=0x41ec"; struct flashrom_flashctx flash = { 0 }; struct flashchip mock_chip = chip_W25Q128_V; @@ -242,7 +249,6 @@ void wp_init_from_status_dummyflasher_test_success(void **state) teardown(NULL); flashrom_wp_cfg_release(wp_cfg); - free(param_dup); } /* Enabled WP makes full chip erasure fail */ @@ -255,7 +261,7 @@ void full_chip_erase_with_wp_dummyflasher_test_success(void **state) struct flashchip mock_chip = chip_W25Q128_V; struct flashrom_wp_cfg *wp_cfg; - char *param_dup = strdup("bus=spi,emulate=W25Q128FV,hwwp=yes"); + const char *param_dup = "bus=spi,emulate=W25Q128FV,hwwp=yes"; setup_chip(&flash, &layout, &mock_chip, param_dup); /* Layout regions are created by setup_chip(). */ @@ -268,6 +274,15 @@ void full_chip_erase_with_wp_dummyflasher_test_success(void **state) this stage WP is not enabled and erase completes successfully. */ assert_int_equal(0, flashrom_flash_erase(&flash)); + /* Write non-erased value to entire chip so that erase operations cannot + * be optimized away. */ + unsigned long size = flashrom_flash_getsize(&flash); + uint8_t *const contents = malloc(size); + assert_non_null(contents); + memset(contents, UNERASED_VALUE(&flash), size); + assert_int_equal(0, flashrom_image_write(&flash, contents, size, NULL)); + free(contents); + assert_int_equal(0, flashrom_wp_read_cfg(wp_cfg, &flash)); /* Hardware-protect first 4 KiB. */ @@ -284,7 +299,6 @@ void full_chip_erase_with_wp_dummyflasher_test_success(void **state) teardown(&layout); flashrom_wp_cfg_release(wp_cfg); - free(param_dup); } /* Enabled WP does not block erasing unprotected parts of the chip */ @@ -297,7 +311,7 @@ void partial_chip_erase_with_wp_dummyflasher_test_success(void **state) struct flashchip mock_chip = chip_W25Q128_V; struct flashrom_wp_cfg *wp_cfg; - char *param_dup = strdup("bus=spi,emulate=W25Q128FV,hwwp=yes"); + const char *param_dup = "bus=spi,emulate=W25Q128FV,hwwp=yes"; setup_chip(&flash, &layout, &mock_chip, param_dup); /* Layout region is created by setup_chip(). */ @@ -321,5 +335,69 @@ void partial_chip_erase_with_wp_dummyflasher_test_success(void **state) teardown(&layout); flashrom_wp_cfg_release(wp_cfg); - free(param_dup); +} + +/* Chip register values & masks are calculated correctly by WP */ +void wp_get_register_values_and_masks(void **state) +{ + (void) state; /* unused */ + + /* + * Test with range: start = 0x004000, lengh = 0xffc000 + * + * WP should use these bit values: + * WPS (S17) = 0 (write protect scheme) + * CMP (S14) = 1 (range complement) + * SRP1 (S8) = 0 + * SRP0 (S7) = 1 (`SRP1 == 1 && SRP0 == 1` is permanent mode) + * SEC (S6) = 1 (base unit is a 4 KiB sector) + * TB (S5) = 1 (bottom up range) + * BP2 (S4) = 0 + * BP1 (S3) = 1 + * BP0 (S2) = 1 (bp: BP2-0 == 0b011 == 3) + * + * Register values: + * SR1 = 0b11101100 = 0xec + * SR2 = 0b01000000 = 0x40 + * SR3 = 0b00000000 = 0x00 + * + * Masks for WP bits in registers: + * SR1: 0b11111100 = 0xfc + * SR2: 0b01000000 = 0x41 + * SR3: 0b00000100 = 0x04 + * + * All WP bits are RW so write masks should be the same as the bit masks. + * + */ + struct flashrom_flashctx flash = { 0 }; + struct flashchip mock_chip = chip_W25Q128_V; + struct flashrom_wp_cfg *wp_cfg; + + uint8_t reg_values[MAX_REGISTERS]; + uint8_t bit_masks[MAX_REGISTERS]; + uint8_t write_masks[MAX_REGISTERS]; + + setup_chip(&flash, NULL, &mock_chip, "bus=spi,emulate=W25Q128FV"); + + assert_int_equal(0, flashrom_wp_cfg_new(&wp_cfg)); + flashrom_wp_set_mode(wp_cfg, FLASHROM_WP_MODE_HARDWARE); + flashrom_wp_set_range(wp_cfg, 0x004000, 0xffc000); + + assert_int_equal(0, wp_cfg_to_reg_values(reg_values, bit_masks, write_masks, &flash, wp_cfg)); + + assert_int_equal(0xec, reg_values[STATUS1]); + assert_int_equal(0x40, reg_values[STATUS2]); + assert_int_equal(0x00, reg_values[STATUS3]); + + assert_int_equal(0xfc, bit_masks[STATUS1]); + assert_int_equal(0x41, bit_masks[STATUS2]); + assert_int_equal(0x04, bit_masks[STATUS3]); + + assert_int_equal(0xfc, write_masks[STATUS1]); + assert_int_equal(0x41, write_masks[STATUS2]); + assert_int_equal(0x04, write_masks[STATUS3]); + + teardown(NULL); + + flashrom_wp_cfg_release(wp_cfg); } diff --git a/tests/dummyflasher.c b/tests/dummyflasher.c index 11482177e..9878bef70 100644 --- a/tests/dummyflasher.c +++ b/tests/dummyflasher.c @@ -88,7 +88,7 @@ void dummy_init_success_invalid_param_test_success(void **state) * is successful, due to invalid param at the end of param string. */ run_init_error_path(state, &dummy_io, &programmer_dummy, - "bus=spi,emulate=W25Q128FV,invalid=value", ERROR_FATAL); + "bus=spi,emulate=W25Q128FV,invalid=value", ERROR_FLASHROM_FATAL); } void dummy_init_success_unhandled_param_test_success(void **state) @@ -107,7 +107,7 @@ void dummy_init_success_unhandled_param_test_success(void **state) * Unhandled param `voltage` is not used for dummyflasher. */ run_init_error_path(state, &dummy_io, &programmer_dummy, - "bus=spi,emulate=W25Q128FV,voltage=3.5V", ERROR_FATAL); + "bus=spi,emulate=W25Q128FV,voltage=3.5V", ERROR_FLASHROM_FATAL); } void dummy_null_prog_param_test_success(void **state) @@ -123,6 +123,43 @@ void dummy_null_prog_param_test_success(void **state) run_basic_lifecycle(state, &dummy_io, &programmer_dummy, NULL); } +void dummy_all_buses_test_success(void **state) +{ + struct io_mock_fallback_open_state dummy_fallback_open_state = { + .noc = 0, + .paths = { NULL }, + }; + const struct io_mock dummy_io = { + .fallback_open_state = &dummy_fallback_open_state, + }; + + run_basic_lifecycle(state, &dummy_io, &programmer_dummy, "bus=lpc+fwh"); + run_basic_lifecycle(state, &dummy_io, &programmer_dummy, "bus=spi"); + run_basic_lifecycle(state, &dummy_io, &programmer_dummy, "bus=prog"); + run_basic_lifecycle(state, &dummy_io, &programmer_dummy, "bus=parallel+fwh+prog"); + run_basic_lifecycle(state, &dummy_io, &programmer_dummy, "bus=spi+prog"); + run_basic_lifecycle(state, &dummy_io, &programmer_dummy, "bus=parallel+lpc+spi"); +} + +void dummy_freq_param_init(void **state) +{ + struct io_mock_fallback_open_state dummy_fallback_open_state = { + .noc = 0, + .paths = { NULL }, + }; + const struct io_mock dummy_io = { + .fallback_open_state = &dummy_fallback_open_state, + }; + + run_basic_lifecycle(state, &dummy_io, &programmer_dummy, "bus=spi,freq=12Hz"); + run_basic_lifecycle(state, &dummy_io, &programmer_dummy, "bus=spi,freq=123KHz"); + run_basic_lifecycle(state, &dummy_io, &programmer_dummy, "bus=spi,freq=345MHz"); + run_basic_lifecycle(state, &dummy_io, &programmer_dummy, "bus=spi,freq=8000MHz"); + /* Valid values for freq param are within the range [1Hz, 8000Mhz] */ + run_init_error_path(state, &dummy_io, &programmer_dummy, "bus=spi,freq=0Hz", 0x1); + run_init_error_path(state, &dummy_io, &programmer_dummy, "bus=spi,freq=8001Mhz", 0x1); +} + #else SKIP_TEST(dummy_basic_lifecycle_test_success) SKIP_TEST(dummy_probe_lifecycle_test_success) @@ -131,4 +168,6 @@ void dummy_null_prog_param_test_success(void **state) SKIP_TEST(dummy_init_success_invalid_param_test_success) SKIP_TEST(dummy_init_success_unhandled_param_test_success) SKIP_TEST(dummy_null_prog_param_test_success) + SKIP_TEST(dummy_all_buses_test_success) + SKIP_TEST(dummy_freq_param_init) #endif /* CONFIG_DUMMY */ diff --git a/tests/erase_func_algo.c b/tests/erase_func_algo.c new file mode 100644 index 000000000..d947eb965 --- /dev/null +++ b/tests/erase_func_algo.c @@ -0,0 +1,1522 @@ +/* + * This file is part of the flashrom project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +#include "tests.h" +#include "chipdrivers.h" +#include "flash.h" +#include "io_mock.h" +#include "libflashrom.h" +#include "programmer.h" + +#define LOG_ERASE_FUNC printf("Eraser called with blockaddr=0x%x, blocklen=0x%x, erase_func=%d\n", blockaddr, blocklen, erase_func - TEST_ERASE_INJECTOR_1 + 1) +#define LOG_READ_WRITE_FUNC printf("%s called with start=0x%x, len=0x%x\n", __func__, start, len) + +#define ERASE_VALUE 0xff +#define MOCK_CHIP_SIZE 16 +#define MIN_BUF_SIZE 1024 /* Minimum buffer size flashrom operates for chip operations. */ +#define MIN_REAL_CHIP_SIZE 1024 /* Minimum chip size that can be defined for real chip in flashchips */ + +struct test_region { + const size_t start; + const size_t end; + const char *name; +}; + +struct erase_invoke { + unsigned int blockaddr; + unsigned int blocklen; + enum block_erase_func erase_func; +}; + +struct test_case { + struct flashchip *chip; /* Chip definition. */ + struct test_region regions[MOCK_CHIP_SIZE]; /* Layout regions. */ + uint8_t initial_buf[MOCK_CHIP_SIZE]; /* Initial state of chip memory. */ + uint8_t erased_buf[MOCK_CHIP_SIZE]; /* Expected content after erase. */ + uint8_t written_buf[MOCK_CHIP_SIZE]; /* Expected content after write. */ + uint8_t written_protected_buf[MOCK_CHIP_SIZE]; /* Expected content after write with protected region. */ + struct erase_invoke eraseblocks_expected[MOCK_CHIP_SIZE]; /* Expected order of eraseblocks invocations. */ + unsigned int eraseblocks_expected_ind; /* Expected number of eraseblocks invocations. */ + char erase_test_name[40]; /* Test case display name for testing erase operation. */ + char write_test_name[40]; /* Test case display name for testing write operation. */ +}; + +struct all_state { + uint8_t buf[MIN_REAL_CHIP_SIZE]; /* Buffer emulating the memory of the mock chip. */ + bool was_modified[MIN_REAL_CHIP_SIZE]; /* Which bytes were modified, 0x1 if byte was modified. */ + bool was_verified[MIN_REAL_CHIP_SIZE]; /* Which bytes were verified, 0x1 if byte was verified. */ + struct erase_invoke eraseblocks_actual[MOCK_CHIP_SIZE]; /* The actual order of eraseblocks invocations. */ + unsigned int eraseblocks_actual_ind; /* Actual number of eraseblocks invocations. */ + const struct test_case* current_test_case; /* Currently executed test case. */ +} g_state; + +static int read_chip(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len) +{ + if (start < MOCK_CHIP_SIZE) + LOG_READ_WRITE_FUNC; + + assert_in_range(start + len, 0, MIN_REAL_CHIP_SIZE); + + memcpy(buf, &g_state.buf[start], len); + + /* If these bytes were modified before => current read op is verify op, track it */ + bool bytes_modified = false; + for (unsigned int i = start; i < start + len; i++) + if (g_state.was_modified[i]) { + bytes_modified = true; + break; + } + if (bytes_modified) + memset(&g_state.was_verified[start], true, len); + + return 0; +} + +static int write_chip(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len) +{ + if (start < MOCK_CHIP_SIZE) + LOG_READ_WRITE_FUNC; + + assert_in_range(start + len, 0, MIN_REAL_CHIP_SIZE); + + memcpy(&g_state.buf[start], buf, len); + + /* Track the bytes were written */ + memset(&g_state.was_modified[start], true, len); + /* Clear the records of previous verification, if there were any */ + memset(&g_state.was_verified[start], false, len); + + return 0; +} + +static int block_erase_chip_tagged(struct flashctx *flash, enum block_erase_func erase_func, unsigned int blockaddr, unsigned int blocklen) +{ + if (blockaddr < MOCK_CHIP_SIZE) { + LOG_ERASE_FUNC; + + /* Register eraseblock invocation. */ + g_state.eraseblocks_actual[g_state.eraseblocks_actual_ind] = (struct erase_invoke){ + .blocklen = blocklen, + .blockaddr = blockaddr, + .erase_func = erase_func, + }; + g_state.eraseblocks_actual_ind++; + } + + assert_in_range(blockaddr + blocklen, 0, MIN_REAL_CHIP_SIZE); + + memset(&g_state.buf[blockaddr], ERASE_VALUE, blocklen); + + /* Track the bytes were erased */ + memset(&g_state.was_modified[blockaddr], true, blocklen); + /* Clear the records of previous verification, if there were any */ + memset(&g_state.was_verified[blockaddr], false, blocklen); + + return 0; +} + +static struct flashchip chip_1_2_4_8_16 = { + .vendor = "aklm", + /* + * total_size is supposed to be in Kilobytes and this number is multiplied + * by 1024 everywhere in flashrom code. With this, we can't have the chip of + * size MOCK_CHIP_SIZE anyway, because MOCK_CHIP_SIZE is much smaller than + * 1024. + * + * So setting 1 here as this is the smallest possible value of unsigned int. + * Why aim for the smallest value? Because various places in flashrom code + * are allocating buffers of size total_size * 1024, however in these unit + * tests only MOCK_CHIP_SIZE bytes are tracked/logged/asserted. + */ + .total_size = 1, + .tested = TEST_OK_PREW, + .gran = WRITE_GRAN_1BYTE, + .read = TEST_READ_INJECTOR, + .write = TEST_WRITE_INJECTOR, + .block_erasers = + { + { + .eraseblocks = { {1, MIN_REAL_CHIP_SIZE} }, + .block_erase = TEST_ERASE_INJECTOR_1, + }, { + .eraseblocks = { {2, MIN_REAL_CHIP_SIZE / 2} }, + .block_erase = TEST_ERASE_INJECTOR_2, + }, { + .eraseblocks = { {4, MIN_REAL_CHIP_SIZE / 4} }, + .block_erase = TEST_ERASE_INJECTOR_3, + }, { + .eraseblocks = { {8, MIN_REAL_CHIP_SIZE / 8} }, + .block_erase = TEST_ERASE_INJECTOR_4, + }, { + .eraseblocks = { {16, MIN_REAL_CHIP_SIZE / 16} }, + .block_erase = TEST_ERASE_INJECTOR_5, + } + }, +}; + +static struct flashchip chip_1_8_16 = { + .vendor = "aklm", + /* See comment on previous chip. */ + .total_size = 1, + .tested = TEST_OK_PREW, + .gran = WRITE_GRAN_1BYTE, + .read = TEST_READ_INJECTOR, + .write = TEST_WRITE_INJECTOR, + .block_erasers = + { + { + .eraseblocks = { {1, MIN_REAL_CHIP_SIZE} }, + .block_erase = TEST_ERASE_INJECTOR_1, + }, { + .eraseblocks = { {8, MIN_REAL_CHIP_SIZE / 8} }, + .block_erase = TEST_ERASE_INJECTOR_4, + }, { + .eraseblocks = { {16, MIN_REAL_CHIP_SIZE / 16} }, + .block_erase = TEST_ERASE_INJECTOR_5, + } + }, +}; + +static struct flashchip chip_8_16 = { + .vendor = "aklm", + /* See comment on previous chip. */ + .total_size = 1, + .tested = TEST_OK_PREW, + .gran = WRITE_GRAN_1BYTE, + .read = TEST_READ_INJECTOR, + .write = TEST_WRITE_INJECTOR, + .block_erasers = + { + { + .eraseblocks = { {8, MIN_REAL_CHIP_SIZE / 8} }, + .block_erase = TEST_ERASE_INJECTOR_4, + }, { + .eraseblocks = { {16, MIN_REAL_CHIP_SIZE / 16} }, + .block_erase = TEST_ERASE_INJECTOR_5, + } + }, +}; + +#define BLOCK_ERASE_FUNC(n) \ + static int block_erase_chip_ ## n (struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen) { \ + return block_erase_chip_tagged(flash, TEST_ERASE_INJECTOR_ ## n, blockaddr, blocklen); \ + } +BLOCK_ERASE_FUNC(1) +BLOCK_ERASE_FUNC(2) +BLOCK_ERASE_FUNC(3) +BLOCK_ERASE_FUNC(4) +BLOCK_ERASE_FUNC(5) + +/* + * Returns the offset how far we need to verify mock chip memory. + * Which is minimum out of MOCK_CHIP_SIZE and the end of the logical layout. + */ +static chipoff_t setup_chip(struct flashrom_flashctx *flashctx, struct flashrom_layout **layout, + const char *programmer_param, struct test_case *current_test_case) +{ + chipoff_t verify_end_boundary = MOCK_CHIP_SIZE - 1; + + g_test_write_injector = write_chip; + g_test_read_injector = read_chip; + /* Each erasefunc corresponds to an operation that erases a block of + * the chip with a particular size in bytes. */ + memcpy(g_test_erase_injector, + (erasefunc_t *const[]){ + block_erase_chip_1, // 1 byte + block_erase_chip_2, // 2 bytes + block_erase_chip_3, // 4 bytes + block_erase_chip_4, // 8 bytes + block_erase_chip_5, // 16 bytes + }, + sizeof(g_test_erase_injector) + ); + + /* First MOCK_CHIP_SIZE bytes have a meaning and set with given values for this test case. */ + memcpy(g_state.buf, current_test_case->initial_buf, MOCK_CHIP_SIZE); + /* The rest of mock chip memory does not matter. */ + memset(g_state.buf + MOCK_CHIP_SIZE, ERASE_VALUE, MIN_REAL_CHIP_SIZE - MOCK_CHIP_SIZE); + + /* Clear eraseblock invocation records. */ + memset(g_state.eraseblocks_actual, 0, MOCK_CHIP_SIZE * sizeof(struct erase_invoke)); + g_state.eraseblocks_actual_ind = 0; + + /* Clear the tracking of each byte modified. */ + memset(g_state.was_modified, false, MIN_REAL_CHIP_SIZE); + /* Clear the tracking of each byte verified. */ + memset(g_state.was_verified, false, MIN_REAL_CHIP_SIZE); + + /* Set the flag to verify after writing on chip */ + flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_AFTER_WRITE, true); + + flashctx->chip = current_test_case->chip; + + printf("Creating layout ... "); + assert_int_equal(0, flashrom_layout_new(layout)); + + /* Adding regions from test case. */ + int i = 0; + while (current_test_case->regions[i].name != NULL) { + assert_int_equal(0, flashrom_layout_add_region(*layout, + current_test_case->regions[i].start, + current_test_case->regions[i].end, + current_test_case->regions[i].name)); + assert_int_equal(0, flashrom_layout_include_region(*layout, current_test_case->regions[i].name)); + + if (current_test_case->regions[i].end < MOCK_CHIP_SIZE - 1) + verify_end_boundary = current_test_case->regions[i].end; + else + verify_end_boundary = MOCK_CHIP_SIZE - 1; + + i++; + } + + flashrom_layout_set(flashctx, *layout); + printf("done\n"); + + /* + * We need some programmer (any), and dummy is a very good one, + * because it doesn't need any mocking. So no extra complexity + * from a programmer side, and test can focus on working with the chip. + */ + printf("Dummyflasher initialising with param=\"%s\"... ", programmer_param); + assert_int_equal(0, programmer_init(&programmer_dummy, programmer_param)); + /* Assignment below normally happens while probing, but this test is not probing. */ + flashctx->mst = ®istered_masters[0]; + printf("done\n"); + + return verify_end_boundary; +} + +static void teardown_chip(struct flashrom_layout **layout) +{ + printf("Dummyflasher shutdown... "); + assert_int_equal(0, programmer_shutdown()); + printf("done\n"); + + printf("Releasing layout... "); + flashrom_layout_release(*layout); + printf("done\n"); +} + +/* + * Setup all test cases. + * + * First half of test cases is set up for a chip with erasers: 1, 2, 4, 8, 16 bytes. + * Second half repeates the same test cases for a chip with erasers: 1, 8, 16 bytes. + * Tests from #16 onwards use the chip with erasers: 8, 16 bytes, to test unaligned layout regions. + */ +static struct test_case test_cases[] = { + { + /* + * Test case #0 + * + * Initial vs written: all 16 bytes are different. + * One layout region for the whole chip. + * Chip with eraseblocks 1, 2, 4, 8, 16. + */ + .chip = &chip_1_2_4_8_16, + .regions = {{0, MIN_REAL_CHIP_SIZE - 1, "whole chip"}}, + .initial_buf = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, + 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f}, + .eraseblocks_expected = {{0x0, 0x10, TEST_ERASE_INJECTOR_5}}, + .eraseblocks_expected_ind = 1, + .erase_test_name = "Erase test case #0", + .write_test_name = "Write test case #0", + }, { + /* + * Test case #1 + * + * Initial vs written: 9 bytes the same, 7 bytes different. + * Two layout regions each one 8 bytes, which is 1/2 size of chip. + * Chip with eraseblocks 1, 2, 4, 8, 16. + */ + .chip = &chip_1_2_4_8_16, + .regions = {{0, MOCK_CHIP_SIZE/2 - 1, "part1"}, {MOCK_CHIP_SIZE/2, MIN_REAL_CHIP_SIZE - 1, "part2"}}, + .initial_buf = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f}, + .eraseblocks_expected = {{0x8, 0x8, TEST_ERASE_INJECTOR_4}, {0x0, 0x8, TEST_ERASE_INJECTOR_4}}, + .eraseblocks_expected_ind = 2, + .erase_test_name = "Erase test case #1", + .write_test_name = "Write test case #1", + }, { + /* + * Test case #2 + * + * Initial vs written: 6 bytes the same, 4 bytes different, 4 bytes the same, 2 bytes different. + * Two layout regions 11 and 5 bytes each. + * Chip with eraseblocks 1, 2, 4, 8, 16. + */ + .chip = &chip_1_2_4_8_16, + .regions = {{0, 10, "odd1"}, {11, 15, "odd2"}, {MOCK_CHIP_SIZE, MIN_REAL_CHIP_SIZE - 1, "longtail"}}, + .initial_buf = {0xff, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, + 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0xff, 0xff, 0x0, 0xff, 0x0, 0xff, 0x20, 0x2f, + 0x20, 0x2f, 0x0, 0xff, 0xff, 0xff, 0x2f, 0x2f}, + .eraseblocks_expected = { + {0xb, 0x1, TEST_ERASE_INJECTOR_1}, + {0xc, 0x4, TEST_ERASE_INJECTOR_3}, + {0xa, 0x1, TEST_ERASE_INJECTOR_1}, + {0x8, 0x2, TEST_ERASE_INJECTOR_2}, + {0x0, 0x8, TEST_ERASE_INJECTOR_4} + }, + .eraseblocks_expected_ind = 5, + .erase_test_name = "Erase test case #2", + .write_test_name = "Write test case #2", + }, { + /* + * Test case #3 + * + * Initial vs written: 4 bytes the same, 4 bytes different, 8 bytes the same. + * One layout region covering the whole chip. + * Chip with eraseblocks 1, 2, 4, 8, 16. + */ + .chip = &chip_1_2_4_8_16, + .regions = {{0, MIN_REAL_CHIP_SIZE - 1, "whole chip"}}, + .initial_buf = {0xff, 0xff, 0xff, 0xff, 0x11, 0x22, 0x33, 0x44, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0xff, 0xff, 0xff, 0xff, 0x1, 0x2, 0x3, 0x4, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .eraseblocks_expected = {{0x0, 0x10, TEST_ERASE_INJECTOR_5}}, + .eraseblocks_expected_ind = 1, + .erase_test_name = "Erase test case #3", + .write_test_name = "Write test case #3", + }, { + /* + * Test case #4 + * + * Initial vs written: 4 bytes different, 4 bytes the same, 8 bytes different. + * One layout region covering the whole chip. + * Chip with eraseblocks 1, 2, 4, 8, 16. + */ + .chip = &chip_1_2_4_8_16, + .regions = {{0, MIN_REAL_CHIP_SIZE - 1, "whole chip"}}, + .initial_buf = {0x1, 0x2, 0x3, 0x4, 0xff, 0xff, 0xff, 0xff, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0x11, 0x22, 0x33, 0x44, 0xff, 0xff, 0xff, 0xff, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, + .eraseblocks_expected = {{0x0, 0x10, TEST_ERASE_INJECTOR_5}}, + .eraseblocks_expected_ind = 1, + .erase_test_name = "Erase test case #4", + .write_test_name = "Write test case #4", + }, { + /* + * Test case #5 + * + * Initial vs written: 7 bytes different, 1 bytes the same, 8 bytes different. + * One layout region covering the whole chip. + * Chip with eraseblocks 1, 2, 4, 8, 16. + */ + .chip = &chip_1_2_4_8_16, + .regions = {{0, MIN_REAL_CHIP_SIZE - 1, "whole chip"}}, + .initial_buf = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0xff, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0xff, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, + .eraseblocks_expected = {{0x0, 0x10, TEST_ERASE_INJECTOR_5}}, + .eraseblocks_expected_ind = 1, + .erase_test_name = "Erase test case #5", + .write_test_name = "Write test case #5", + }, { + /* + * Test case #6 + * + * Initial vs written: 7 bytes the same, 1 bytes different, 8 bytes the same. + * One layout region covering the whole chip. + * Chip with eraseblocks 1, 2, 4, 8, 16. + */ + .chip = &chip_1_2_4_8_16, + .regions = {{0, MIN_REAL_CHIP_SIZE - 1, "whole chip"}}, + .initial_buf = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x1d, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0xdd, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, + .eraseblocks_expected = {{0x0, 0x10, TEST_ERASE_INJECTOR_5}}, + .eraseblocks_expected_ind = 1, + .erase_test_name = "Erase test case #6", + .write_test_name = "Write test case #6", + }, { + /* + * Test case #7 + * + * Initial vs written: all 16 bytes are different. + * Layout with irregular regions unaligned with eraseblocks. + * Chip with eraseblocks 1, 2, 4, 8, 16. + */ + .chip = &chip_1_2_4_8_16, + .regions = {{0, 2, "reg3"}, {3, 7, "reg5"}, {8, 14, "reg7"}, {15, MIN_REAL_CHIP_SIZE - 1, "reg1"}}, + .initial_buf = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f}, + .eraseblocks_expected = { + {0xf, 0x1, TEST_ERASE_INJECTOR_1}, + {0xe, 0x1, TEST_ERASE_INJECTOR_1}, + {0xc, 0x2, TEST_ERASE_INJECTOR_2}, + {0x8, 0x4, TEST_ERASE_INJECTOR_3}, + {0x3, 0x1, TEST_ERASE_INJECTOR_1}, + {0x4, 0x4, TEST_ERASE_INJECTOR_3}, + {0x2, 0x1, TEST_ERASE_INJECTOR_1}, + {0x0, 0x2, TEST_ERASE_INJECTOR_2} + }, + .eraseblocks_expected_ind = 8, + .erase_test_name = "Erase test case #7", + .write_test_name = "Write test case #7", + }, { + /* + * Test case #8 + * + * Initial vs written: all 16 bytes are different. + * One layout region for the whole chip. + * Chip with eraseblocks 1, 8, 16. + */ + .chip = &chip_1_8_16, + .regions = {{0, MIN_REAL_CHIP_SIZE - 1, "whole chip"}}, + .initial_buf = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f}, + .eraseblocks_expected = {{0x0, 0x10, TEST_ERASE_INJECTOR_5}}, + .eraseblocks_expected_ind = 1, + .erase_test_name = "Erase test case #8", + .write_test_name = "Write test case #8", + }, { + /* + * Test case #9 + * + * Initial vs written: 9 bytes the same, 7 bytes different. + * Two layout regions each one 8 bytes, which is 1/2 size of chip. + * Chip with eraseblocks 1, 8, 16. + */ + .chip = &chip_1_8_16, + .regions = {{0, MOCK_CHIP_SIZE/2 - 1, "part1"}, {MOCK_CHIP_SIZE/2, MOCK_CHIP_SIZE - 1, "part2"}, + {MOCK_CHIP_SIZE, MIN_REAL_CHIP_SIZE - 1, "longtail"}}, + .initial_buf = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f}, + .eraseblocks_expected = {{0x8, 0x8, TEST_ERASE_INJECTOR_4}, {0x0, 0x8, TEST_ERASE_INJECTOR_4}}, + .eraseblocks_expected_ind = 2, + .erase_test_name = "Erase test case #9", + .write_test_name = "Write test case #9", + }, { + /* + * Test case #10 + * + * Initial vs written: 6 bytes the same, 4 bytes different, 4 bytes the same, 2 bytes different. + * Two layout regions 11 and 5 bytes each. + * Chip with eraseblocks 1, 8, 16. + */ + .chip = &chip_1_8_16, + .regions = {{0, 10, "odd1"}, {11, 15, "odd2"}, {MOCK_CHIP_SIZE, MIN_REAL_CHIP_SIZE - 1, "longtail"}}, + .initial_buf = {0xff, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, + 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0xff, 0xff, 0x0, 0xff, 0x0, 0xff, 0x20, 0x2f, + 0x20, 0x2f, 0x0, 0xff, 0xff, 0xff, 0x2f, 0x2f}, + .eraseblocks_expected = { + {0xb, 0x1, TEST_ERASE_INJECTOR_1}, + {0xc, 0x1, TEST_ERASE_INJECTOR_1}, + {0xd, 0x1, TEST_ERASE_INJECTOR_1}, + {0xe, 0x1, TEST_ERASE_INJECTOR_1}, + {0xf, 0x1, TEST_ERASE_INJECTOR_1}, + {0x8, 0x1, TEST_ERASE_INJECTOR_1}, + {0x9, 0x1, TEST_ERASE_INJECTOR_1}, + {0xa, 0x1, TEST_ERASE_INJECTOR_1}, + {0x0, 0x8, TEST_ERASE_INJECTOR_4} + }, + .eraseblocks_expected_ind = 9, + .erase_test_name = "Erase test case #10", + .write_test_name = "Write test case #10", + }, { + /* + * Test case #11 + * + * Initial vs written: 4 bytes the same, 4 bytes different, 8 bytes the same. + * One layout region covering the whole chip. + * Chip with eraseblocks 1, 8, 16. + */ + .chip = &chip_1_8_16, + .regions = {{0, MIN_REAL_CHIP_SIZE - 1, "whole chip"}}, + .initial_buf = {0xff, 0xff, 0xff, 0xff, 0x11, 0x22, 0x33, 0x44, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0xff, 0xff, 0xff, 0xff, 0x1, 0x2, 0x3, 0x4, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .eraseblocks_expected = {{0x0, 0x10, TEST_ERASE_INJECTOR_5}}, + .eraseblocks_expected_ind = 1, + .erase_test_name = "Erase test case #11", + .write_test_name = "Write test case #11", + }, { + /* + * Test case #12 + * + * Initial vs written: 4 bytes different, 4 bytes the same, 8 bytes different. + * One layout region covering the whole chip. + * Chip with eraseblocks 1, 8, 16. + */ + .chip = &chip_1_8_16, + .regions = {{0, MIN_REAL_CHIP_SIZE - 1, "whole chip"}}, + .initial_buf = {0x1, 0x2, 0x3, 0x4, 0xff, 0xff, 0xff, 0xff, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0x11, 0x22, 0x33, 0x44, 0xff, 0xff, 0xff, 0xff, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, + .eraseblocks_expected = {{0x0, 0x10, TEST_ERASE_INJECTOR_5}}, + .eraseblocks_expected_ind = 1, + .erase_test_name = "Erase test case #12", + .write_test_name = "Write test case #12", + }, { + /* + * Test case #13 + * + * Initial vs written: 7 bytes different, 1 bytes the same, 8 bytes different. + * One layout region covering the whole chip. + * Chip with eraseblocks 1, 8, 16. + */ + .chip = &chip_1_8_16, + .regions = {{0, MIN_REAL_CHIP_SIZE - 1, "whole chip"}}, + .initial_buf = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0xff, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0xff, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, + .eraseblocks_expected = {{0x0, 0x10, TEST_ERASE_INJECTOR_5}}, + .eraseblocks_expected_ind = 1, + .erase_test_name = "Erase test case #13", + .write_test_name = "Write test case #13", + }, { + /* + * Test case #14 + * + * Initial vs written: 7 bytes the same, 1 bytes different, 8 bytes the same. + * One layout region covering the whole chip. + * Chip with eraseblocks 1, 8, 16. + */ + .chip = &chip_1_8_16, + .regions = {{0, MIN_REAL_CHIP_SIZE - 1, "whole chip"}}, + .initial_buf = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x1d, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0xdd, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, + .eraseblocks_expected = {{0x0, 0x10, TEST_ERASE_INJECTOR_5}}, + .eraseblocks_expected_ind = 1, + .erase_test_name = "Erase test case #14", + .write_test_name = "Write test case #14", + }, { + /* + * Test case #15 + * + * Initial vs written: all 16 bytes are different. + * Layout with irregular regions unaligned with eraseblocks. + * Chip with eraseblocks 1, 8, 16. + */ + .chip = &chip_1_8_16, + .regions = {{0, 2, "reg3"}, {3, 7, "reg5"}, {8, 14, "reg7"}, + {15, MIN_REAL_CHIP_SIZE - 1, "reg1"}}, + .initial_buf = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f}, + .eraseblocks_expected = { + {0xf, 0x1, TEST_ERASE_INJECTOR_1}, + {0x8, 0x1, TEST_ERASE_INJECTOR_1}, + {0x9, 0x1, TEST_ERASE_INJECTOR_1}, + {0xa, 0x1, TEST_ERASE_INJECTOR_1}, + {0xb, 0x1, TEST_ERASE_INJECTOR_1}, + {0xc, 0x1, TEST_ERASE_INJECTOR_1}, + {0xd, 0x1, TEST_ERASE_INJECTOR_1}, + {0xe, 0x1, TEST_ERASE_INJECTOR_1}, + {0x3, 0x1, TEST_ERASE_INJECTOR_1}, + {0x4, 0x1, TEST_ERASE_INJECTOR_1}, + {0x5, 0x1, TEST_ERASE_INJECTOR_1}, + {0x6, 0x1, TEST_ERASE_INJECTOR_1}, + {0x7, 0x1, TEST_ERASE_INJECTOR_1}, + {0x0, 0x1, TEST_ERASE_INJECTOR_1}, + {0x1, 0x1, TEST_ERASE_INJECTOR_1}, + {0x2, 0x1, TEST_ERASE_INJECTOR_1}, + }, + .eraseblocks_expected_ind = 16, + .erase_test_name = "Erase test case #15", + .write_test_name = "Write test case #15", + }, { + /* + * Test case #16 + * + * Initial vs written: all 16 bytes are different. + * Layout with unaligned regions 2+4+9+1b which are smaller than the smallest eraseblock. + * Chip with eraseblocks 8, 16. + */ + .chip = &chip_8_16, + .regions = {{0, 1, "reg2"}, {2, 5, "reg4"}, {6, 14, "reg9"}, + {15, MIN_REAL_CHIP_SIZE - 1, "reg1"}}, + .initial_buf = {0x4, 0x4, 0x5, 0x5, 0x5, 0x5, 0x6, 0x6, + 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x7}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x17}, + .eraseblocks_expected = { + {0x8, 0x8, TEST_ERASE_INJECTOR_4}, + {0x0, 0x10, TEST_ERASE_INJECTOR_5}, + {0x0, 0x8, TEST_ERASE_INJECTOR_4}, + {0x0, 0x8, TEST_ERASE_INJECTOR_4}, + }, + .eraseblocks_expected_ind = 4, + .erase_test_name = "Erase test case #16", + .write_test_name = "Write test case #16", + }, { + /* + * Test case #17 + * + * Initial vs written: all 16 bytes are different. + * Layout with unaligned region 3+13b which are smaller than the smallest eraseblock. + * Chip with eraseblocks 8, 16. + */ + .chip = &chip_8_16, + .regions = {{0, 2, "reg3"}, {3, MIN_REAL_CHIP_SIZE - 1, "tail"}}, + .initial_buf = {0x4, 0x4, 0x4, 0x6, 0x6, 0x6, 0x6, 0x6, + 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0x14, 0x14, 0x14, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16}, + .eraseblocks_expected = {{0x0, 0x10, TEST_ERASE_INJECTOR_5}, {0x0, 0x8, TEST_ERASE_INJECTOR_4}}, + .eraseblocks_expected_ind = 2, + .erase_test_name = "Erase test case #17", + .write_test_name = "Write test case #17", + }, { + /* + * Test case #18 + * + * Initial vs written: all 16 bytes are different. + * Layout with unaligned region 9+7b. + * Chip with eraseblocks 8, 16. + */ + .chip = &chip_8_16, + .regions = {{0, 8, "reg9"}, {9, MIN_REAL_CHIP_SIZE - 1, "tail"}}, + .initial_buf = {0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, + 0x4, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16}, + .eraseblocks_expected = {{0x8, 0x8, TEST_ERASE_INJECTOR_4}, {0x0, 0x10, TEST_ERASE_INJECTOR_5}}, + .eraseblocks_expected_ind = 2, + .erase_test_name = "Erase test case #18", + .write_test_name = "Write test case #18", + }, { + /* + * Test case #19 + * + * Initial vs written: 3 bytes of the logical layout are different, rest is the same. + * Layout with unaligned region 3 bytes. Layout does not cover the whole chip memory. + * Chip memory outside of logical layout is skipped by both erase and write ops. + * Chip with eraseblocks 8, 16. + */ + .chip = &chip_8_16, + .regions = {{0, 2, "reg3"}}, + .initial_buf = {0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + .written_buf = {0x14, 0x14, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + .eraseblocks_expected = {{0x0, 0x8, TEST_ERASE_INJECTOR_4}}, + .eraseblocks_expected_ind = 1, + .erase_test_name = "Erase test case #19", + .write_test_name = "Write test case #19", + }, +}; + + +#define START_PROTECTED_REGION 6 +#define END_PROTECTED_REGION 13 + +/* + * Setup all test cases with protected region. + * Protected region is the same for all test cases, between bytes START_PROTECTED_REGION and up to END_PROTECTED_REGION. + */ +static struct test_case test_cases_protected_region[] = { + { + /* + * Test case #0 + * + * Initial vs written: all 16 bytes are different. + * One layout region for the whole chip. + * Chip with eraseblocks 1, 2, 4, 8, 16. + */ + .chip = &chip_1_2_4_8_16, + .regions = {{0, MIN_REAL_CHIP_SIZE - 1, "whole chip"}}, + .initial_buf = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, + .written_protected_buf = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0x6, 0x7, + 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xfe, 0xff}, + .eraseblocks_expected = {{0x4, 0x2, TEST_ERASE_INJECTOR_2}, {0x0, 0x4, TEST_ERASE_INJECTOR_3}, + {0xe, 0x2, TEST_ERASE_INJECTOR_2}}, + .eraseblocks_expected_ind = 3, + .erase_test_name = "Erase protected region test case #0", + .write_test_name = "Write protected region test case #0", + }, { + /* + * Test case #1 + * + * Initial vs written: all 16 bytes are different. + * Two layout regions each one 8 bytes, which is 1/2 size of chip. + * Chip with eraseblocks 1, 2, 4, 8, 16. + */ + .chip = &chip_1_2_4_8_16, + .regions = {{0, MOCK_CHIP_SIZE/2 - 1, "part1"}, {MOCK_CHIP_SIZE/2, MIN_REAL_CHIP_SIZE - 1, "part2"}}, + .initial_buf = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, + .written_protected_buf = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xae, 0xaf}, + .eraseblocks_expected = {{0xe, 0x2, TEST_ERASE_INJECTOR_2}, {0x4, 0x2, TEST_ERASE_INJECTOR_2}, + {0x0, 0x4, TEST_ERASE_INJECTOR_3}}, + .eraseblocks_expected_ind = 3, + .erase_test_name = "Erase protected region test case #1", + .write_test_name = "Write protected region test case #1", + }, { + /* + * Test case #2 + * + * Initial vs written: all 16 bytes are different. + * Three layout regions 8+4+4b + * Chip with eraseblocks 1, 2, 4, 8, 16. + */ + .chip = &chip_1_2_4_8_16, + .regions = {{0, 7, "odd1"}, {8, 11, "odd2"}, {12, 15, "odd3"}, + {MOCK_CHIP_SIZE, MIN_REAL_CHIP_SIZE - 1, "longtail"}}, + .initial_buf = {0xff, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, + 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, 0x0, 0xff, + 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, + .written_protected_buf = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x0, 0xff, + 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0xae, 0xaf}, + .eraseblocks_expected = {{0xe, 0x2, TEST_ERASE_INJECTOR_2}, {0x4, 0x2, TEST_ERASE_INJECTOR_2}, + {0x0, 0x4, TEST_ERASE_INJECTOR_3}}, + .eraseblocks_expected_ind = 3, + .erase_test_name = "Erase protected region test case #2", + .write_test_name = "Write protected region test case #2", + }, { + /* + * Test case #3 + * + * Initial vs written: all 16 bytes are different. + * Layout with unaligned regions 2+4+9+1b which require use of the 1-byte erase block. + * Chip with eraseblocks 1, 2, 4, 8, 16. + */ + .chip = &chip_1_2_4_8_16, + .regions = {{0, 1, "reg2"}, {2, 5, "reg4"}, {6, 14, "reg9"}, + {15, MIN_REAL_CHIP_SIZE - 1, "reg1"}}, + .initial_buf = {0x4, 0x4, 0x5, 0x5, 0x5, 0x5, 0x6, 0x6, + 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x7}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, 0x6, 0x6, + 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, + .written_protected_buf = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x6, 0x6, + 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0xae, 0xaf}, + .eraseblocks_expected = {{0xf, 0x1, TEST_ERASE_INJECTOR_1}, {0xe, 0x1, TEST_ERASE_INJECTOR_1}, + {0x2, 0x2, TEST_ERASE_INJECTOR_2}, {0x4, 0x2, TEST_ERASE_INJECTOR_2}, + {0x0, 0x2, TEST_ERASE_INJECTOR_2}}, + .eraseblocks_expected_ind = 5, + .erase_test_name = "Erase protected region test case #3", + .write_test_name = "Write protected region test case #3", + }, { + /* + * Test case #4 + * + * Initial vs written: all 16 bytes are different. + * Layout with unaligned region 3+13b which require use of the 1-byte erase block. + * Chip with eraseblocks 1, 8, 16. + */ + .chip = &chip_1_8_16, + .regions = {{0, 2, "reg3"}, {3, MIN_REAL_CHIP_SIZE - 1, "tail"}}, + .initial_buf = {0x4, 0x4, 0x4, 0x6, 0x6, 0x6, 0x6, 0x6, + 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, 0x6, 0x6, + 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, + .written_protected_buf = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x6, 0x6, + 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0xae, 0xaf}, + .eraseblocks_expected = { + {0x3, 0x1, TEST_ERASE_INJECTOR_1}, + {0x4, 0x1, TEST_ERASE_INJECTOR_1}, + {0x5, 0x1, TEST_ERASE_INJECTOR_1}, + {0xe, 0x1, TEST_ERASE_INJECTOR_1}, + {0xf, 0x1, TEST_ERASE_INJECTOR_1}, + {0x0, 0x1, TEST_ERASE_INJECTOR_1}, + {0x1, 0x1, TEST_ERASE_INJECTOR_1}, + {0x2, 0x1, TEST_ERASE_INJECTOR_1}, + }, + .eraseblocks_expected_ind = 8, + .erase_test_name = "Erase protected region test case #4", + .write_test_name = "Write protected region test case #4", + }, { + /* + * Test case #5 + * + * Initial vs written: all 16 bytes are different. + * Layout with unaligned region 9+7b. + * Chip with eraseblocks 1, 8, 16. + */ + .chip = &chip_1_8_16, + .regions = {{0, 8, "reg9"}, {9, MIN_REAL_CHIP_SIZE - 1, "tail"}}, + .initial_buf = {0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, + 0x4, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6}, + .erased_buf = {ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, ERASE_VALUE, + ERASE_VALUE, ERASE_VALUE, 0x4, 0x4, + 0x4, 0x6, 0x6, 0x6, 0x6, 0x6, ERASE_VALUE, ERASE_VALUE}, + .written_buf = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, + .written_protected_buf = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x4, 0x4, + 0x4, 0x6, 0x6, 0x6, 0x6, 0x6, 0xae, 0xaf}, + .eraseblocks_expected = { + {0xe, 0x1, TEST_ERASE_INJECTOR_1}, + {0xf, 0x1, TEST_ERASE_INJECTOR_1}, + {0x0, 0x1, TEST_ERASE_INJECTOR_1}, + {0x1, 0x1, TEST_ERASE_INJECTOR_1}, + {0x2, 0x1, TEST_ERASE_INJECTOR_1}, + {0x3, 0x1, TEST_ERASE_INJECTOR_1}, + {0x4, 0x1, TEST_ERASE_INJECTOR_1}, + {0x5, 0x1, TEST_ERASE_INJECTOR_1}, + }, + .eraseblocks_expected_ind = 8, + .erase_test_name = "Erase protected region test case #5", + .write_test_name = "Write protected region test case #5", + }, +}; + +static int setup(void **state) { + struct test_case *current_test_case = *state; + g_state.current_test_case = current_test_case; + return 0; +} + +static int teardown(void **state) { + return 0; +} + +/* + * Creates the array of tests for each test case in test_cases[]. + * Each test_case produces two tests: one for erase and one for write operation. + * The caller needs to free the allocated memory. + */ +struct CMUnitTest *get_erase_func_algo_tests(size_t *num_tests) { + const size_t test_cases_num = ARRAY_SIZE(test_cases); + + // Twice the number of test cases, because each test case is run twice: for erase and write. + struct CMUnitTest *all_cases = calloc(test_cases_num * 2, sizeof(struct CMUnitTest)); + *num_tests = test_cases_num * 2; + + for (size_t i = 0; i < test_cases_num; i++) { + all_cases[i] = (struct CMUnitTest) { + .name = test_cases[i].erase_test_name, + .setup_func = setup, + .teardown_func = teardown, + .initial_state = &test_cases[i], + .test_func = erase_function_algo_test_success, + }; + all_cases[i + test_cases_num] = (struct CMUnitTest) { + .name = test_cases[i].write_test_name, + .setup_func = setup, + .teardown_func = teardown, + .initial_state = &test_cases[i], + .test_func = write_function_algo_test_success, + }; + } + + return all_cases; +} + +static void test_erase_fails_for_unwritable_region(void **); +static void erase_unwritable_regions_skipflag_on_test_success(void **); +static void write_unwritable_regions_skipflag_on_test_success(void **); + +/* + * Creates the array of tests for each test case in test_cases_protected_region[]. + * The caller needs to free the allocated memory. + */ +struct CMUnitTest *get_erase_protected_region_algo_tests(size_t *num_tests) { + const size_t num_parameterized = ARRAY_SIZE(test_cases_protected_region); + const size_t num_unparameterized = 1; + // Twice the number of parameterized test cases, because each test case is run twice: + // for erase and write. + const size_t num_cases = num_parameterized * 2 + num_unparameterized; + + struct CMUnitTest *all_cases = calloc(num_cases, sizeof(struct CMUnitTest)); + *num_tests = num_cases; + + for (size_t i = 0; i < num_parameterized; i++) { + all_cases[i] = (struct CMUnitTest) { + .name = test_cases_protected_region[i].erase_test_name, + .setup_func = setup, + .teardown_func = teardown, + .initial_state = &test_cases_protected_region[i], + .test_func = erase_unwritable_regions_skipflag_on_test_success, + }; + all_cases[i + num_parameterized] = (struct CMUnitTest) { + .name = test_cases_protected_region[i].write_test_name, + .setup_func = setup, + .teardown_func = teardown, + .initial_state = &test_cases_protected_region[i], + .test_func = write_unwritable_regions_skipflag_on_test_success, + }; + } + + memcpy( + &all_cases[num_parameterized * 2], + (const struct CMUnitTest[]){ + (const struct CMUnitTest) { + .name = "erase failure for unskipped unwritable regions", + .test_func = test_erase_fails_for_unwritable_region, + } + }, + sizeof(*all_cases) * num_unparameterized + ); + + return all_cases; +} + +/* + * This function is invoked for every test case in test_cases[], + * current test case is passed as an argument. + */ +void erase_function_algo_test_success(void **state) +{ + struct test_case* current_test_case = *state; + + int all_erase_tests_result = 0; + struct flashrom_flashctx flashctx = { 0 }; + const char *param = ""; /* Default values for all params. */ + + struct flashrom_layout *layout; + + const chipoff_t verify_end_boundary = setup_chip(&flashctx, &layout, param, current_test_case); + + printf("%s started.\n", current_test_case->erase_test_name); + int ret = flashrom_flash_erase(&flashctx); + printf("%s returned %d.\n", current_test_case->erase_test_name, ret); + + int chip_erased = !memcmp(g_state.buf, current_test_case->erased_buf, MOCK_CHIP_SIZE); + + int eraseblocks_in_order = !memcmp(g_state.eraseblocks_actual, + current_test_case->eraseblocks_expected, + current_test_case->eraseblocks_expected_ind * sizeof(struct erase_invoke)); + + int eraseblocks_invocations = (g_state.eraseblocks_actual_ind == + current_test_case->eraseblocks_expected_ind); + + int chip_verified = 1; + for (unsigned int i = 0; i <= verify_end_boundary; i++) + if (g_state.was_modified[i] && !g_state.was_verified[i]) { + chip_verified = 0; /* byte was modified, but not verified after */ + printf("Error: byte 0x%x, modified: %d, verified: %d\n", i, g_state.was_modified[i], g_state.was_verified[i]); + } + + if (chip_erased) + printf("Erased chip memory state for %s is CORRECT\n", + current_test_case->erase_test_name); + else + printf("Erased chip memory state for %s is WRONG\n", + current_test_case->erase_test_name); + + if (eraseblocks_in_order) + printf("Eraseblocks order of invocation for %s is CORRECT\n", + current_test_case->erase_test_name); + else + printf("Eraseblocks order of invocation for %s is WRONG\n", + current_test_case->erase_test_name); + + if (eraseblocks_invocations) + printf("Eraseblocks number of invocations for %s is CORRECT\n", + current_test_case->erase_test_name); + else + printf("Eraseblocks number of invocations for %s is WRONG, expected %d actual %d\n", + current_test_case->erase_test_name, + current_test_case->eraseblocks_expected_ind, + g_state.eraseblocks_actual_ind); + + if (chip_verified) + printf("Erased chip memory state for %s was verified successfully\n", + current_test_case->erase_test_name); + else + printf("Erased chip memory state for %s was NOT verified completely\n", + current_test_case->erase_test_name); + + all_erase_tests_result |= ret; + all_erase_tests_result |= !chip_erased; + all_erase_tests_result |= !eraseblocks_in_order; + all_erase_tests_result |= !eraseblocks_invocations; + all_erase_tests_result |= !chip_verified; + + teardown_chip(&layout); + + assert_int_equal(0, all_erase_tests_result); +} + +/* + * This function is invoked for every test case in test_cases[], + * current test case is passed as an argument. + */ +void write_function_algo_test_success(void **state) +{ + struct test_case* current_test_case = *state; + + int all_write_test_result = 0; + struct flashrom_flashctx flashctx = { 0 }; + uint8_t newcontents[MIN_BUF_SIZE]; + const char *param = ""; /* Default values for all params. */ + + struct flashrom_layout *layout; + + const chipoff_t verify_end_boundary = setup_chip(&flashctx, &layout, param, current_test_case); + memcpy(&newcontents, current_test_case->written_buf, MOCK_CHIP_SIZE); + + printf("%s started.\n", current_test_case->write_test_name); + int ret = flashrom_image_write(&flashctx, &newcontents, MIN_BUF_SIZE, NULL); + printf("%s returned %d.\n", current_test_case->write_test_name, ret); + + int chip_written = !memcmp(g_state.buf, current_test_case->written_buf, MOCK_CHIP_SIZE); + + int chip_verified = 1; + for (unsigned int i = 0; i <= verify_end_boundary; i++) + if (g_state.was_modified[i] && !g_state.was_verified[i]) { + chip_verified = 0; /* the byte was modified, but not verified after */ + printf("Error: byte 0x%x, modified: %d, verified: %d\n", i, g_state.was_modified[i], g_state.was_verified[i]); + } + + if (chip_written) + printf("Written chip memory state for %s is CORRECT\n", + current_test_case->write_test_name); + else + printf("Written chip memory state for %s is WRONG\n", + current_test_case->write_test_name); + + if (chip_verified) + printf("Written chip memory state for %s was verified successfully\n", + current_test_case->write_test_name); + else + printf("Written chip memory state for %s was NOT verified completely\n", + current_test_case->write_test_name); + + all_write_test_result |= ret; + all_write_test_result |= !chip_written; + all_write_test_result |= !chip_verified; + + teardown_chip(&layout); + + assert_int_equal(0, all_write_test_result); +} + +static void get_protected_region(const struct flashctx *flash, unsigned int addr, struct flash_region *region) +{ + if (addr < 20) + printf("Inside test get_protected_region for addr=0x%x\n", addr); + + if (addr < START_PROTECTED_REGION) { + region->name = strdup("not protected"); + region->start = 0; + region->end = START_PROTECTED_REGION - 1; + region->read_prot = false; + region->write_prot = false; + } else if (addr <= END_PROTECTED_REGION) { + region->name = strdup("protected"); + region->start = START_PROTECTED_REGION; + region->end = END_PROTECTED_REGION; + region->read_prot = false; + region->write_prot = true; + } else { + region->name = strdup("tail"); + region->start = END_PROTECTED_REGION + 1; + region->end = flashrom_flash_getsize(flash) - 1; + region->read_prot = false; + region->write_prot = false; + } +} + +static int block_erase_chip_with_protected_region(struct flashctx *flash, enum block_erase_func erase_func, unsigned int blockaddr, unsigned int blocklen) +{ + if (blockaddr + blocklen <= MOCK_CHIP_SIZE) { + LOG_ERASE_FUNC; + + /* Register eraseblock invocation. */ + g_state.eraseblocks_actual[g_state.eraseblocks_actual_ind] = (struct erase_invoke){ + .erase_func = erase_func, + .blocklen = blocklen, + .blockaddr = blockaddr, + }; + g_state.eraseblocks_actual_ind++; + } + + assert_in_range(blockaddr + blocklen, 0, MIN_REAL_CHIP_SIZE); + + // Check we are not trying to erase protected region. This should not happen, + // because the logic should handle protected regions and never invoke erasefn + // for them. If this happens, means there is a bug in erasure logic, and test fails. + // + // Note: returning 1 instead of assert, so that the flow goes back to erasure code + // to clean up the memory after failed erase. Memory leaks are also tested by unit tests. + const unsigned int erase_op_size = 1 << (erase_func - TEST_ERASE_INJECTOR_1); + if (blocklen < erase_op_size) { + printf("Error: block length %d is smaller than erase_func length %d\n", blocklen, erase_op_size); + return 1; + } + + if ((blockaddr >= START_PROTECTED_REGION && blockaddr <= END_PROTECTED_REGION) + || (blockaddr + blocklen - 1 >= START_PROTECTED_REGION + && blockaddr + blocklen - 1 <= END_PROTECTED_REGION) + || (blockaddr < START_PROTECTED_REGION + && blockaddr + blocklen + 1 > END_PROTECTED_REGION)) { + printf("Error: block with start=%d, len=%d overlaps protected region %d-%d\n", + blockaddr, blocklen, START_PROTECTED_REGION, END_PROTECTED_REGION); + return 1; + } + + memset(&g_state.buf[blockaddr], ERASE_VALUE, blocklen); + + /* Track the bytes were erased */ + memset(&g_state.was_modified[blockaddr], true, blocklen); + /* Clear the records of previous verification, if there were any */ + memset(&g_state.was_verified[blockaddr], false, blocklen); + + return 0; +} + +#define BLOCK_ERASE_PROTECTED_FUNC(i) static int block_erase_chip_with_protected_region_ ## i \ + (struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen) { \ + return block_erase_chip_with_protected_region(flash, TEST_ERASE_INJECTOR_ ## i, blockaddr, blocklen); \ + } +BLOCK_ERASE_PROTECTED_FUNC(1) +BLOCK_ERASE_PROTECTED_FUNC(2) +BLOCK_ERASE_PROTECTED_FUNC(3) +BLOCK_ERASE_PROTECTED_FUNC(4) +BLOCK_ERASE_PROTECTED_FUNC(5) + +/* + * Runs the test cases that use protected flash regions (regions returned from + * get_flash_region() where write_prot is true) when the runtime flag to avoid + * writing to those regions is enabled. + * + * These tests verify that no protected region is erased, and that the erase + * commands used match the expected erase size (ensuring for example that a + * command erasing 16 bytes is not used when only 8 should be erased). + */ +static void erase_unwritable_regions_skipflag_on_test_success(void **state) +{ + struct test_case* current_test_case = *state; + + int all_erase_tests_result = 0; + struct flashrom_flashctx flashctx = { 0 }; + const char *param = ""; /* Default values for all params. */ + + struct flashrom_layout *layout; + + const chipoff_t verify_end_boundary = setup_chip(&flashctx, &layout, param, current_test_case); + + // This test needs special block erase to emulate protected regions. + memcpy(g_test_erase_injector, + (erasefunc_t *const[]){ + block_erase_chip_with_protected_region_1, + block_erase_chip_with_protected_region_2, + block_erase_chip_with_protected_region_3, + block_erase_chip_with_protected_region_4, + block_erase_chip_with_protected_region_5, + }, + sizeof(g_test_erase_injector) + ); + + flashrom_flag_set(&flashctx, FLASHROM_FLAG_SKIP_UNWRITABLE_REGIONS, true); + + // We use dummyflasher programmer in tests, but for this test we need to + // replace dummyflasher's default get_region fn with test one. + // The rest of master struct is fine for this test. + // Note dummyflasher registers multiple masters by default, so replace + // get_region for each of them. + flashctx.mst->spi.get_region = &get_protected_region; + flashctx.mst->opaque.get_region = &get_protected_region; + + printf("%s started.\n", current_test_case->erase_test_name); + int ret = flashrom_flash_erase(&flashctx); + printf("%s returned %d.\n", current_test_case->erase_test_name, ret); + + int chip_erased = !memcmp(g_state.buf, current_test_case->erased_buf, MOCK_CHIP_SIZE); + + int eraseblocks_in_order = !memcmp(g_state.eraseblocks_actual, + current_test_case->eraseblocks_expected, + current_test_case->eraseblocks_expected_ind * sizeof(struct erase_invoke)); + + int eraseblocks_invocations = (g_state.eraseblocks_actual_ind == + current_test_case->eraseblocks_expected_ind); + + int chip_verified = 1; + for (unsigned int i = 0; i <= verify_end_boundary; i++) + if (g_state.was_modified[i] && !g_state.was_verified[i]) { + chip_verified = 0; /* byte was modified, but not verified after */ + printf("Error: byte 0x%x, modified: %d, verified: %d\n", i, g_state.was_modified[i], g_state.was_verified[i]); + } + + if (chip_erased) + printf("Erased chip memory state for %s is CORRECT\n", + current_test_case->erase_test_name); + else + printf("Erased chip memory state for %s is WRONG\n", + current_test_case->erase_test_name); + + if (eraseblocks_in_order) + printf("Eraseblocks order of invocation for %s is CORRECT\n", + current_test_case->erase_test_name); + else + printf("Eraseblocks order of invocation for %s is WRONG\n", + current_test_case->erase_test_name); + + if (eraseblocks_invocations) + printf("Eraseblocks number of invocations for %s is CORRECT\n", + current_test_case->erase_test_name); + else + printf("Eraseblocks number of invocations for %s is WRONG, expected %d actual %d\n", + current_test_case->erase_test_name, + current_test_case->eraseblocks_expected_ind, + g_state.eraseblocks_actual_ind); + + if (chip_verified) + printf("Erased chip memory state for %s was verified successfully\n", + current_test_case->erase_test_name); + else + printf("Erased chip memory state for %s was NOT verified completely\n", + current_test_case->erase_test_name); + + all_erase_tests_result |= ret; + all_erase_tests_result |= !chip_erased; + all_erase_tests_result |= !eraseblocks_in_order; + all_erase_tests_result |= !eraseblocks_invocations; + all_erase_tests_result |= !chip_verified; + + teardown_chip(&layout); + + assert_int_equal(0, all_erase_tests_result); +} + +/* + * Runs the test cases that use protected flash regions (regions returned from + * get_flash_region() where write_prot is true) when the runtime flag to avoid + * writing to those regions is enabled. + * + * These tests verify that no protected region is written, i.e. protected region + * memory state stays untouched. + */ +static void write_unwritable_regions_skipflag_on_test_success(void **state) { + struct test_case* current_test_case = *state; + + int all_write_tests_result = 0; + struct flashrom_flashctx flashctx = { 0 }; + uint8_t newcontents[MIN_BUF_SIZE]; + uint8_t newcontents_protected[MIN_BUF_SIZE]; + const char *param = ""; /* Default values for all params. */ + + struct flashrom_layout *layout; + + const chipoff_t verify_end_boundary = setup_chip(&flashctx, &layout, param, current_test_case); + memcpy(&newcontents, current_test_case->written_buf, MOCK_CHIP_SIZE); + + // This test needs special block erase to emulate protected regions. + memcpy(g_test_erase_injector, + (erasefunc_t *const[]){ + block_erase_chip_with_protected_region_1, + block_erase_chip_with_protected_region_2, + block_erase_chip_with_protected_region_3, + block_erase_chip_with_protected_region_4, + block_erase_chip_with_protected_region_5, + }, + sizeof(g_test_erase_injector) + ); + + flashrom_flag_set(&flashctx, FLASHROM_FLAG_SKIP_UNWRITABLE_REGIONS, true); + flashrom_flag_set(&flashctx, FLASHROM_FLAG_SKIP_UNREADABLE_REGIONS, true); + flashrom_flag_set(&flashctx, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, false); + /* We need to manually trigger verify op after write, because of protected regions */ + flashrom_flag_set(&flashctx, FLASHROM_FLAG_VERIFY_AFTER_WRITE, false); + + // We use dummyflasher programmer in tests, but for this test we need to + // replace dummyflasher's default get_region fn with test one. + // The rest of master struct is fine for this test. + // Note dummyflasher registers multiple masters by default, so replace + // get_region for each of them. + flashctx.mst->spi.get_region = &get_protected_region; + flashctx.mst->opaque.get_region = &get_protected_region; + + printf("%s started.\n", current_test_case->write_test_name); + int ret = flashrom_image_write(&flashctx, &newcontents, MIN_BUF_SIZE, NULL); + printf("%s returned %d.\n", current_test_case->write_test_name, ret); + + /* Expected end result leaves protected region untouched */ + memcpy(&newcontents_protected, current_test_case->written_protected_buf, MOCK_CHIP_SIZE); + /* Outside of MOCK_CHIP_SIZE newcontents are not initialised in test cases, so just copy */ + memcpy(&newcontents_protected[MOCK_CHIP_SIZE], + &newcontents[MOCK_CHIP_SIZE], + MIN_BUF_SIZE - MOCK_CHIP_SIZE); + printf("%s verification started.\n", current_test_case->write_test_name); + ret = flashrom_image_verify(&flashctx, &newcontents_protected, MIN_BUF_SIZE); + printf("%s verification returned %d.\n", current_test_case->write_test_name, ret); + + int chip_written = !memcmp(g_state.buf, current_test_case->written_protected_buf, MOCK_CHIP_SIZE); + + int chip_verified = 1; + for (unsigned int i = 0; i <= verify_end_boundary; i++) + if (g_state.was_modified[i] && !g_state.was_verified[i]) { + chip_verified = 0; /* byte was modified, but not verified after */ + printf("Error: byte 0x%x, modified: %d, verified: %d\n", i, g_state.was_modified[i], g_state.was_verified[i]); + } + + if (chip_written) + printf("Written chip memory state for %s is CORRECT\n", + current_test_case->write_test_name); + else + printf("Written chip memory state for %s is WRONG\n", + current_test_case->write_test_name); + + if (chip_verified) + printf("Written chip memory state for %s was verified successfully\n", + current_test_case->write_test_name); + else + printf("Written chip memory state for %s was NOT verified completely\n", + current_test_case->write_test_name); + + all_write_tests_result |= ret; + all_write_tests_result |= !chip_written; + all_write_tests_result |= !chip_verified; + + teardown_chip(&layout); + + assert_int_equal(0, all_write_tests_result); +} + +static void test_erase_fails_for_unwritable_region(void **state) { + struct flashrom_flashctx flashctx = { + .chip = &chip_1_2_4_8_16, + }; + assert_int_equal(0, programmer_init(&programmer_dummy, "")); + flashctx.mst = ®istered_masters[0]; + + flashctx.mst->spi.get_region = &get_protected_region; + flashctx.mst->opaque.get_region = &get_protected_region; + flashrom_flag_set(&flashctx, FLASHROM_FLAG_SKIP_UNWRITABLE_REGIONS, false); + + /* Ask to erase one byte at the end of the unprotected region and one byte + * at the beginning of the protected one. If the check for unwritable regions + * wrongly treats the upper bound as exclusive, it will incorrectly try + * to erase inside the protected region. */ + struct flashrom_layout *layout; + flashrom_layout_new(&layout); + flashrom_layout_add_region(layout, 7, 8, "protected"); + flashrom_layout_include_region(layout, "protected"); + flashrom_layout_set(&flashctx, layout); + + int ret = flashrom_flash_erase(&flashctx); + + assert_int_equal(0, programmer_shutdown()); + flashrom_layout_release(layout); + + assert_int_not_equal(ret, 0); +} diff --git a/tests/flashrom.c b/tests/flashrom.c index cc8883132..52cc9c85a 100644 --- a/tests/flashrom.c +++ b/tests/flashrom.c @@ -13,9 +13,10 @@ * GNU General Public License for more details. */ +#include + #include #include "tests.h" - #include "programmer.h" #define assert_equal_and_free(text, expected) \ diff --git a/tests/helpers.c b/tests/helpers.c index e2e652edf..95a161994 100644 --- a/tests/helpers.c +++ b/tests/helpers.c @@ -19,6 +19,7 @@ #include "flash.h" #include +#include void address_to_bits_test_success(void **state) { @@ -45,6 +46,7 @@ void strcat_realloc_test_success(void **state) const char src0[] = "hello"; const char src1[] = " world"; char *dest = calloc(1, 1); + assert_non_null(dest); dest = strcat_realloc(dest, src0); dest = strcat_realloc(dest, src1); assert_string_equal("hello world", dest); diff --git a/tests/include/test.h b/tests/include/test.h index 88ac16d93..ef0b9a6f6 100644 --- a/tests/include/test.h +++ b/tests/include/test.h @@ -31,6 +31,9 @@ #define MOCK_FD (0x10ec) +#define SKIP_TEST(name) \ + void name (void **state) { skip(); } + /* * Having this as function allows to set a breakpoint on the address, * as it has a named symbol associated with the address number. diff --git a/tests/io_mock.c b/tests/io_mock.c index 9f86fcd67..4828e53ca 100644 --- a/tests/io_mock.c +++ b/tests/io_mock.c @@ -14,7 +14,6 @@ * GNU General Public License for more details. */ -#include #include "io_mock.h" static const struct io_mock *current_io = NULL; @@ -22,7 +21,7 @@ static const struct io_mock *current_io = NULL; void io_mock_register(const struct io_mock *io) { /* A test can either register its own mock open function or fallback_open_state. */ - assert_true(io == NULL || io->open == NULL || io->fallback_open_state == NULL); + assert_true(io == NULL || io->iom_open == NULL || io->fallback_open_state == NULL); current_io = io; } diff --git a/tests/io_mock.h b/tests/io_mock.h index 9e92a9d3e..04b0ef528 100644 --- a/tests/io_mock.h +++ b/tests/io_mock.h @@ -31,11 +31,17 @@ #ifndef _IO_MOCK_H_ #define _IO_MOCK_H_ +#include + /* Required for `FILE *` */ #include #include +/* Required for struct timeval and mode_t */ +#include +#include + #include "usb_unittests.h" /* Address value needs fit into uint8_t. */ @@ -47,11 +53,6 @@ struct pci_dev { unsigned int device_id; }; -/* POSIX open() flags, avoiding dependency on fcntl.h */ -#define O_RDONLY 0 -#define O_WRONLY 1 -#define O_RDWR 2 - /* Linux I2C interface constants, avoiding linux/i2c-dev.h */ #define I2C_SLAVE 0x0703 @@ -99,19 +100,25 @@ struct io_mock { uint8_t config_index, struct libusb_config_descriptor **); void (*libusb_free_config_descriptor)(void *state, struct libusb_config_descriptor *); + struct libusb_transfer* (*libusb_alloc_transfer)(void *state, int iso_packets); + int (*libusb_submit_transfer)(void *state, struct libusb_transfer *transfer); + void (*libusb_free_transfer)(void *state, struct libusb_transfer *transfer); + int (*libusb_handle_events_timeout)(void *state, libusb_context *ctx, struct timeval *tv); /* POSIX File I/O */ - int (*open)(void *state, const char *pathname, int flags); - int (*ioctl)(void *state, int fd, unsigned long request, va_list args); - int (*read)(void *state, int fd, void *buf, size_t sz); - int (*write)(void *state, int fd, const void *buf, size_t sz); + int (*iom_open)(void *state, const char *pathname, int flags, mode_t mode); + int (*iom_ioctl)(void *state, int fd, unsigned long request, va_list args); + int (*iom_read)(void *state, int fd, void *buf, size_t sz); + int (*iom_write)(void *state, int fd, const void *buf, size_t sz); /* Standard I/O */ - FILE* (*fopen)(void *state, const char *pathname, const char *mode); - char* (*fgets)(void *state, char *buf, int len, FILE *fp); - size_t (*fread)(void *state, void *buf, size_t size, size_t len, FILE *fp); - int (*fprintf)(void *state, FILE *fp, const char *fmt, va_list args); - int (*fclose)(void *state, FILE *fp); + FILE* (*iom_fopen)(void *state, const char *pathname, const char *mode); + char* (*iom_fgets)(void *state, char *buf, int len, FILE *fp); + size_t (*iom_fread)(void *state, void *buf, size_t size, size_t len, FILE *fp); + size_t (*iom_fwrite)(void *state, const void *buf, size_t size, size_t len, FILE *fp); + int (*iom_fprintf)(void *state, FILE *fp, const char *fmt, va_list args); + int (*iom_fclose)(void *state, FILE *fp); + FILE *(*iom_fdopen)(void *state, int fd, const char *mode); /* * An alternative to custom open mock. A test can either register its diff --git a/tests/io_real.c b/tests/io_real.c new file mode 100644 index 000000000..429027fb5 --- /dev/null +++ b/tests/io_real.c @@ -0,0 +1,78 @@ +/* + * This file is part of the flashrom project. + * + * Copyright 2022 Google LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "io_mock.h" +#include "wraps.h" + +#include "io_real.h" +#include + +static int io_real_open(void *state, const char *pathname, int flags, mode_t mode) +{ + LOG_ME; + return __real_open(pathname, flags, mode); +} + +static FILE *io_real_fopen(void *state, const char *pathname, const char *mode) +{ + LOG_ME; + return __real_fopen(pathname, mode); +} + +static FILE *io_real_fdopen(void *state, int fd, const char *mode) +{ + LOG_ME; + return __real_fdopen(fd, mode); +} + +static size_t io_real_fwrite(void *state, const void *ptr, size_t size, size_t nmemb, FILE *fp) +{ + return __real_fwrite(ptr, size, nmemb, fp); +} + +static int io_real_fclose(void *state, FILE *fp) +{ + LOG_ME; + return __real_fclose(fp); +} + +/* Mock ios that defer to the real io functions. + * These exist so that code coverage can print to real files on disk. + */ +static const struct io_mock real_io = { + .iom_open = io_real_open, + .iom_fopen = io_real_fopen, + .iom_fwrite = io_real_fwrite, + .iom_fdopen = io_real_fdopen, + .iom_fclose = io_real_fclose, +}; + +/* Return 0 if string ends with suffix. */ +static int check_suffix(const char *string, const char *suffix) +{ + int len_l = strlen(string); + int len_r = strlen(suffix); + if (len_l > len_r) + return strcmp(string + len_l - len_r, suffix); + return 1; +} + +void maybe_unmock_io(const char *pathname) +{ + const char *gcov_suffix = ".gcda"; + const char *llvm_cov_suffix = ".profraw"; + if (!check_suffix(pathname, gcov_suffix) || !check_suffix(pathname, llvm_cov_suffix)) + io_mock_register(&real_io); +} diff --git a/tests/io_real.h b/tests/io_real.h new file mode 100644 index 000000000..f2491c3ab --- /dev/null +++ b/tests/io_real.h @@ -0,0 +1,24 @@ +/* + * This file is part of the flashrom project. + * + * Copyright 2022 Google LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef IO_REAL_H +#define IO_REAL_H + +/* Detect file io that should not be mocked, for example code coverage writing + * gcda files. Call io_mock_register with functions that defer to real io. + */ +void maybe_unmock_io(const char* pathname); + +#endif /* IO_REAL_H */ diff --git a/tests/layout.c b/tests/layout.c index e71debfe2..917d77e24 100644 --- a/tests/layout.c +++ b/tests/layout.c @@ -110,6 +110,8 @@ void layout_pass_sanity_checks_test_success(void **state) unsigned int region_start = 0x00021000; unsigned int region_end = 0x00031000; + unsigned int region2_start = 0x00041000; + unsigned int region2_end = 0x00051000; unsigned int start = 0; unsigned int len = 0; @@ -119,6 +121,9 @@ void layout_pass_sanity_checks_test_success(void **state) assert_int_equal(0, flashrom_layout_new(&layout)); assert_int_equal(0, flashrom_layout_add_region(layout, region_start, region_end, "region")); assert_int_equal(0, flashrom_layout_include_region(layout, "region")); + assert_int_equal(0, flashrom_layout_add_region(layout, region2_start, region2_end, "region2")); + assert_int_equal(0, flashrom_layout_include_region(layout, "region2")); + assert_int_equal(0, flashrom_layout_exclude_region(layout, "region2")); printf("done\n"); printf("Asserting region range... "); diff --git a/tests/libusb_wraps.c b/tests/libusb_wraps.c index 85bb963bc..be990a12c 100644 --- a/tests/libusb_wraps.c +++ b/tests/libusb_wraps.c @@ -34,6 +34,17 @@ int __wrap_libusb_init(libusb_context **ctx) return 0; } +void __wrap_libusb_set_debug(libusb_context *ctx, int level) +{ + LOG_ME; +} + +int __wrap_libusb_set_option(libusb_context *ctx, int option, ...) +{ + LOG_ME; + return 0; +} + int __wrap_libusb_open(libusb_device *dev, libusb_device_handle **devh) { LOG_ME; @@ -58,6 +69,19 @@ int __wrap_libusb_attach_kernel_driver(libusb_device_handle *dev_handle, int int return 0; } +struct libusb_device_handle *__wrap_libusb_open_device_with_vid_pid( + libusb_context *ctx, uint16_t vendor_id, uint16_t product_id) +{ + LOG_ME; + return not_null(); +} + +libusb_device *__wrap_libusb_get_device(libusb_device_handle *dev_handle) +{ + LOG_ME; + return not_null(); +} + ssize_t __wrap_libusb_get_device_list(libusb_context *ctx, libusb_device ***list) { LOG_ME; @@ -161,6 +185,37 @@ void __wrap_libusb_unref_device(libusb_device *dev) LOG_ME; } +struct libusb_transfer *__wrap_libusb_alloc_transfer(int iso_packets) +{ + LOG_ME; + if (get_io() && get_io()->libusb_alloc_transfer) + return get_io()->libusb_alloc_transfer(get_io()->state, iso_packets); + return not_null(); +} + +int __wrap_libusb_submit_transfer(struct libusb_transfer *transfer) +{ + LOG_ME; + if (get_io() && get_io()->libusb_submit_transfer) + return get_io()->libusb_submit_transfer(get_io()->state, transfer); + return 0; +} + +void __wrap_libusb_free_transfer(struct libusb_transfer *transfer) +{ + LOG_ME; + if (get_io() && get_io()->libusb_free_transfer) + get_io()->libusb_free_transfer(get_io()->state, transfer); +} + +int __wrap_libusb_handle_events_timeout(libusb_context *ctx, struct timeval *tv) +{ + LOG_ME; + if (get_io() && get_io()->libusb_handle_events_timeout) + get_io()->libusb_handle_events_timeout(get_io()->state, ctx, tv); + return 0; +} + void __wrap_libusb_exit(libusb_context *ctx) { LOG_ME; diff --git a/tests/libusb_wraps.h b/tests/libusb_wraps.h index f7e4dafe0..8c3aa40a1 100644 --- a/tests/libusb_wraps.h +++ b/tests/libusb_wraps.h @@ -21,10 +21,15 @@ void *__wrap_usb_dev_get_by_vid_pid_number( libusb_context *usb_ctx, uint16_t vid, uint16_t pid, unsigned int num); int __wrap_libusb_init(libusb_context **ctx); +void __wrap_libusb_set_debug(libusb_context *ctx, int level); +int __wrap_libusb_set_option(libusb_context *ctx, int option, ...); int __wrap_libusb_open(libusb_device *dev, libusb_device_handle **devh); int __wrap_libusb_set_auto_detach_kernel_driver(libusb_device_handle *devh, int enable); int __wrap_libusb_detach_kernel_driver(libusb_device_handle *dev_handle, int interface_number); int __wrap_libusb_attach_kernel_driver(libusb_device_handle *dev_handle, int interface_number); +struct libusb_device_handle *__wrap_libusb_open_device_with_vid_pid( + libusb_context *ctx, uint16_t vendor_id, uint16_t product_id); +libusb_device *__wrap_libusb_get_device(libusb_device_handle *dev_handle); ssize_t __wrap_libusb_get_device_list(libusb_context *ctx, libusb_device ***list); void __wrap_libusb_free_device_list(libusb_device **list, int unref_devices); uint8_t __wrap_libusb_get_bus_number(libusb_device *dev); @@ -43,6 +48,10 @@ int __wrap_libusb_release_interface(libusb_device_handle *devh, int interface_nu void __wrap_libusb_close(libusb_device_handle *devh); libusb_device *__wrap_libusb_ref_device(libusb_device *dev); void __wrap_libusb_unref_device(libusb_device *dev); +struct libusb_transfer *__wrap_libusb_alloc_transfer(int iso_packets); +int __wrap_libusb_submit_transfer(struct libusb_transfer *transfer); +void __wrap_libusb_free_transfer(struct libusb_transfer *transfer); +int __wrap_libusb_handle_events_timeout(libusb_context *ctx, struct timeval *tv); void __wrap_libusb_exit(libusb_context *ctx); #endif /* LIBUSB_WRAPS_H */ diff --git a/tests/lifecycle.c b/tests/lifecycle.c index 0c7969920..95c424969 100644 --- a/tests/lifecycle.c +++ b/tests/lifecycle.c @@ -40,10 +40,8 @@ static void run_lifecycle(void **state, const struct io_mock *io, const struct p struct flashrom_programmer *flashprog; - char *param_dup = param ? strdup(param) : NULL; - printf("Testing flashrom_programmer_init for programmer=%s ...\n", prog->name); - assert_int_equal(0, flashrom_programmer_init(&flashprog, prog->name, param_dup)); + assert_int_equal(0, flashrom_programmer_init(&flashprog, prog->name, param)); printf("... flashrom_programmer_init for programmer=%s successful\n", prog->name); if (action) @@ -53,8 +51,6 @@ static void run_lifecycle(void **state, const struct io_mock *io, const struct p assert_int_equal(0, flashrom_programmer_shutdown(flashprog)); printf("... flashrom_programmer_shutdown for programmer=%s successful\n", prog->name); - free(param_dup); - io_mock_register(NULL); } @@ -82,10 +78,9 @@ void run_init_error_path(void **state, const struct io_mock *io, const struct pr io_mock_register(io); struct flashrom_programmer *flashprog; - char *param_dup = strdup(param); - printf("Testing init error path for programmer=%s with params: %s ...\n", prog->name, param_dup); - assert_int_equal(error_code, flashrom_programmer_init(&flashprog, prog->name, param_dup)); + printf("Testing init error path for programmer=%s with params: %s ...\n", prog->name, param); + assert_int_equal(error_code, flashrom_programmer_init(&flashprog, prog->name, param)); printf("... init failed with error code %i as expected\n", error_code); /* @@ -99,7 +94,5 @@ void run_init_error_path(void **state, const struct io_mock *io, const struct pr assert_int_equal(0, flashrom_programmer_shutdown(flashprog)); printf("... completed\n"); - free(param_dup); - io_mock_register(NULL); } diff --git a/tests/lifecycle.h b/tests/lifecycle.h index 69f111969..b4c2fbedd 100644 --- a/tests/lifecycle.h +++ b/tests/lifecycle.h @@ -28,9 +28,6 @@ #include "programmer.h" #include "spi.h" -#define SKIP_TEST(name) \ - void name (void **state) { skip(); } - void run_basic_lifecycle(void **state, const struct io_mock *io, const struct programmer_entry *prog, const char *param); diff --git a/tests/linux_mtd.c b/tests/linux_mtd.c index 10ccb5eb8..0cee7857c 100644 --- a/tests/linux_mtd.c +++ b/tests/linux_mtd.c @@ -13,6 +13,8 @@ * GNU General Public License for more details. */ +#include + #include "lifecycle.h" #if CONFIG_LINUX_MTD == 1 @@ -81,9 +83,9 @@ void linux_mtd_probe_lifecycle_test_success(void **state) }; const struct io_mock linux_mtd_io = { .state = &linux_mtd_io_state, - .fopen = linux_mtd_fopen, - .fread = linux_mtd_fread, - .fclose = linux_mtd_fclose, + .iom_fopen = linux_mtd_fopen, + .iom_fread = linux_mtd_fread, + .iom_fclose = linux_mtd_fclose, .fallback_open_state = &linux_mtd_fallback_open_state, }; diff --git a/tests/linux_spi.c b/tests/linux_spi.c index 2e3dc95f4..1b653fefd 100644 --- a/tests/linux_spi.c +++ b/tests/linux_spi.c @@ -23,14 +23,14 @@ static int linux_spi_ioctl(void *state, int fd, unsigned long request, va_list a /* First message has write array and write count */ unsigned int writecnt = msg[0].len; - unsigned char *writearr = (unsigned char *)msg[0].tx_buf; + unsigned char *writearr = (unsigned char *)(uintptr_t)msg[0].tx_buf; /* Second message has read array and read count */ unsigned int readcnt = msg[1].len; /* Detect probing */ if (writecnt == 1 && writearr[0] == JEDEC_RDID && readcnt == 3) { /* We need to populate read array. */ - unsigned char *readarr = (unsigned char *)msg[1].rx_buf; + unsigned char *readarr = (unsigned char *)(uintptr_t)msg[1].rx_buf; readarr[0] = 0xEF; /* WINBOND_NEX_ID */ readarr[1] = 0x40; /* WINBOND_NEX_W25Q128_V left byte */ readarr[2] = 0x18; /* WINBOND_NEX_W25Q128_V right byte */ @@ -60,8 +60,8 @@ void linux_spi_probe_lifecycle_test_success(void **state) .flags = { O_RDWR }, }; const struct io_mock linux_spi_io = { - .fgets = linux_spi_fgets, - .ioctl = linux_spi_ioctl, + .iom_fgets = linux_spi_fgets, + .iom_ioctl = linux_spi_ioctl, .fallback_open_state = &linux_spi_fallback_open_state, }; diff --git a/tests/meson.build b/tests/meson.build index e4f7c2aa2..e788b8081 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -11,7 +11,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -srcs = [ +test_srcs = files( 'io_mock.c', 'tests.c', 'libusb_wraps.c', @@ -19,24 +19,23 @@ srcs = [ 'flashrom.c', 'spi25.c', 'lifecycle.c', - 'dummyflasher.c', - 'nicrealtek.c', - 'raiden_debug_spi.c', - 'dediprog.c', - 'linux_mtd.c', - 'linux_spi.c', - 'parade_lspcon.c', - 'mediatek_i2c_spi.c', - 'realtek_mst_i2c_spi.c', 'layout.c', 'chip.c', 'chip_wp.c', -] + 'selfcheck.c', + 'io_real.c', + 'erase_func_algo.c', + 'udelay.c', +) if not programmer.get('dummy').get('active') - srcs += programmer.get('dummy').get('srcs') + test_srcs += programmer.get('dummy').get('srcs') endif +foreach p_name, p_data : programmer + test_srcs += p_data.get('test_srcs') +endforeach + mocks = [ '-Wl,--wrap=strdup', '-Wl,--wrap=physunmap', @@ -63,15 +62,14 @@ mocks = [ '-Wl,--wrap=__xstat64', '-Wl,--wrap=fstat', '-Wl,--wrap=fstat64', + '-Wl,--wrap=__fstat50', '-Wl,--wrap=__fxstat', '-Wl,--wrap=__fxstat64', '-Wl,--wrap=fileno', '-Wl,--wrap=fsync', '-Wl,--wrap=fread', '-Wl,--wrap=fgets', - '-Wl,--wrap=__fgets_chk', '-Wl,--wrap=fprintf', - '-Wl,--wrap=__vfprintf_chk', '-Wl,--wrap=fclose', '-Wl,--wrap=feof', '-Wl,--wrap=ferror', @@ -86,10 +84,14 @@ mocks = [ '-Wl,--wrap=INL', '-Wl,--wrap=usb_dev_get_by_vid_pid_number', '-Wl,--wrap=libusb_init', + '-Wl,--wrap=libusb_set_debug', + '-Wl,--wrap=libusb_set_option', '-Wl,--wrap=libusb_open', '-Wl,--wrap=libusb_set_auto_detach_kernel_driver', '-Wl,--wrap=libusb_detach_kernel_driver', '-Wl,--wrap=libusb_attach_kernel_driver', + '-Wl,--wrap=libusb_open_device_with_vid_pid', + '-Wl,--wrap=libusb_get_device', '-Wl,--wrap=libusb_get_device_list', '-Wl,--wrap=libusb_free_device_list', '-Wl,--wrap=libusb_get_bus_number', @@ -105,19 +107,31 @@ mocks = [ '-Wl,--wrap=libusb_ref_device', '-Wl,--wrap=libusb_unref_device', '-Wl,--wrap=libusb_close', + '-Wl,--wrap=libusb_alloc_transfer', + '-Wl,--wrap=libusb_submit_transfer', + '-Wl,--wrap=libusb_free_transfer', + '-Wl,--wrap=libusb_handle_events_timeout', '-Wl,--wrap=libusb_exit', '-Wl,--gc-sections', ] +threads_dep = dependency('threads') + flashrom_tests = executable('flashrom_unit_tests', - srcs, + test_srcs, c_args : [ cargs, '-ffunction-sections', '-fdata-sections', + '-U_FORTIFY_SOURCE', + '-DFLASHROM_TEST', ], export_dynamic : true, - link_args : mocks, - dependencies : [cmocka_dep, flashrom_test_dep], + link_args : mocks + link_args, + dependencies : [cmocka_dep, flashrom_test_dep, threads_dep], ) test('cmocka test flashrom', flashrom_tests) + +if get_option('llvm_cov').enabled() + run_target('llvm-cov-tests', command : ['../scripts/llvm-cov', flashrom_tests]) +endif diff --git a/tests/parade_lspcon.c b/tests/parade_lspcon.c index 9d7bd2305..980e1280d 100644 --- a/tests/parade_lspcon.c +++ b/tests/parade_lspcon.c @@ -108,9 +108,9 @@ void parade_lspcon_basic_lifecycle_test_success(void **state) }; const struct io_mock parade_lspcon_io = { .state = ¶de_lspcon_io_state, - .ioctl = parade_lspcon_ioctl, - .read = parade_lspcon_read, - .write = parade_lspcon_write, + .iom_ioctl = parade_lspcon_ioctl, + .iom_read = parade_lspcon_read, + .iom_write = parade_lspcon_write, .fallback_open_state = ¶de_lspcon_fallback_open_state, }; diff --git a/tests/raiden_debug_spi.c b/tests/raiden_debug_spi.c index f5bf185a2..8ec0617dc 100644 --- a/tests/raiden_debug_spi.c +++ b/tests/raiden_debug_spi.c @@ -13,12 +13,15 @@ * GNU General Public License for more details. */ +#include + #include "lifecycle.h" #if CONFIG_RAIDEN_DEBUG_SPI == 1 static ssize_t raiden_debug_libusb_get_device_list(void *state, libusb_context *ctx, libusb_device ***list) { *list = calloc(1, sizeof(**list)); + assert_non_null(*list); /* * libusb_device is opaque type, it is tossed around between libusb functions but always @@ -48,10 +51,14 @@ static int raiden_debug_libusb_get_config_descriptor( void *state, libusb_device *dev, uint8_t config_index, struct libusb_config_descriptor **config) { *config = calloc(1, sizeof(**config)); + assert_non_null(*config); struct libusb_endpoint_descriptor *tmp_endpoint = calloc(2, sizeof(*tmp_endpoint)); + assert_non_null(tmp_endpoint); struct libusb_interface_descriptor *tmp_interface_desc = calloc(1, sizeof(*tmp_interface_desc)); + assert_non_null(tmp_interface_desc); struct libusb_interface *tmp_interface = calloc(1, sizeof(*tmp_interface)); + assert_non_null(tmp_interface); /* in endpoint */ tmp_endpoint[0].bEndpointAddress = 0x80; @@ -99,15 +106,100 @@ void raiden_debug_basic_lifecycle_test_success(void **state) .fallback_open_state = &raiden_debug_fallback_open_state, }; - /* - * 12 is the length of programmer param string for 3-digit address. - * Address can be max 3-digit because it needs to fit into uint8_t. - */ - char raiden_debug_param[12]; - snprintf(raiden_debug_param, 12, "address=%d", USB_DEVICE_ADDRESS); + char raiden_debug_param[32]; + + snprintf(raiden_debug_param, sizeof(raiden_debug_param), + "address=%d", USB_DEVICE_ADDRESS); + run_basic_lifecycle(state, &raiden_debug_io, &programmer_raiden_debug_spi, raiden_debug_param); +} + +void raiden_debug_targetAP_basic_lifecycle_test_success(void **state) +{ + struct io_mock_fallback_open_state raiden_debug_fallback_open_state = { + .noc = 0, + .paths = { NULL }, + }; + const struct io_mock raiden_debug_io = { + .libusb_get_device_list = raiden_debug_libusb_get_device_list, + .libusb_free_device_list = raiden_debug_libusb_free_device_list, + .libusb_get_device_descriptor = raiden_debug_libusb_get_device_descriptor, + .libusb_get_config_descriptor = raiden_debug_libusb_get_config_descriptor, + .libusb_free_config_descriptor = raiden_debug_libusb_free_config_descriptor, + .fallback_open_state = &raiden_debug_fallback_open_state, + }; + + char raiden_debug_param[32]; + snprintf(raiden_debug_param, sizeof(raiden_debug_param), + "address=%d,target=AP", USB_DEVICE_ADDRESS); + run_basic_lifecycle(state, &raiden_debug_io, &programmer_raiden_debug_spi, raiden_debug_param); +} + +void raiden_debug_targetEC_basic_lifecycle_test_success(void **state) +{ + struct io_mock_fallback_open_state raiden_debug_fallback_open_state = { + .noc = 0, + .paths = { NULL }, + }; + const struct io_mock raiden_debug_io = { + .libusb_get_device_list = raiden_debug_libusb_get_device_list, + .libusb_free_device_list = raiden_debug_libusb_free_device_list, + .libusb_get_device_descriptor = raiden_debug_libusb_get_device_descriptor, + .libusb_get_config_descriptor = raiden_debug_libusb_get_config_descriptor, + .libusb_free_config_descriptor = raiden_debug_libusb_free_config_descriptor, + .fallback_open_state = &raiden_debug_fallback_open_state, + }; + + char raiden_debug_param[32]; + snprintf(raiden_debug_param, sizeof(raiden_debug_param), + "address=%d,target=ec", USB_DEVICE_ADDRESS); + run_basic_lifecycle(state, &raiden_debug_io, &programmer_raiden_debug_spi, raiden_debug_param); +} + +void raiden_debug_target0_basic_lifecycle_test_success(void **state) +{ + struct io_mock_fallback_open_state raiden_debug_fallback_open_state = { + .noc = 0, + .paths = { NULL }, + }; + const struct io_mock raiden_debug_io = { + .libusb_get_device_list = raiden_debug_libusb_get_device_list, + .libusb_free_device_list = raiden_debug_libusb_free_device_list, + .libusb_get_device_descriptor = raiden_debug_libusb_get_device_descriptor, + .libusb_get_config_descriptor = raiden_debug_libusb_get_config_descriptor, + .libusb_free_config_descriptor = raiden_debug_libusb_free_config_descriptor, + .fallback_open_state = &raiden_debug_fallback_open_state, + }; + + char raiden_debug_param[32]; + snprintf(raiden_debug_param, sizeof(raiden_debug_param), + "address=%d,target=0", USB_DEVICE_ADDRESS); + run_basic_lifecycle(state, &raiden_debug_io, &programmer_raiden_debug_spi, raiden_debug_param); +} + +void raiden_debug_target1_basic_lifecycle_test_success(void **state) +{ + struct io_mock_fallback_open_state raiden_debug_fallback_open_state = { + .noc = 0, + .paths = { NULL }, + }; + const struct io_mock raiden_debug_io = { + .libusb_get_device_list = raiden_debug_libusb_get_device_list, + .libusb_free_device_list = raiden_debug_libusb_free_device_list, + .libusb_get_device_descriptor = raiden_debug_libusb_get_device_descriptor, + .libusb_get_config_descriptor = raiden_debug_libusb_get_config_descriptor, + .libusb_free_config_descriptor = raiden_debug_libusb_free_config_descriptor, + .fallback_open_state = &raiden_debug_fallback_open_state, + }; + char raiden_debug_param[32]; + snprintf(raiden_debug_param, sizeof(raiden_debug_param), + "address=%d,target=1", USB_DEVICE_ADDRESS); run_basic_lifecycle(state, &raiden_debug_io, &programmer_raiden_debug_spi, raiden_debug_param); } #else SKIP_TEST(raiden_debug_basic_lifecycle_test_success) + SKIP_TEST(raiden_debug_targetAP_basic_lifecycle_test_success) + SKIP_TEST(raiden_debug_targetEC_basic_lifecycle_test_success) + SKIP_TEST(raiden_debug_target0_basic_lifecycle_test_success) + SKIP_TEST(raiden_debug_target1_basic_lifecycle_test_success) #endif /* CONFIG_RAIDEN_DEBUG_SPI */ diff --git a/tests/realtek_mst_i2c_spi.c b/tests/realtek_mst_i2c_spi.c index 0526124df..753f06b91 100644 --- a/tests/realtek_mst_i2c_spi.c +++ b/tests/realtek_mst_i2c_spi.c @@ -50,9 +50,9 @@ void realtek_mst_basic_lifecycle_test_success(void **state) .flags = { O_RDWR }, }; const struct io_mock realtek_mst_io = { - .ioctl = realtek_mst_ioctl, - .read = realtek_mst_read, - .write = realtek_mst_write, + .iom_ioctl = realtek_mst_ioctl, + .iom_read = realtek_mst_read, + .iom_write = realtek_mst_write, .fallback_open_state = &realtek_mst_fallback_open_state, }; diff --git a/tests/selfcheck.c b/tests/selfcheck.c new file mode 100644 index 000000000..e235d8ef0 --- /dev/null +++ b/tests/selfcheck.c @@ -0,0 +1,156 @@ +/* + * This file is part of the flashrom project. + * + * Copyright 2022 Google LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "flash.h" +#include "string.h" + +#include "include/test.h" +#include "programmer.h" +#include "tests.h" +#include + + +#define assert_table(assertion, message, index, name) \ + do { \ + if (!(assertion)) \ + fail_msg(message " for index:%zu name:%s", (index), (name) ? (name) : "unknown"); \ + } while (0) + + +void selfcheck_programmer_table(void **state) +{ + (void)state; /* unused */ + + size_t i; + for (i = 0; i < programmer_table_size; i++) { + const struct programmer_entry *const p = programmer_table[i]; + assert_table(p, "programmer entry is null", i, "unknown"); + assert_table(p->name, "programmer name is null", i, p->name); + bool type_good = false; + switch (p->type) { + case PCI: + case USB: + case OTHER: + type_good = true; + } + assert_table(type_good, "programmer type is invalid", i, p->name); + /* internal has its device list stored separately. */ + if (strcmp("internal", p->name) != 0) + assert_table(p->devs.note, "programmer devs.note is null", i, p->name); + assert_table(p->init, "programmer init is null", i, p->name); + } +} + +void selfcheck_flashchips_table(void **state) +{ + (void)state; /* unused */ + + size_t i; + assert_true(flashchips_size > 1); + assert_true(flashchips[flashchips_size - 1].name == NULL); + for (i = 0; i < flashchips_size - 1; i++) { + const struct flashchip *chip = &flashchips[i]; + assert_table(chip->vendor, "chip vendor is null", i, chip->name); + assert_table(chip->name, "chip name is null", i, chip->name); + assert_table(chip->bustype != BUS_NONE, "chip bustype is BUS_NONE", i, chip->name); + } +} + +void selfcheck_eraseblocks(void **state) +{ + (void)state; /* unused */ + + size_t chip_index; + for (chip_index = 0; chip_index < flashchips_size - 1; chip_index++) { + size_t i, j, k; + const struct flashchip *chip = &flashchips[chip_index]; + unsigned int prev_eraseblock_count = chip->total_size * 1024; + + for (k = 0; k < NUM_ERASEFUNCTIONS; k++) { + unsigned int done = 0; + struct block_eraser eraser = chip->block_erasers[k]; + unsigned int curr_eraseblock_count = 0; + + for (i = 0; i < NUM_ERASEREGIONS; i++) { + /* Blocks with zero size are bugs in flashchips.c. */ + if (eraser.eraseblocks[i].count && !eraser.eraseblocks[i].size) { + fail_msg("Flash chip %s erase function %zu region %zu has size 0", + chip->name, k, i); + } + /* Blocks with zero count are bugs in flashchips.c. */ + if (!eraser.eraseblocks[i].count && eraser.eraseblocks[i].size) { + fail_msg("Flash chip %s erase function %zu region %zu has count 0", + chip->name, k, i); + } + done += eraser.eraseblocks[i].count * eraser.eraseblocks[i].size; + curr_eraseblock_count += eraser.eraseblocks[i].count; + } + /* Empty eraseblock definition with erase function. */ + if (!done && eraser.block_erase) { + printf("Strange: Empty eraseblock definition with non-empty erase function chip %s function %zu. Not an error.\n", + chip->name, k); + } + + if (!done) + continue; + if (done != chip->total_size * 1024) { + fail_msg( + "Flash chip %s erase function %zu region walking resulted in 0x%06x bytes total, expected 0x%06x bytes.", + chip->name, k, done, chip->total_size * 1024); + assert_true(false); + } + + if (!eraser.block_erase) + continue; + /* Check if there are identical erase functions for different + * layouts. That would imply "magic" erase functions. The + * easiest way to check this is with function pointers. + */ + for (j = k + 1; j < NUM_ERASEFUNCTIONS; j++) { + if (eraser.block_erase == chip->block_erasers[j].block_erase) { + fail_msg("Flash chip %s erase function %zu and %zu are identical.", + chip->name, k, j); + } + } + if (curr_eraseblock_count > prev_eraseblock_count) { + fail_msg("Flash chip %s erase function %zu is not in order", chip->name, k); + } + prev_eraseblock_count = curr_eraseblock_count; + } + } +} + +#if CONFIG_INTERNAL == 1 +void selfcheck_board_matches_table(void **state) +{ + (void)state; /* unused */ + + size_t i; + + assert_true(board_matches_size > 0); + assert_true(board_matches[board_matches_size - 1].vendor_name == NULL); + for (i = 0; i < board_matches_size - 1; i++) { + const struct board_match *b = &board_matches[i]; + assert_table(b->vendor_name, "board vendor_name is null", i, b->board_name); + assert_table(b->board_name, "board boad_name is null", i, b->board_name); + if ((!b->first_vendor || !b->first_device || !b->second_vendor || !b->second_device) + || ((!b->lb_vendor) ^ (!b->lb_part)) || (!b->max_rom_decode_parallel && !b->enable)) + fail_msg("Board enable for %s %s is misdefined.\n", b->vendor_name, b->board_name); + } +} + +#else + SKIP_TEST(selfcheck_board_matches_table) +#endif /* CONFIG_INTERNAL */ diff --git a/tests/spi25.c b/tests/spi25.c index f10191040..872959341 100644 --- a/tests/spi25.c +++ b/tests/spi25.c @@ -31,8 +31,8 @@ struct flashchip mock_chip = { .total_size = 0, .page_size = 256, .tested = TEST_BAD_PREW, - .probe = probe_spi_rdid, - .write = NULL, + .probe = PROBE_SPI_RDID, + .write = NO_WRITE_FUNC, }; /* diff --git a/tests/tests.c b/tests/tests.c index 53bad6569..3fee05681 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -17,10 +17,13 @@ #include "io_mock.h" #include "tests.h" #include "wraps.h" +#include "io_real.h" #include +#include #include #include +#include void *not_null(void) { @@ -75,10 +78,11 @@ uint8_t __wrap_sio_read(uint16_t port, uint8_t reg) return (uint8_t)mock(); } -static int mock_open(const char *pathname, int flags) +static int mock_open(const char *pathname, int flags, mode_t mode) { - if (get_io() && get_io()->open) - return get_io()->open(get_io()->state, pathname, flags); + maybe_unmock_io(pathname); + if (get_io() && get_io()->iom_open) + return get_io()->iom_open(get_io()->state, pathname, flags, mode); if (get_io() && get_io()->fallback_open_state) { struct io_mock_fallback_open_state *io_state; @@ -96,32 +100,53 @@ static int mock_open(const char *pathname, int flags) return MOCK_FD; } -int __wrap_open(const char *pathname, int flags) +int __wrap_open(const char *pathname, int flags, ...) { LOG_ME; - return mock_open(pathname, flags); + int mode = 0; + if (flags & O_CREAT) { + va_list ap; + va_start(ap, flags); + mode = va_arg(ap, int); + va_end(ap); + } + return mock_open(pathname, flags, (mode_t) mode); } -int __wrap_open64(const char *pathname, int flags) +int __wrap_open64(const char *pathname, int flags, ...) { LOG_ME; - return mock_open(pathname, flags); + int mode = 0; + if (flags & O_CREAT) { + va_list ap; + va_start(ap, flags); + mode = va_arg(ap, int); + va_end(ap); + } + return mock_open(pathname, flags, (mode_t) mode); } -int __wrap___open64_2(const char *pathname, int flags) +int __wrap___open64_2(const char *pathname, int flags, ...) { LOG_ME; - return mock_open(pathname, flags); + int mode = 0; + if (flags & O_CREAT) { + va_list ap; + va_start(ap, flags); + mode = va_arg(ap, int); + va_end(ap); + } + return mock_open(pathname, flags, (mode_t) mode); } int __wrap_ioctl(int fd, unsigned long int request, ...) { LOG_ME; - if (get_io() && get_io()->ioctl) { + if (get_io() && get_io()->iom_ioctl) { va_list args; int out; va_start(args, request); - out = get_io()->ioctl(get_io()->state, fd, request, args); + out = get_io()->iom_ioctl(get_io()->state, fd, request, args); va_end(args); return out; } @@ -131,38 +156,42 @@ int __wrap_ioctl(int fd, unsigned long int request, ...) int __wrap_write(int fd, const void *buf, size_t sz) { LOG_ME; - if (get_io() && get_io()->write) - return get_io()->write(get_io()->state, fd, buf, sz); + if (get_io() && get_io()->iom_write) + return get_io()->iom_write(get_io()->state, fd, buf, sz); return sz; } int __wrap_read(int fd, void *buf, size_t sz) { LOG_ME; - if (get_io() && get_io()->read) - return get_io()->read(get_io()->state, fd, buf, sz); + if (get_io() && get_io()->iom_read) + return get_io()->iom_read(get_io()->state, fd, buf, sz); return sz; } FILE *__wrap_fopen(const char *pathname, const char *mode) { LOG_ME; - if (get_io() && get_io()->fopen) - return get_io()->fopen(get_io()->state, pathname, mode); + maybe_unmock_io(pathname); + if (get_io() && get_io()->iom_fopen) + return get_io()->iom_fopen(get_io()->state, pathname, mode); return not_null(); } FILE *__wrap_fopen64(const char *pathname, const char *mode) { LOG_ME; - if (get_io() && get_io()->fopen) - return get_io()->fopen(get_io()->state, pathname, mode); + maybe_unmock_io(pathname); + if (get_io() && get_io()->iom_fopen) + return get_io()->iom_fopen(get_io()->state, pathname, mode); return not_null(); } FILE *__wrap_fdopen(int fd, const char *mode) { LOG_ME; + if (get_io() && get_io()->iom_fdopen) + return get_io()->iom_fdopen(get_io()->state, fd, mode); return not_null(); } @@ -202,45 +231,45 @@ int __wrap_fstat64(int fd, void *buf) return 0; } -int __wrap___fxstat(int fd, void *buf) +int __wrap___fstat50(int fd, void *buf) { LOG_ME; return 0; } -int __wrap___fxstat64(int fd, void *buf) +int __wrap___fxstat(int fd, void *buf) { LOG_ME; return 0; } -char *__wrap_fgets(char *buf, int len, FILE *fp) +int __wrap___fxstat64(int fd, void *buf) { LOG_ME; - if (get_io() && get_io()->fgets) - return get_io()->fgets(get_io()->state, buf, len, fp); - return NULL; + return 0; } -char *__wrap___fgets_chk(char *buf, int len, FILE *fp) +char *__wrap_fgets(char *buf, int len, FILE *fp) { LOG_ME; - if (get_io() && get_io()->fgets) - return get_io()->fgets(get_io()->state, buf, len, fp); + if (get_io() && get_io()->iom_fgets) + return get_io()->iom_fgets(get_io()->state, buf, len, fp); return NULL; } size_t __wrap_fread(void *ptr, size_t size, size_t nmemb, FILE *fp) { LOG_ME; - if (get_io() && get_io()->fread) - return get_io()->fread(get_io()->state, ptr, size, nmemb, fp); + if (get_io() && get_io()->iom_fread) + return get_io()->iom_fread(get_io()->state, ptr, size, nmemb, fp); return nmemb; } size_t __wrap_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp) { LOG_ME; + if (get_io() && get_io()->iom_fwrite) + return get_io()->iom_fwrite(get_io()->state, ptr, size, nmemb, fp); return nmemb; } @@ -271,30 +300,22 @@ int __wrap_setvbuf(FILE *fp, char *buf, int type, size_t size) int __wrap_fprintf(FILE *fp, const char *fmt, ...) { LOG_ME; - if (get_io() && get_io()->fprintf) { + if (get_io() && get_io()->iom_fprintf) { va_list args; int out; va_start(args, fmt); - out = get_io()->fprintf(get_io()->state, fp, fmt, args); + out = get_io()->iom_fprintf(get_io()->state, fp, fmt, args); va_end(args); return out; } return 0; } -int __wrap___vfprintf_chk(FILE *fp, const char *fmt, va_list args) -{ - LOG_ME; - if (get_io() && get_io()->fprintf) - return get_io()->fprintf(get_io()->state, fp, fmt, args); - return 0; -} - int __wrap_fclose(FILE *fp) { LOG_ME; - if (get_io() && get_io()->fclose) - return get_io()->fclose(get_io()->state, fp); + if (get_io() && get_io()->iom_fclose) + return get_io()->iom_fclose(get_io()->state, fp); return 0; } @@ -366,26 +387,32 @@ unsigned int __wrap_INL(unsigned short port) return 0; } +static void *doing_nothing(void *vargp) { + return NULL; +} + int main(int argc, char *argv[]) { int ret = 0; -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - /* - * Pretending to be a multithreaded environment so that `fileno` - * is called as a function (and not as a macro). - * fileno macro in FreeBSD is expanded into inline access of - * private field of file descriptor, which is impossible to mock. - * Calling fileno as a function allows the test to mock it. - */ - __isthreaded = 1; -#endif - if (argc > 1) cmocka_set_test_filter(argv[1]); cmocka_set_message_output(CM_OUTPUT_STDOUT); + /* + * Creating new thread which is doing nothing, to trigger __isthreaded being 1. + * This is a workaround for BSD family. In multi-threaded environment fileno + * macro is expanded into a function which is possible to mock in unit tests. + * Without this workaround, on a single-thread environment, fileno macro is + * expanded into an inline access of a private field of a file descriptor, + * which is impossible to mock. + * + * In other OSes this is just creating a thread which is doing nothing. + */ + pthread_t thread_id; + pthread_create(&thread_id, NULL, doing_nothing, NULL); + const struct CMUnitTest helpers_tests[] = { cmocka_unit_test(address_to_bits_test_success), cmocka_unit_test(bitcount_test_success), @@ -397,6 +424,15 @@ int main(int argc, char *argv[]) }; ret |= cmocka_run_group_tests_name("helpers.c tests", helpers_tests, NULL, NULL); + const struct CMUnitTest selfcheck[] = { + cmocka_unit_test(selfcheck_programmer_table), + cmocka_unit_test(selfcheck_flashchips_table), + cmocka_unit_test(selfcheck_eraseblocks), + cmocka_unit_test(selfcheck_board_matches_table), + }; + ret |= cmocka_run_group_tests_name("selfcheck.c tests", selfcheck, + NULL, NULL); + const struct CMUnitTest flashrom_tests[] = { cmocka_unit_test(flashbuses_to_text_test_success), }; @@ -425,8 +461,14 @@ int main(int argc, char *argv[]) cmocka_unit_test(dummy_init_success_invalid_param_test_success), cmocka_unit_test(dummy_init_success_unhandled_param_test_success), cmocka_unit_test(dummy_null_prog_param_test_success), + cmocka_unit_test(dummy_all_buses_test_success), + cmocka_unit_test(dummy_freq_param_init), cmocka_unit_test(nicrealtek_basic_lifecycle_test_success), cmocka_unit_test(raiden_debug_basic_lifecycle_test_success), + cmocka_unit_test(raiden_debug_targetAP_basic_lifecycle_test_success), + cmocka_unit_test(raiden_debug_targetEC_basic_lifecycle_test_success), + cmocka_unit_test(raiden_debug_target0_basic_lifecycle_test_success), + cmocka_unit_test(raiden_debug_target1_basic_lifecycle_test_success), cmocka_unit_test(dediprog_basic_lifecycle_test_success), cmocka_unit_test(linux_mtd_probe_lifecycle_test_success), cmocka_unit_test(linux_spi_probe_lifecycle_test_success), @@ -436,6 +478,8 @@ int main(int argc, char *argv[]) cmocka_unit_test(mediatek_i2c_no_allow_brick_test_success), cmocka_unit_test(realtek_mst_basic_lifecycle_test_success), cmocka_unit_test(realtek_mst_no_allow_brick_test_success), + cmocka_unit_test(ch341a_spi_basic_lifecycle_test_success), + cmocka_unit_test(ch341a_spi_probe_lifecycle_test_success), }; ret |= cmocka_run_group_tests_name("lifecycle.c tests", lifecycle_tests, NULL, NULL); @@ -456,11 +500,34 @@ int main(int argc, char *argv[]) cmocka_unit_test(read_chip_with_dummyflasher_test_success), cmocka_unit_test(write_chip_test_success), cmocka_unit_test(write_chip_with_dummyflasher_test_success), + cmocka_unit_test(write_chip_feature_no_erase), + cmocka_unit_test(write_nonaligned_region_with_dummyflasher_test_success), cmocka_unit_test(verify_chip_test_success), cmocka_unit_test(verify_chip_with_dummyflasher_test_success), }; ret |= cmocka_run_group_tests_name("chip.c tests", chip_tests, NULL, NULL); + const struct CMUnitTest delay_tests[] = { + cmocka_unit_test(udelay_test_short), + }; + ret |= cmocka_run_group_tests_name("udelay.c tests", delay_tests, NULL, NULL); + + size_t n_erase_tests; + struct CMUnitTest *erase_func_algo_tests = get_erase_func_algo_tests(&n_erase_tests); + ret |= _cmocka_run_group_tests("erase_func_algo.c tests", erase_func_algo_tests, n_erase_tests, NULL, NULL); + free(erase_func_algo_tests); + + size_t n_erase_protected_region_tests; + struct CMUnitTest *erase_protected_region_algo_tests + = get_erase_protected_region_algo_tests(&n_erase_protected_region_tests); + ret |= _cmocka_run_group_tests("erase_func_algo.c protected region tests", + erase_protected_region_algo_tests, + n_erase_protected_region_tests, + NULL, + NULL); + free(erase_protected_region_algo_tests); + + // Write-protect group should run last. const struct CMUnitTest chip_wp_tests[] = { cmocka_unit_test(invalid_wp_range_dummyflasher_test_success), cmocka_unit_test(set_wp_range_dummyflasher_test_success), @@ -468,6 +535,7 @@ int main(int argc, char *argv[]) cmocka_unit_test(wp_init_from_status_dummyflasher_test_success), cmocka_unit_test(full_chip_erase_with_wp_dummyflasher_test_success), cmocka_unit_test(partial_chip_erase_with_wp_dummyflasher_test_success), + cmocka_unit_test(wp_get_register_values_and_masks), }; ret |= cmocka_run_group_tests_name("chip_wp.c tests", chip_wp_tests, NULL, NULL); diff --git a/tests/tests.h b/tests/tests.h index 7d84101e7..100bda1bc 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -16,6 +16,9 @@ #ifndef TESTS_H #define TESTS_H +#include +#include + /* helpers.c */ void address_to_bits_test_success(void **state); void bitcount_test_success(void **state); @@ -49,8 +52,14 @@ void dummy_init_fails_unhandled_param_test_success(void **state); void dummy_init_success_invalid_param_test_success(void **state); void dummy_init_success_unhandled_param_test_success(void **state); void dummy_null_prog_param_test_success(void **state); +void dummy_all_buses_test_success(void **state); +void dummy_freq_param_init(void **state); void nicrealtek_basic_lifecycle_test_success(void **state); void raiden_debug_basic_lifecycle_test_success(void **state); +void raiden_debug_targetAP_basic_lifecycle_test_success(void **state); +void raiden_debug_targetEC_basic_lifecycle_test_success(void **state); +void raiden_debug_target0_basic_lifecycle_test_success(void **state); +void raiden_debug_target1_basic_lifecycle_test_success(void **state); void dediprog_basic_lifecycle_test_success(void **state); void linux_mtd_probe_lifecycle_test_success(void **state); void linux_spi_probe_lifecycle_test_success(void **state); @@ -60,6 +69,8 @@ void mediatek_i2c_spi_basic_lifecycle_test_success(void **state); void mediatek_i2c_no_allow_brick_test_success(void **state); void realtek_mst_basic_lifecycle_test_success(void **state); void realtek_mst_no_allow_brick_test_success(void **state); +void ch341a_spi_basic_lifecycle_test_success(void **state); +void ch341a_spi_probe_lifecycle_test_success(void **state); /* layout.c */ void included_regions_dont_overlap_test_success(void **state); @@ -76,6 +87,8 @@ void read_chip_test_success(void **state); void read_chip_with_dummyflasher_test_success(void **state); void write_chip_test_success(void **state); void write_chip_with_dummyflasher_test_success(void **state); +void write_chip_feature_no_erase(void **state); +void write_nonaligned_region_with_dummyflasher_test_success(void **state); void verify_chip_test_success(void **state); void verify_chip_with_dummyflasher_test_success(void **state); @@ -86,5 +99,21 @@ void switch_wp_mode_dummyflasher_test_success(void **state); void wp_init_from_status_dummyflasher_test_success(void **state); void full_chip_erase_with_wp_dummyflasher_test_success(void **state); void partial_chip_erase_with_wp_dummyflasher_test_success(void **state); +void wp_get_register_values_and_masks(void **state); + +/* selfcheck.c */ +void selfcheck_programmer_table(void **state); +void selfcheck_flashchips_table(void **state); +void selfcheck_eraseblocks(void **state); +void selfcheck_board_matches_table(void **state); + +/* erase_func_algo.c */ +struct CMUnitTest *get_erase_func_algo_tests(size_t *num_tests); +struct CMUnitTest *get_erase_protected_region_algo_tests(size_t *num_tests); +void erase_function_algo_test_success(void **state); +void write_function_algo_test_success(void **state); + +/* udelay.c */ +void udelay_test_short(void **state); #endif /* TESTS_H */ diff --git a/tests/udelay.c b/tests/udelay.c new file mode 100644 index 000000000..8d24b00dd --- /dev/null +++ b/tests/udelay.c @@ -0,0 +1,65 @@ +/* + * This file is part of the flashrom project. + * + * Copyright 2024 Google LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include + +#include "programmer.h" +#include "tests.h" + +static uint64_t now_us(void) { +#if HAVE_CLOCK_GETTIME == 1 + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + return (ts.tv_nsec / 1000) + (ts.tv_sec * 1000000); +#else + struct timeval tv; + + gettimeofday(&tv, NULL); + return tv.tv_usec + (tv.tv_sec * 1000000); +#endif +} + +static const int64_t min_sleep = CONFIG_DELAY_MINIMUM_SLEEP_US; + +/* + * A short delay should delay for at least as long as requested, + * and more than 10x as long would be worrisome. + * + * This test could fail spuriously on a heavily-loaded system, or if we need + * to use gettimeofday() and a time change (such as DST) occurs during the + * test. + */ +void udelay_test_short(void **state) { + /* + * Delay for 100 microseconds, or short enough that we won't sleep. + * It's not useful to test the sleep path because we assume the OS won't + * sleep for less time than we ask. + */ + int64_t delay_us = 100; + if (delay_us >= min_sleep) + delay_us = min_sleep - 1; + /* No point in running this test if delay always sleeps. */ + if (delay_us <= 0) + skip(); + + uint64_t start = now_us(); + default_delay(delay_us); + uint64_t elapsed = now_us() - start; + + assert_in_range(elapsed, delay_us, 10 * delay_us); +} diff --git a/tests/usb_unittests.h b/tests/usb_unittests.h index 29c4b78d3..c81e18147 100644 --- a/tests/usb_unittests.h +++ b/tests/usb_unittests.h @@ -25,7 +25,7 @@ #ifndef _USB_UNITTESTS_H_ #define _USB_UNITTESTS_H_ -#if CONFIG_RAIDEN_DEBUG_SPI == 1 || CONFIG_DEDIPROG == 1 +#if CONFIG_RAIDEN_DEBUG_SPI == 1 || CONFIG_DEDIPROG == 1 || CONFIG_CH341A_SPI == 1 #include @@ -55,6 +55,8 @@ typedef struct libusb_interface_descriptor libusb_interface_descriptor; struct libusb_endpoint_descriptor; typedef struct libusb_endpoint_descriptor libusb_endpoint_descriptor; +struct libusb_transfer; + #endif #endif /* _USB_UNITTESTS_H_ */ diff --git a/tests/wraps.h b/tests/wraps.h index f97eaba45..089d99274 100644 --- a/tests/wraps.h +++ b/tests/wraps.h @@ -28,27 +28,32 @@ struct pci_dev *__wrap_pcidev_init(const struct programmer_cfg *cfg, void *devs, uintptr_t __wrap_pcidev_readbar(void *dev, int bar); void __wrap_sio_write(uint16_t port, uint8_t reg, uint8_t data); uint8_t __wrap_sio_read(uint16_t port, uint8_t reg); -int __wrap_open(const char *pathname, int flags); -int __wrap_open64(const char *pathname, int flags); -int __wrap___open64_2(const char *pathname, int flags); +int __wrap_open(const char *pathname, int flags, ...); +int __real_open(const char *pathname, int flags, ...); +int __wrap_open64(const char *pathname, int flags, ...); +int __wrap___open64_2(const char *pathname, int flags, ...); int __wrap_ioctl(int fd, unsigned long int request, ...); int __wrap_write(int fd, const void *buf, size_t sz); int __wrap_read(int fd, void *buf, size_t sz); FILE *__wrap_fopen(const char *pathname, const char *mode); +FILE *__real_fopen(const char *pathname, const char *mode); FILE *__wrap_fopen64(const char *pathname, const char *mode); FILE *__wrap_fdopen(int fd, const char *mode); +FILE *__real_fdopen(int fd, const char *mode); int __wrap_stat(const char *path, void *buf); int __wrap_stat64(const char *path, void *buf); int __wrap___xstat(const char *path, void *buf); int __wrap___xstat64(const char *path, void *buf); int __wrap_fstat(int fd, void *buf); int __wrap_fstat64(int fd, void *buf); +int __wrap___fstat50(int fd, void *buf); int __wrap___fxstat(int fd, void *buf); int __wrap___fxstat64(int fd, void *buf); char *__wrap_fgets(char *buf, int len, FILE *fp); char *__wrap___fgets_chk(char *buf, int len, FILE *fp); size_t __wrap_fread(void *ptr, size_t size, size_t nmemb, FILE *fp); size_t __wrap_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp); +size_t __real_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp); int __wrap_fflush(FILE *fp); int __wrap_fileno(FILE *fp); int __wrap_fsync(int fd); @@ -56,6 +61,7 @@ int __wrap_setvbuf(FILE *fp, char *buf, int type, size_t size); int __wrap_fprintf(FILE *fp, const char *fmt, ...); int __wrap___vfprintf_chk(FILE *fp, const char *fmt, va_list args); int __wrap_fclose(FILE *fp); +int __real_fclose(FILE *fp); int __wrap_feof(FILE *fp); int __wrap_ferror(FILE *fp); void __wrap_clearerr(FILE *fp); diff --git a/udelay.c b/udelay.c index 6c0efc436..c43b6e3a7 100644 --- a/udelay.c +++ b/udelay.c @@ -3,6 +3,7 @@ * * Copyright (C) 2000 Silicon Integrated System Corporation * Copyright (C) 2009,2010 Carl-Daniel Hailfinger + * Copyright (C) 2024 Google LLC * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,20 +28,25 @@ #include "flash.h" #include "programmer.h" -static bool use_clock_gettime = false; - #if HAVE_CLOCK_GETTIME == 1 +static void clock_usec_delay(int usecs) +{ + static clockid_t clock_id = #ifdef _POSIX_MONOTONIC_CLOCK -static clockid_t clock_id = CLOCK_MONOTONIC; + CLOCK_MONOTONIC; #else -static clockid_t clock_id = CLOCK_REALTIME; + CLOCK_REALTIME; #endif -static void clock_usec_delay(int usecs) -{ struct timespec now; - clock_gettime(clock_id, &now); + if (clock_gettime(clock_id, &now)) { + /* Fall back to realtime clock if monotonic doesn't work */ + if (clock_id != CLOCK_REALTIME && errno == EINVAL) { + clock_id = CLOCK_REALTIME; + clock_gettime(clock_id, &now); + } + } const long end_nsec = now.tv_nsec + usecs * 1000L; const struct timespec end = { @@ -52,210 +58,56 @@ static void clock_usec_delay(int usecs) } while (now.tv_sec < end.tv_sec || (now.tv_sec == end.tv_sec && now.tv_nsec < end.tv_nsec)); } -static int clock_check_res(void) -{ - struct timespec res; - if (!clock_getres(clock_id, &res)) { - if (res.tv_sec == 0 && res.tv_nsec <= 100) { - msg_pinfo("Using clock_gettime for delay loops (clk_id: %d, resolution: %ldns).\n", - (int)clock_id, res.tv_nsec); - use_clock_gettime = true; - return 1; - } - } else if (clock_id != CLOCK_REALTIME && errno == EINVAL) { - /* Try again with CLOCK_REALTIME. */ - clock_id = CLOCK_REALTIME; - return clock_check_res(); - } - return 0; -} #else -static inline void clock_usec_delay(int usecs) {} -static inline int clock_check_res(void) { return 0; } - -#endif /* HAVE_CLOCK_GETTIME == 1 */ - -/* loops per microsecond */ -static unsigned long micro = 1; - -__attribute__ ((noinline)) void myusec_delay(unsigned int usecs) -{ - unsigned long i; - for (i = 0; i < usecs * micro; i++) { - /* Make sure the compiler doesn't optimize the loop away. */ - __asm__ volatile ("" : : "rm" (i) ); - } -} - -static unsigned long measure_os_delay_resolution(void) -{ - unsigned long timeusec; +static void clock_usec_delay(unsigned int usecs) { struct timeval start, end; - unsigned long counter = 0; + unsigned long elapsed = 0; gettimeofday(&start, NULL); - timeusec = 0; - while (!timeusec && (++counter < 1000000000)) { + while (elapsed < usecs) { gettimeofday(&end, NULL); - timeusec = 1000000 * (end.tv_sec - start.tv_sec) + + elapsed = 1000000 * (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec); /* Protect against time going forward too much. */ if ((end.tv_sec > start.tv_sec) && ((end.tv_sec - start.tv_sec) >= LONG_MAX / 1000000 - 1)) - timeusec = 0; + elapsed = 0; /* Protect against time going backwards during leap seconds. */ - if ((end.tv_sec < start.tv_sec) || (timeusec > LONG_MAX)) - timeusec = 0; + if ((end.tv_sec < start.tv_sec) || (elapsed > LONG_MAX)) + elapsed = 0; } - return timeusec; } -static unsigned long measure_delay(unsigned int usecs) -{ - unsigned long timeusec; - struct timeval start, end; - - gettimeofday(&start, NULL); - myusec_delay(usecs); - gettimeofday(&end, NULL); - timeusec = 1000000 * (end.tv_sec - start.tv_sec) + - (end.tv_usec - start.tv_usec); - /* Protect against time going forward too much. */ - if ((end.tv_sec > start.tv_sec) && - ((end.tv_sec - start.tv_sec) >= LONG_MAX / 1000000 - 1)) - timeusec = LONG_MAX; - /* Protect against time going backwards during leap seconds. */ - if ((end.tv_sec < start.tv_sec) || (timeusec > LONG_MAX)) - timeusec = 1; - - return timeusec; -} - -void myusec_calibrate_delay(void) -{ - if (clock_check_res()) - return; - - unsigned long count = 1000; - unsigned long timeusec, resolution; - int i, tries = 0; - - msg_pinfo("Calibrating delay loop... "); - resolution = measure_os_delay_resolution(); - if (resolution) { - msg_pdbg("OS timer resolution is %lu usecs, ", resolution); - } else { - msg_pinfo("OS timer resolution is unusable. "); - } - -recalibrate: - count = 1000; - while (1) { - timeusec = measure_delay(count); - if (timeusec > 1000000 / 4) - break; - if (count >= ULONG_MAX / 2) { - msg_pinfo("timer loop overflow, reduced precision. "); - break; - } - count *= 2; - } - tries ++; - - /* Avoid division by zero, but in that case the loop is shot anyway. */ - if (!timeusec) - timeusec = 1; - - /* Compute rounded up number of loops per microsecond. */ - micro = (count * micro) / timeusec + 1; - msg_pdbg("%luM loops per second, ", micro); - - /* Did we try to recalibrate less than 5 times? */ - if (tries < 5) { - /* Recheck our timing to make sure we weren't just hitting - * a scheduler delay or something similar. - */ - for (i = 0; i < 4; i++) { - if (resolution && (resolution < 10)) { - timeusec = measure_delay(100); - } else if (resolution && - (resolution < ULONG_MAX / 200)) { - timeusec = measure_delay(resolution * 10) * - 100 / (resolution * 10); - } else { - /* This workaround should be active for broken - * OS and maybe libpayload. The criterion - * here is horrible or non-measurable OS timer - * resolution which will result in - * measure_delay(100)=0 whereas a longer delay - * (1000 ms) may be sufficient - * to get a nonzero time measurement. - */ - timeusec = measure_delay(1000000) / 10000; - } - if (timeusec < 90) { - msg_pdbg("delay more than 10%% too short (got " - "%lu%% of expected delay), " - "recalculating... ", timeusec); - goto recalibrate; - } - } - } else { - msg_perr("delay loop is unreliable, trying to continue "); - } - - /* We're interested in the actual precision. */ - timeusec = measure_delay(10); - msg_pdbg("10 myus = %ld us, ", timeusec); - timeusec = measure_delay(100); - msg_pdbg("100 myus = %ld us, ", timeusec); - timeusec = measure_delay(1000); - msg_pdbg("1000 myus = %ld us, ", timeusec); - timeusec = measure_delay(10000); - msg_pdbg("10000 myus = %ld us, ", timeusec); - timeusec = measure_delay(resolution * 4); - msg_pdbg("%ld myus = %ld us, ", resolution * 4, timeusec); - - msg_pinfo("OK.\n"); -} +#endif /* HAVE_CLOCK_GETTIME == 1 */ /* Not very precise sleep. */ void internal_sleep(unsigned int usecs) { #if IS_WINDOWS Sleep((usecs + 999) / 1000); -#elif defined(__DJGPP__) - sleep(usecs / 1000000); - usleep(usecs % 1000000); #else nanosleep(&(struct timespec){usecs / 1000000, (usecs * 1000) % 1000000000UL}, NULL); #endif } +static const unsigned min_sleep = CONFIG_DELAY_MINIMUM_SLEEP_US; + /* Precise delay. */ -void internal_delay(unsigned int usecs) +void default_delay(unsigned int usecs) { - /* If the delay is >1 s, use internal_sleep because timing does not need to be so precise. */ - if (usecs > 1000000) { - internal_sleep(usecs); - } else if (use_clock_gettime) { + if (usecs < min_sleep) { clock_usec_delay(usecs); } else { - myusec_delay(usecs); + internal_sleep(usecs); } } #else #include -void myusec_calibrate_delay(void) -{ - get_cpu_speed(); -} - -void internal_delay(unsigned int usecs) +void default_delay(unsigned int usecs) { udelay(usecs); } diff --git a/udelay_dos.c b/udelay_dos.c new file mode 100644 index 000000000..c3914eacc --- /dev/null +++ b/udelay_dos.c @@ -0,0 +1,172 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2000 Silicon Integrated System Corporation + * Copyright (C) 2009,2010 Carl-Daniel Hailfinger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "flash.h" +#include "programmer.h" + +/* loops per microsecond */ +static unsigned long micro = 1; + +__attribute__ ((noinline)) static void myusec_delay(unsigned int usecs) +{ + unsigned long i; + for (i = 0; i < usecs * micro; i++) { + /* Make sure the compiler doesn't optimize the loop away. */ + __asm__ volatile ("" : : "rm" (i) ); + } +} + +static unsigned long measure_os_delay_resolution(void) +{ + unsigned long timeusec; + struct timeval start, end; + unsigned long counter = 0; + + gettimeofday(&start, NULL); + timeusec = 0; + + while (!timeusec && (++counter < 1000000000)) { + gettimeofday(&end, NULL); + timeusec = 1000000 * (end.tv_sec - start.tv_sec) + + (end.tv_usec - start.tv_usec); + /* Protect against time going forward too much. */ + if ((end.tv_sec > start.tv_sec) && + ((end.tv_sec - start.tv_sec) >= LONG_MAX / 1000000 - 1)) + timeusec = 0; + /* Protect against time going backwards during leap seconds. */ + if ((end.tv_sec < start.tv_sec) || (timeusec > LONG_MAX)) + timeusec = 0; + } + return timeusec; +} + +static unsigned long measure_delay(unsigned int usecs) +{ + unsigned long timeusec; + struct timeval start, end; + + gettimeofday(&start, NULL); + myusec_delay(usecs); + gettimeofday(&end, NULL); + timeusec = 1000000 * (end.tv_sec - start.tv_sec) + + (end.tv_usec - start.tv_usec); + /* Protect against time going forward too much. */ + if ((end.tv_sec > start.tv_sec) && + ((end.tv_sec - start.tv_sec) >= LONG_MAX / 1000000 - 1)) + timeusec = LONG_MAX; + /* Protect against time going backwards during leap seconds. */ + if ((end.tv_sec < start.tv_sec) || (timeusec > LONG_MAX)) + timeusec = 1; + + return timeusec; +} + +static void myusec_calibrate_delay(void) +{ + unsigned long count = 1000; + unsigned long timeusec, resolution; + int i, tries = 0; + + msg_pinfo("Calibrating delay loop... "); + /* Timing resolution on DJGPP is about 50ms, but measure it precisely. */ + resolution = measure_os_delay_resolution(); + if (resolution) { + msg_pdbg("OS timer resolution is %lu usecs, ", resolution); + } else { + msg_pinfo("OS timer resolution is unusable. "); + } + +recalibrate: + count = 1000; + while (1) { + timeusec = measure_delay(count); + if (timeusec > 1000000 / 4) + break; + if (count >= ULONG_MAX / 2) { + msg_pinfo("timer loop overflow, reduced precision. "); + break; + } + count *= 2; + } + tries ++; + + /* Avoid division by zero, but in that case the loop is shot anyway. */ + if (!timeusec) + timeusec = 1; + + /* Compute rounded up number of loops per microsecond. */ + micro = (count * micro) / timeusec + 1; + msg_pdbg("%luM loops per second, ", micro); + + /* Did we try to recalibrate less than 5 times? */ + if (tries < 5) { + /* Recheck our timing to make sure we weren't just hitting + * a scheduler delay or something similar. + */ + for (i = 0; i < 4; i++) { + timeusec = measure_delay(resolution * 10) * + 100 / (resolution * 10); + + if (timeusec < 90) { + msg_pdbg("delay more than 10%% too short (got " + "%lu%% of expected delay), " + "recalculating... ", timeusec); + goto recalibrate; + } + } + } else { + msg_perr("delay loop is unreliable, trying to continue "); + } + + /* We're interested in the actual precision. */ + timeusec = measure_delay(resolution * 4); + msg_pdbg("%ld myus = %ld us, ", resolution * 4, timeusec); + + msg_pinfo("OK.\n"); +} + +/* Not very precise sleep. */ +void internal_sleep(unsigned int usecs) +{ + sleep(usecs / 1000000); + usleep(usecs % 1000000); +} + +static const unsigned min_sleep = CONFIG_DELAY_MINIMUM_SLEEP_US; + +/* Precise delay. */ +void default_delay(unsigned int usecs) +{ + static bool calibrated = false; + + if (usecs < min_sleep) { + if (!calibrated) { + myusec_calibrate_delay(); + calibrated = true; + } + myusec_delay(usecs); + } else { + internal_sleep(usecs); + } +} diff --git a/usb_device.c b/usb_device.c index b3c966cc7..0c8e3e215 100644 --- a/usb_device.c +++ b/usb_device.c @@ -342,9 +342,11 @@ int usb_device_claim(struct usb_device *device) } } - ret = LIBUSB(libusb_set_auto_detach_kernel_driver(device->handle, 1)); - if (ret != 0) { - msg_perr("USB: Failed to enable auto kernel driver detach\n"); + ret = libusb_detach_kernel_driver(device->handle, + device->interface_descriptor->bInterfaceNumber); + if (ret != 0 && ret != LIBUSB_ERROR_NOT_FOUND && ret != LIBUSB_ERROR_NOT_SUPPORTED) { + msg_perr("Cannot detach the existing usb driver. %s\n", + libusb_error_name(ret)); return ret; } @@ -355,6 +357,8 @@ int usb_device_claim(struct usb_device *device) if (ret != 0) { msg_perr("USB: Could not claim device interface %d\n", device->interface_descriptor->bInterfaceNumber); + libusb_attach_kernel_driver(device->handle, + device->interface_descriptor->bInterfaceNumber); return ret; } @@ -384,6 +388,8 @@ struct usb_device *usb_device_free(struct usb_device *device) if (device->handle != NULL) { libusb_release_interface(device->handle, device->interface_descriptor->bInterfaceNumber); + libusb_attach_kernel_driver(device->handle, + device->interface_descriptor->bInterfaceNumber); libusb_close(device->handle); } diff --git a/usbblaster_spi.c b/usbblaster_spi.c index 5e2c020a3..43acaad8e 100644 --- a/usbblaster_spi.c +++ b/usbblaster_spi.c @@ -168,12 +168,9 @@ static const struct spi_master spi_master_usbblaster = { .max_data_read = 256, .max_data_write = 256, .command = usbblaster_spi_send_command, - .multicommand = default_spi_send_multicommand, .read = default_spi_read, .write_256 = default_spi_write_256, - .write_aai = default_spi_write_aai, .shutdown = usbblaster_shutdown, - .probe_opcode = default_spi_probe_opcode, }; /* Returns 0 upon success, a negative number upon errors. */ diff --git a/util/docker/flashrom.org/Dockerfile b/util/docker/flashrom.org/Dockerfile new file mode 100644 index 000000000..23f5f5040 --- /dev/null +++ b/util/docker/flashrom.org/Dockerfile @@ -0,0 +1,29 @@ +FROM alpine:3.8 + +COPY makeSphinx.sh /makeSphinx.sh + +ADD https://sourceforge.net/projects/ditaa/files/ditaa/0.9/ditaa0_9.zip/download /tmp/ditaa.zip + +RUN apk add --no-cache python3 make bash git openjdk8-jre ttf-dejavu fontconfig \ + && pip3 install --upgrade --no-cache-dir pip \ + && pip3 install --no-cache-dir \ + sphinx===1.8.3 \ + sphinx_rtd_theme===0.4.2 \ + recommonmark===0.5.0 \ + sphinx_autobuild===0.7.1 \ + sphinxcontrib-ditaa===0.6 \ + && chmod 755 /makeSphinx.sh +RUN cd /tmp \ + && unzip ditaa.zip \ + && mv ditaa0_9.jar /usr/lib +ADD ditaa.sh /usr/bin/ditaa + +VOLUME /data-in /data-out + +# For Sphinx-autobuild +# Port 8000 - HTTP server +# Port 35729 - websockets connection to allow automatic browser reloads after each build +EXPOSE 8000 35729 + +ENTRYPOINT ["/bin/bash", "/makeSphinx.sh"] +CMD [] diff --git a/util/docker/flashrom.org/README.md b/util/docker/flashrom.org/README.md new file mode 100644 index 000000000..313d0d768 --- /dev/null +++ b/util/docker/flashrom.org/README.md @@ -0,0 +1,32 @@ +# doc.coreboot.org + Docker container for generating and developing documentation for doc.coreboot.org + +**NOTE**: All paths are from the base of the coreboot git repo. + +### Build + +```sh + docker build --force-rm -t "doc.flashrom.org" "$PWD/util/docker/flashrom.org/" +``` + +### Generating production HTML + +```sh +# To ensure the output directory is given the correct permissions, make sure to +# created it before running docker the first time. +mkdir -p "$PWD/doc/_build/" + +docker run -it --rm \ + --user "$(id -u):$(id -g)" \ + -v "$PWD/:/data-in/:ro" \ + -v "$PWD/doc/_build/:/data-out/" \ + doc.flashrom.org +``` + +### live reloaded with web server +On the host machine, open a browser to the address http://0.0.0.0:8000 +```sh +docker run -it --rm \ + --net=host -v "$PWD/:/data-in/:ro" \ + doc.flashrom.org livehtml +``` diff --git a/util/docker/flashrom.org/ditaa.sh b/util/docker/flashrom.org/ditaa.sh new file mode 100755 index 000000000..637379f3e --- /dev/null +++ b/util/docker/flashrom.org/ditaa.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +exec java -jar /usr/lib/ditaa0_9.jar $* diff --git a/util/docker/flashrom.org/makeSphinx.sh b/util/docker/flashrom.org/makeSphinx.sh new file mode 100755 index 000000000..5b6ea0386 --- /dev/null +++ b/util/docker/flashrom.org/makeSphinx.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +if [ "$1" == "livehtml" ]; then + echo "Starting live documentation build" + cd /data-in/ && sphinx-autobuild -b html doc /tmp/build/html +else + echo "Starting production documentation build" + cd /data-in/ \ + && sphinx-build -b html doc /tmp/build/html \ + && rm -rf /data-out/* \ + && mv /tmp/build/html/* /data-out/ +fi diff --git a/util/flashrom.bash-completion.tmpl b/util/flashrom.bash-completion.tmpl new file mode 100644 index 000000000..afb7ae98c --- /dev/null +++ b/util/flashrom.bash-completion.tmpl @@ -0,0 +1,77 @@ +# Completion file for bash +# +# This file is part of the flashrom project. +# +# Copyright 2022 Alexander Goncharov +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# + +_flashrom() +{ + local cur prev OPTS + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + case $prev in + '-r'|'--read'|'-w'|'--write'|'-v'|'--verify'|'-l'|'--layout'| \ + '--fmap-file'|'-o'|'--output'|'--flash-contents') + local IFS=$'\n' + compopt -o filenames + COMPREPLY=( $(compgen -f -- $cur) ) + return 0 + ;; + '-c'|'--chip'|'--wp-range'|'--wp-region'|'-i'|'--include') + return 0 + ;; + '-p'|'--programmer') + COMPREPLY=( $(compgen -W "@PROGRAMMERS@" -- $cur) ) + return 0 + ;; + '-h'|'--help'|'-R'|'--version'|'-L'|'--list-supported') + return 0 + ;; + esac + OPTS="--help + --version + --read + --write + --verify + --erase + --verbose + --chip + --force + --noverify + --noverify-all + --extract + --layout + --wp-disable + --wp-enable + --wp-list + --wp-status + --wp-range + --wp-region + --flash-name + --flash-size + --fmap + --fmap-file + --ifd + --include + --output + --flash-contents + --list-supported + --progress + --programmer" + COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) ) + return 0 +} + +complete -F _flashrom flashrom diff --git a/util/flashrom_tester/.cargo/config.toml b/util/flashrom_tester/.cargo/config.toml new file mode 100644 index 000000000..8af59dd8c --- /dev/null +++ b/util/flashrom_tester/.cargo/config.toml @@ -0,0 +1,2 @@ +[env] +RUST_TEST_THREADS = "1" diff --git a/util/flashrom_tester/Cargo.toml b/util/flashrom_tester/Cargo.toml index b57f04e54..50c73dd72 100644 --- a/util/flashrom_tester/Cargo.toml +++ b/util/flashrom_tester/Cargo.toml @@ -3,6 +3,8 @@ name = "flashrom_tester" version = "1.6.0" authors = ["Edward O'Callaghan ", "Peter Marheine "] +description = "A tool to verify flashrom and flash chip behaviour." +license = "GPL-2.0-only" edition = "2018" build = "build.rs" @@ -13,12 +15,17 @@ name = "flashrom_tester" name = "flashrom_tester" required-features = ["cli"] +[workspace] +members = [".", "flashrom"] + [dependencies] +atty = "0.2" built = { version = "0.5", features = ["chrono"] } chrono = { version = "0.4", optional = true } clap = { version = "2.33", default-features = false, optional = true } flashrom = { path = "flashrom/" } libc = "0.2" +libflashrom = { path = "../../bindings/rust/libflashrom" } log = { version = "0.4", features = ["std"] } rand = "0.6.4" serde_json = "1" @@ -27,6 +34,9 @@ sys-info = "0.9" [build-dependencies] built = { version = "0.5", features = ["chrono"] } +[dev-dependencies] +gag = "1" + [features] # Features required to build the CLI binary but not the library cli = ["chrono", "clap"] diff --git a/util/flashrom_tester/flashrom/Cargo.toml b/util/flashrom_tester/flashrom/Cargo.toml index a2447d04f..4d4fc2fea 100644 --- a/util/flashrom_tester/flashrom/Cargo.toml +++ b/util/flashrom_tester/flashrom/Cargo.toml @@ -3,6 +3,8 @@ name = "flashrom" version = "1.0.0" authors = ["Edward O'Callaghan ", "Peter Marheine "] +description = "Flashrom abstraction for the flashrom_tester tool." +license = "GPL-2.0-only" edition = "2018" [dependencies] diff --git a/util/flashrom_tester/flashrom/src/cmd.rs b/util/flashrom_tester/flashrom/src/cmd.rs index faf597d8f..00c92cb3f 100644 --- a/util/flashrom_tester/flashrom/src/cmd.rs +++ b/util/flashrom_tester/flashrom/src/cmd.rs @@ -33,17 +33,20 @@ // Software Foundation. // -use crate::{FlashChip, FlashromError, ROMWriteSpecifics}; +use crate::{FlashChip, FlashromError}; -use std::process::Command; +use libflashrom::FlashromFlags; + +use std::{ + ffi::{OsStr, OsString}, + path::Path, + process::Command, +}; #[derive(Default)] pub struct FlashromOpt<'a> { pub wp_opt: WPOpt, - pub io_opt: IOOpt<'a>, - - pub layout: Option<&'a str>, // -l - pub image: Option<&'a str>, // -i + pub io_opt: Option>, pub flash_name: bool, // --flash-name pub verbose: bool, // -V @@ -58,13 +61,28 @@ pub struct WPOpt { pub disable: bool, // --wp-disable } -#[derive(Default)] -pub struct IOOpt<'a> { - pub read: Option<&'a str>, // -r - pub write: Option<&'a str>, // -w - pub verify: Option<&'a str>, // -v - pub erase: bool, // -E - pub region: Option<(&'a str, &'a str)>, // --image +pub enum OperationArgs<'a> { + /// The file is the whole chip. + EntireChip(&'a Path), + /// File is the size of the full chip, limited to a single named region. + /// + /// The required path is the file to use, and the optional path is a layout file + /// specifying how to locate regions (if unspecified, flashrom will attempt + /// to discover the layout itself). + FullFileRegion(&'a str, &'a Path, Option<&'a Path>), + /// File is the size of the single named region only. + /// + /// The required path is the file to use, and the optional path is a layout file + /// specifying how to locate regions (if unspecified, flashrom will attempt + /// to discover the layout itself). + RegionFileRegion(&'a str, &'a Path, Option<&'a Path>), // The file contains only the region +} + +pub enum IOOpt<'a> { + Read(OperationArgs<'a>), // -r + Write(OperationArgs<'a>), // -w + Verify(OperationArgs<'a>), // -v + Erase, // -E } #[derive(PartialEq, Eq, Debug)] @@ -112,12 +130,7 @@ impl crate::Flashrom for FlashromCmd { fn name(&self) -> Result<(String, String), FlashromError> { let opts = FlashromOpt { - io_opt: IOOpt { - ..Default::default() - }, - flash_name: true, - ..Default::default() }; @@ -128,16 +141,18 @@ impl crate::Flashrom for FlashromCmd { } } - fn write_file_with_layout(&self, rws: &ROMWriteSpecifics) -> Result { + fn write_from_file_region( + &self, + path: &Path, + region: &str, + layout: &Path, + ) -> Result { let opts = FlashromOpt { - io_opt: IOOpt { - write: rws.write_file, - ..Default::default() - }, - - layout: rws.layout_file, - image: rws.name_file, - + io_opt: Some(IOOpt::Write(OperationArgs::FullFileRegion( + region, + path, + Some(layout), + ))), ..Default::default() }; @@ -145,11 +160,12 @@ impl crate::Flashrom for FlashromCmd { Ok(true) } - fn wp_range(&self, range: (i64, i64), wp_enable: bool) -> Result { + fn wp_range(&self, range: (i64, i64), en: bool) -> Result { let opts = FlashromOpt { wp_opt: WPOpt { + enable: en, + disable: !en, range: Some(range), - enable: wp_enable, ..Default::default() }, ..Default::default() @@ -180,6 +196,7 @@ impl crate::Flashrom for FlashromCmd { fn wp_status(&self, en: bool) -> Result { let status = if en { "en" } else { "dis" }; + let protection_mode = if en { "hardware" } else { "disable" }; info!("See if chip write protect is {}abled", status); let opts = FlashromOpt { @@ -191,33 +208,19 @@ impl crate::Flashrom for FlashromCmd { }; let (stdout, _) = self.dispatch(opts, "wp_status")?; - let s = std::format!("write protect is {}abled", status); + let s = std::format!("Protection mode: {}", protection_mode); Ok(stdout.contains(&s)) } fn wp_toggle(&self, en: bool) -> Result { - let status = if en { "en" } else { "dis" }; - - // For MTD, --wp-range and --wp-enable must be used simultaneously. let range = if en { let rom_sz: i64 = self.get_size()?; - Some((0, rom_sz)) // (start, len) + (0, rom_sz) // (start, len) } else { - None + (0, 0) }; - - let opts = FlashromOpt { - wp_opt: WPOpt { - range, - enable: en, - disable: !en, - ..Default::default() - }, - ..Default::default() - }; - - self.dispatch(opts, "wp_toggle")?; - + self.wp_range(range, en)?; + let status = if en { "en" } else { "dis" }; match self.wp_status(true) { Ok(_ret) => { info!("Successfully {}abled write-protect", status); @@ -227,12 +230,9 @@ impl crate::Flashrom for FlashromCmd { } } - fn read_into_file(&self, path: &str) -> Result<(), FlashromError> { + fn read_into_file(&self, path: &Path) -> Result<(), FlashromError> { let opts = FlashromOpt { - io_opt: IOOpt { - read: Some(path), - ..Default::default() - }, + io_opt: Some(IOOpt::Read(OperationArgs::EntireChip(path))), ..Default::default() }; @@ -240,12 +240,11 @@ impl crate::Flashrom for FlashromCmd { Ok(()) } - fn read_region_into_file(&self, path: &str, region: &str) -> Result<(), FlashromError> { + fn read_region_into_file(&self, path: &Path, region: &str) -> Result<(), FlashromError> { let opts = FlashromOpt { - io_opt: IOOpt { - region: Some((region, path)), - ..Default::default() - }, + io_opt: Some(IOOpt::Read(OperationArgs::RegionFileRegion( + region, path, None, + ))), ..Default::default() }; @@ -253,12 +252,9 @@ impl crate::Flashrom for FlashromCmd { Ok(()) } - fn write_from_file(&self, path: &str) -> Result<(), FlashromError> { + fn write_from_file(&self, path: &Path) -> Result<(), FlashromError> { let opts = FlashromOpt { - io_opt: IOOpt { - write: Some(path), - ..Default::default() - }, + io_opt: Some(IOOpt::Write(OperationArgs::EntireChip(path))), ..Default::default() }; @@ -266,12 +262,9 @@ impl crate::Flashrom for FlashromCmd { Ok(()) } - fn verify_from_file(&self, path: &str) -> Result<(), FlashromError> { + fn verify_from_file(&self, path: &Path) -> Result<(), FlashromError> { let opts = FlashromOpt { - io_opt: IOOpt { - verify: Some(path), - ..Default::default() - }, + io_opt: Some(IOOpt::Verify(OperationArgs::EntireChip(path))), ..Default::default() }; @@ -279,12 +272,21 @@ impl crate::Flashrom for FlashromCmd { Ok(()) } + fn verify_region_from_file(&self, path: &Path, region: &str) -> Result<(), FlashromError> { + let opts = FlashromOpt { + io_opt: Some(IOOpt::Verify(OperationArgs::RegionFileRegion( + region, path, None, + ))), + ..Default::default() + }; + + self.dispatch(opts, "verify_region_from_file")?; + Ok(()) + } + fn erase(&self) -> Result<(), FlashromError> { let opts = FlashromOpt { - io_opt: IOOpt { - erase: true, - ..Default::default() - }, + io_opt: Some(IOOpt::Erase), ..Default::default() }; @@ -295,10 +297,16 @@ impl crate::Flashrom for FlashromCmd { fn can_control_hw_wp(&self) -> bool { self.fc.can_control_hw_wp() } + + fn set_flags(&self, flags: &FlashromFlags) -> () { + // The flashrom CLI sets its own default flags, + // and we currently have no need for custom flags, + // so this set_flags function is intentionally a no-op. + } } -fn flashrom_decode_opts(opts: FlashromOpt) -> Vec { - let mut params = Vec::::new(); +fn flashrom_decode_opts(opts: FlashromOpt) -> Vec { + let mut params = Vec::::new(); // ------------ WARNING !!! ------------ // each param must NOT contain spaces! @@ -307,58 +315,74 @@ fn flashrom_decode_opts(opts: FlashromOpt) -> Vec { // wp_opt if opts.wp_opt.range.is_some() { let (x0, x1) = opts.wp_opt.range.unwrap(); - params.push("--wp-range".to_string()); - params.push(hex_range_string(x0, x1)); + params.push("--wp-range".into()); + params.push(hex_range_string(x0, x1).into()); } if opts.wp_opt.status { - params.push("--wp-status".to_string()); + params.push("--wp-status".into()); } else if opts.wp_opt.list { - params.push("--wp-list".to_string()); + params.push("--wp-list".into()); } else if opts.wp_opt.enable { - params.push("--wp-enable".to_string()); + params.push("--wp-enable".into()); } else if opts.wp_opt.disable { - params.push("--wp-disable".to_string()); + params.push("--wp-disable".into()); } // io_opt - if let Some((region, path)) = opts.io_opt.region { - params.push("--image".to_string()); - params.push(format!("{}:{}", region, path)); - params.push("-r".to_string()); - } else if opts.io_opt.read.is_some() { - params.push("-r".to_string()); - params.push(opts.io_opt.read.unwrap().to_string()); - } else if opts.io_opt.write.is_some() { - params.push("-w".to_string()); - params.push(opts.io_opt.write.unwrap().to_string()); - } else if opts.io_opt.verify.is_some() { - params.push("-v".to_string()); - params.push(opts.io_opt.verify.unwrap().to_string()); - } else if opts.io_opt.erase { - params.push("-E".to_string()); - } - - // misc_opt - if opts.layout.is_some() { - params.push("-l".to_string()); - params.push(opts.layout.unwrap().to_string()); + fn add_operation_args(opts: OperationArgs, params: &mut Vec) { + let (file, region, layout) = match opts { + OperationArgs::EntireChip(file) => (Some(file), None, None), + OperationArgs::FullFileRegion(region, file, layout) => { + (Some(file), Some(region.to_string()), layout) + } + OperationArgs::RegionFileRegion(region, file, layout) => ( + None, + Some(format!("{region}:{}", file.to_string_lossy())), + layout, + ), + }; + if let Some(file) = file { + params.push(file.into()) + } + if let Some(region) = region { + params.push("--include".into()); + params.push(region.into()) + } + if let Some(layout) = layout { + params.push("--layout".into()); + params.push(layout.into()) + } } - if opts.image.is_some() { - params.push("-i".to_string()); - params.push(opts.image.unwrap().to_string()); + if let Some(io) = opts.io_opt { + match io { + IOOpt::Read(args) => { + params.push("-r".into()); + add_operation_args(args, &mut params); + } + IOOpt::Write(args) => { + params.push("-w".into()); + add_operation_args(args, &mut params); + } + IOOpt::Verify(args) => { + params.push("-v".into()); + add_operation_args(args, &mut params); + } + IOOpt::Erase => params.push("-E".into()), + } } + // misc_opt if opts.flash_name { - params.push("--flash-name".to_string()); + params.push("--flash-name".into()); } if opts.verbose { - params.push("-V".to_string()); + params.push("-V".into()); } params } -fn flashrom_dispatch>( +fn flashrom_dispatch>( path: &str, params: &[S], fc: FlashChip, @@ -366,7 +390,7 @@ fn flashrom_dispatch>( ) -> Result<(String, String), FlashromError> { // from man page: // ' -p, --programmer [:parameter[,parameter[,parameter]]] ' - let mut args: Vec<&str> = vec!["-p", FlashChip::to(fc)]; + let mut args: Vec<&OsStr> = vec![OsStr::new("-p"), OsStr::new(FlashChip::to(fc))]; args.extend(params.iter().map(S::as_ref)); info!("flashrom_dispatch() running: {} {:?}", path, args); @@ -396,35 +420,6 @@ fn flashrom_dispatch>( Ok((stdout.into(), stderr.into())) } -pub fn dut_ctrl_toggle_wp(en: bool) -> Result<(Vec, Vec), FlashromError> { - let args = if en { - ["fw_wp_en:off", "fw_wp:on"] - } else { - ["fw_wp_en:on", "fw_wp:off"] - }; - dut_ctrl(&args) -} - -fn dut_ctrl(args: &[&str]) -> Result<(Vec, Vec), FlashromError> { - let output = match Command::new("dut-control").args(args).output() { - Ok(x) => x, - Err(e) => return Err(format!("Failed to run dut-control: {}", e).into()), - }; - if !output.status.success() { - // There is two cases on failure; - // i. ) A bad exit code, - // ii.) A SIG killed us. - match output.status.code() { - Some(code) => { - return Err(format!("Exited with error code: {}", code).into()); - } - None => return Err("Process terminated by a signal".into()), - } - } - - Ok((output.stdout, output.stderr)) -} - fn hex_range_string(s: i64, l: i64) -> String { format!("{:#08X},{:#08X}", s, l) } @@ -454,6 +449,8 @@ fn extract_flash_name(stdout: &str) -> Option<(&str, &str)> { #[cfg(test)] mod tests { + use std::path::Path; + use super::flashrom_decode_opts; use super::{FlashromOpt, IOOpt, WPOpt}; @@ -506,7 +503,7 @@ mod tests { fn test_io_opt(opts: IOOpt, expected: &[&str]) { assert_eq!( flashrom_decode_opts(FlashromOpt { - io_opt: opts, + io_opt: Some(opts), ..Default::default() }), expected @@ -514,53 +511,40 @@ mod tests { } test_io_opt( - IOOpt { - read: Some("foo.bin"), - ..Default::default() - }, + IOOpt::Read(crate::cmd::OperationArgs::EntireChip(Path::new("foo.bin"))), &["-r", "foo.bin"], ); test_io_opt( - IOOpt { - write: Some("bar.bin"), - ..Default::default() - }, + IOOpt::Write(crate::cmd::OperationArgs::EntireChip(Path::new("bar.bin"))), &["-w", "bar.bin"], ); test_io_opt( - IOOpt { - verify: Some("/tmp/baz.bin"), - ..Default::default() - }, - &["-v", "/tmp/baz.bin"], + IOOpt::Verify(crate::cmd::OperationArgs::EntireChip(Path::new("baz.bin"))), + &["-v", "baz.bin"], ); + test_io_opt(IOOpt::Erase, &["-E"]); test_io_opt( - IOOpt { - erase: true, - ..Default::default() - }, - &["-E"], + IOOpt::Read(crate::cmd::OperationArgs::FullFileRegion( + "RO", + Path::new("foo.bin"), + Some(Path::new("baz.bin")), + )), + &["-r", "foo.bin", "--include", "RO", "--layout", "baz.bin"], ); + + test_io_opt( + IOOpt::Read(crate::cmd::OperationArgs::RegionFileRegion( + "foo", + Path::new("bar.bin"), + None, + )), + &["-r", "--include", "foo:bar.bin"], + ) } #[test] fn decode_misc() { //use Default::default; - assert_eq!( - flashrom_decode_opts(FlashromOpt { - layout: Some("TestLayout"), - ..Default::default() - }), - &["-l", "TestLayout"] - ); - - assert_eq!( - flashrom_decode_opts(FlashromOpt { - image: Some("TestImage"), - ..Default::default() - }), - &["-i", "TestImage"] - ); assert_eq!( flashrom_decode_opts(FlashromOpt { diff --git a/util/flashrom_tester/flashrom/src/flashromlib.rs b/util/flashrom_tester/flashrom/src/flashromlib.rs index d20dbb228..fb74188ee 100644 --- a/util/flashrom_tester/flashrom/src/flashromlib.rs +++ b/util/flashrom_tester/flashrom/src/flashromlib.rs @@ -32,11 +32,11 @@ // Software Foundation. // -use libflashrom::{Chip, Programmer}; +use libflashrom::{Chip, FlashromFlag, FlashromFlags, Programmer}; -use std::{cell::RefCell, convert::TryFrom, fs}; +use std::{cell::RefCell, convert::TryFrom, fs, path::Path}; -use crate::{FlashChip, FlashromError, ROMWriteSpecifics}; +use crate::{FlashChip, FlashromError}; #[derive(Debug)] pub struct FlashromLib { @@ -102,19 +102,17 @@ impl crate::Flashrom for FlashromLib { } fn wp_toggle(&self, en: bool) -> Result { - // TODO why does the cmd impl not do this? - // for cmd, range is only set for enable - // and disable is not sent for the wp_range command - self.wp_range((0, self.get_size()?), en) + let range = if en { (0, self.get_size()?) } else { (0, 0) }; + self.wp_range(range, en) } - fn read_into_file(&self, path: &str) -> Result<(), FlashromError> { + fn read_into_file(&self, path: &Path) -> Result<(), FlashromError> { let buf = self.flashrom.borrow_mut().image_read(None)?; fs::write(path, buf).map_err(|error| error.to_string())?; Ok(()) } - fn read_region_into_file(&self, path: &str, region: &str) -> Result<(), FlashromError> { + fn read_region_into_file(&self, path: &Path, region: &str) -> Result<(), FlashromError> { let mut layout = self.flashrom.borrow_mut().layout_read_fmap_from_rom()?; layout.include_region(region)?; let range = layout.get_region_range(region)?; @@ -123,32 +121,58 @@ impl crate::Flashrom for FlashromLib { Ok(()) } - fn write_from_file(&self, path: &str) -> Result<(), FlashromError> { + fn write_from_file(&self, path: &Path) -> Result<(), FlashromError> { let mut buf = fs::read(path).map_err(|error| error.to_string())?; self.flashrom.borrow_mut().image_write(&mut buf, None)?; Ok(()) } - fn write_file_with_layout(&self, rws: &ROMWriteSpecifics) -> Result { - let buf = fs::read(rws.layout_file.unwrap()).map_err(|error| error.to_string())?; + fn write_from_file_region( + &self, + path: &Path, + region: &str, + layout: &Path, + ) -> Result { + let buf = fs::read(layout).map_err(|error| error.to_string())?; let buf = String::from_utf8(buf).unwrap(); let mut layout: libflashrom::Layout = buf .parse() .map_err(|e: Box| e.to_string())?; - layout.include_region(rws.name_file.unwrap())?; - let mut buf = fs::read(rws.write_file.unwrap()).map_err(|error| error.to_string())?; + layout.include_region(region)?; + let mut buf = fs::read(path).map_err(|error| error.to_string())?; self.flashrom .borrow_mut() .image_write(&mut buf, Some(layout))?; Ok(true) } - fn verify_from_file(&self, path: &str) -> Result<(), FlashromError> { + fn verify_from_file(&self, path: &Path) -> Result<(), FlashromError> { let buf = fs::read(path).map_err(|error| error.to_string())?; self.flashrom.borrow_mut().image_verify(&buf, None)?; Ok(()) } + fn verify_region_from_file(&self, path: &Path, region: &str) -> Result<(), FlashromError> { + let mut layout = self.flashrom.borrow_mut().layout_read_fmap_from_rom()?; + layout.include_region(region)?; + let range = layout.get_region_range(region)?; + let region_data = fs::read(path).map_err(|error| error.to_string())?; + if region_data.len() != range.len() { + return Err(format!( + "verify region range ({}) does not match provided file size ({})", + range.len(), + region_data.len() + ) + .into()); + } + let mut buf = vec![0; self.get_size()? as usize]; + buf[range].copy_from_slice(®ion_data); + self.flashrom + .borrow_mut() + .image_verify(&buf, Some(layout))?; + Ok(()) + } + fn erase(&self) -> Result<(), FlashromError> { self.flashrom.borrow_mut().erase()?; Ok(()) @@ -157,4 +181,25 @@ impl crate::Flashrom for FlashromLib { fn can_control_hw_wp(&self) -> bool { self.fc.can_control_hw_wp() } + + fn set_flags(&self, flags: &FlashromFlags) -> () { + self.flashrom + .borrow_mut() + .flag_set(FlashromFlag::FlashromFlagForce, flags.force); + self.flashrom + .borrow_mut() + .flag_set(FlashromFlag::FlashromFlagForceBoardmismatch, flags.force_boardmismatch); + self.flashrom + .borrow_mut() + .flag_set(FlashromFlag::FlashromFlagVerifyAfterWrite, flags.verify_after_write); + self.flashrom + .borrow_mut() + .flag_set(FlashromFlag::FlashromFlagVerifyWholeChip, flags.verify_whole_chip); + self.flashrom + .borrow_mut() + .flag_set(FlashromFlag::FlashromFlagSkipUnreadableRegions, flags.skip_unreadable_regions); + self.flashrom + .borrow_mut() + .flag_set(FlashromFlag::FlashromFlagSkipUnwritableRegions, flags.skip_unwritable_regions); + } } diff --git a/util/flashrom_tester/flashrom/src/lib.rs b/util/flashrom_tester/flashrom/src/lib.rs index 7e245ae84..e5ba9a879 100644 --- a/util/flashrom_tester/flashrom/src/lib.rs +++ b/util/flashrom_tester/flashrom/src/lib.rs @@ -39,40 +39,31 @@ extern crate log; mod cmd; mod flashromlib; -use std::{error, fmt}; +use std::{error, fmt, path::Path}; -pub use cmd::{dut_ctrl_toggle_wp, FlashromCmd}; +pub use cmd::FlashromCmd; pub use flashromlib::FlashromLib; pub use libflashrom::{ - flashrom_log_level, FLASHROM_MSG_DEBUG, FLASHROM_MSG_DEBUG2, FLASHROM_MSG_ERROR, + flashrom_log_level, FlashromFlags, FLASHROM_MSG_DEBUG, FLASHROM_MSG_DEBUG2, FLASHROM_MSG_ERROR, FLASHROM_MSG_INFO, FLASHROM_MSG_SPEW, FLASHROM_MSG_WARN, }; #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum FlashChip { - EC, - HOST, - SERVO, - DEDIPROG, + INTERNAL, } impl FlashChip { pub fn from(s: &str) -> Result { match s { - "ec" => Ok(FlashChip::EC), - "host" => Ok(FlashChip::HOST), - "servo" => Ok(FlashChip::SERVO), - "dediprog" => Ok(FlashChip::DEDIPROG), + "internal" => Ok(FlashChip::INTERNAL), _ => Err("cannot convert str to enum"), } } pub fn to(fc: FlashChip) -> &'static str { match fc { - FlashChip::EC => "ec", - FlashChip::HOST => "host", - FlashChip::SERVO => "ft2231_spi:type=servo-v2", - FlashChip::DEDIPROG => "dediprog", + FlashChip::INTERNAL => "internal", } } @@ -89,8 +80,7 @@ impl FlashChip { /// disabled. pub fn can_control_hw_wp(&self) -> bool { match self { - FlashChip::HOST | FlashChip::EC => true, - FlashChip::SERVO | FlashChip::DEDIPROG => false, + FlashChip::INTERNAL => true, } } } @@ -117,12 +107,6 @@ where } } -pub struct ROMWriteSpecifics<'a> { - pub layout_file: Option<&'a str>, - pub write_file: Option<&'a str>, - pub name_file: Option<&'a str>, -} - pub trait Flashrom { /// Returns the size of the flash in bytes. fn get_size(&self) -> Result; @@ -130,10 +114,7 @@ pub trait Flashrom { /// Returns the vendor name and the flash name. fn name(&self) -> Result<(String, String), FlashromError>; - /// Write only a region of the flash. - fn write_file_with_layout(&self, rws: &ROMWriteSpecifics) -> Result; - - /// Set write protect status for a range. + /// Set write protect status and range. fn wp_range(&self, range: (i64, i64), wp_enable: bool) -> Result; /// Read the write protect regions for the flash. @@ -143,23 +124,45 @@ pub trait Flashrom { fn wp_status(&self, en: bool) -> Result; /// Set write protect status. + /// If en=true sets wp_range to the whole chip (0,getsize()). + /// If en=false sets wp_range to (0,0). + /// This is due to the MTD driver, which requires wp enable to use a range + /// length != 0 and wp disable to have the range 0,0. fn wp_toggle(&self, en: bool) -> Result; /// Read the whole flash to the file specified by `path`. - fn read_into_file(&self, path: &str) -> Result<(), FlashromError>; + fn read_into_file(&self, path: &Path) -> Result<(), FlashromError>; - /// Read only a region of the flash. - fn read_region_into_file(&self, path: &str, region: &str) -> Result<(), FlashromError>; + /// Read only a region of the flash into the file specified by `path`. Note + /// the first byte written to the file is the first byte from the region. + fn read_region_into_file(&self, path: &Path, region: &str) -> Result<(), FlashromError>; /// Write the whole flash to the file specified by `path`. - fn write_from_file(&self, path: &str) -> Result<(), FlashromError>; + fn write_from_file(&self, path: &Path) -> Result<(), FlashromError>; + + /// Write only a region of the flash. + /// `path` is a file of the size of the whole flash. + /// The `region` name corresponds to a region name in the `layout` file, not the flash. + fn write_from_file_region( + &self, + path: &Path, + region: &str, + layout: &Path, + ) -> Result; /// Verify the whole flash against the file specified by `path`. - fn verify_from_file(&self, path: &str) -> Result<(), FlashromError>; + fn verify_from_file(&self, path: &Path) -> Result<(), FlashromError>; + + /// Verify only the region against the file specified by `path`. + /// Note the first byte in the file is matched against the first byte of the region. + fn verify_region_from_file(&self, path: &Path, region: &str) -> Result<(), FlashromError>; /// Erase the whole flash. fn erase(&self) -> Result<(), FlashromError>; /// Return true if the hardware write protect of this flash can be controlled. fn can_control_hw_wp(&self) -> bool; + + /// Set flags used by the flashrom cli. + fn set_flags(&self, flags: &FlashromFlags) -> (); } diff --git a/util/flashrom_tester/src/cros_sysinfo.rs b/util/flashrom_tester/src/cros_sysinfo.rs index e047f8e61..37e1ec659 100644 --- a/util/flashrom_tester/src/cros_sysinfo.rs +++ b/util/flashrom_tester/src/cros_sysinfo.rs @@ -34,6 +34,7 @@ // use std::ffi::OsStr; +use std::fs; use std::io::Result as IoResult; use std::process::{Command, Stdio}; @@ -58,3 +59,12 @@ pub fn system_info() -> IoResult { pub fn bios_info() -> IoResult { dmidecode_dispatch(&["-q", "-t0"]) } + +pub fn release_description() -> IoResult { + for l in fs::read_to_string("/etc/lsb-release")?.lines() { + if l.starts_with("CHROMEOS_RELEASE_DESCRIPTION") { + return Ok(l.to_string()); + } + } + Err(std::io::ErrorKind::NotFound.into()) +} diff --git a/util/flashrom_tester/src/logger.rs b/util/flashrom_tester/src/logger.rs index 12e54957b..c9c364066 100644 --- a/util/flashrom_tester/src/logger.rs +++ b/util/flashrom_tester/src/logger.rs @@ -35,96 +35,70 @@ use flashrom_tester::types; use std::io::Write; -use std::path::PathBuf; -use std::sync::Mutex; -struct Logger { +struct Logger { level: log::LevelFilter, - target: LogTarget, + color: types::Color, } -enum LogTarget -where - W: Write, -{ - Terminal, - Write(Mutex), -} - -impl log::Log for Logger { +impl log::Log for Logger { fn enabled(&self, metadata: &log::Metadata) -> bool { metadata.level() <= self.level } fn log(&self, record: &log::Record) { - fn log_internal(mut w: W, record: &log::Record) -> std::io::Result<()> { - let now = chrono::Local::now(); - write!(w, "{}{} ", types::MAGENTA, now.format("%Y-%m-%dT%H:%M:%S"))?; - write!( - w, - "{}[ {} ]{} ", - types::YELLOW, - record.level(), - types::RESET - )?; - writeln!(w, "{}", record.args()) - } - // Write errors deliberately ignored - let _ = match self.target { - LogTarget::Terminal => { - let stdout = std::io::stdout(); - let mut lock = stdout.lock(); - log_internal(&mut lock, record) - } - LogTarget::Write(ref mutex) => { - let mut lock = mutex.lock().unwrap(); - log_internal(&mut *lock, record) - } - }; + let stdout = std::io::stdout(); + let mut lock = stdout.lock(); + let now = chrono::Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Micros, true); + let _ = write!(lock, "{}{} ", self.color.magenta, now); + let _ = write!( + lock, + "{}[ {} ]{} ", + self.color.yellow, + record.level(), + self.color.reset + ); + let _ = writeln!(lock, "{}", record.args()); } fn flush(&self) { // Flush errors deliberately ignored - let _ = match self.target { - LogTarget::Terminal => std::io::stdout().flush(), - LogTarget::Write(ref w) => w.lock().unwrap().flush(), - }; + let _ = std::io::stdout().flush(); } } -pub fn init(to_file: Option, debug: bool) { +pub fn init(debug: bool) { let mut logger = Logger { level: log::LevelFilter::Info, - target: LogTarget::Terminal, + color: if atty::is(atty::Stream::Stdout) { + types::COLOR + } else { + types::NOCOLOR + }, }; if debug { logger.level = log::LevelFilter::Debug; } - if let Some(path) = to_file { - logger.target = LogTarget::Write(Mutex::new( - std::fs::File::create(path).expect("Unable to open log file for writing"), - )); - } - log::set_max_level(logger.level); log::set_boxed_logger(Box::new(logger)).unwrap(); } #[cfg(test)] mod tests { - use super::{LogTarget, Logger}; + use std::io::Read; + + use super::Logger; + use flashrom_tester::types; use log::{Level, LevelFilter, Log, Record}; - use std::sync::Mutex; fn run_records(records: &[Record]) -> String { - let mut buf = Vec::::new(); + let buf = gag::BufferRedirect::stdout().unwrap(); { - let lock = Mutex::new(&mut buf); let logger = Logger { level: LevelFilter::Info, - target: LogTarget::Write(lock), + color: types::COLOR, }; for record in records { @@ -133,7 +107,9 @@ mod tests { } } } - String::from_utf8(buf).unwrap() + let mut ret = String::new(); + buf.into_inner().read_to_string(&mut ret).unwrap(); + ret } /// Log messages have the expected format @@ -146,9 +122,10 @@ mod tests { assert_eq!(&buf[..5], "\x1b[35m"); // Time is difficult to test, assume it's formatted okay + // Split on the UTC timezone char assert_eq!( - &buf[24..], - " \x1b[33m[ INFO ]\x1b[0m Test message at INFO\n" + buf.split_once("Z ").unwrap().1, + "\x1b[33m[ INFO ]\x1b[0m Test message at INFO\n" ); } diff --git a/util/flashrom_tester/src/main.rs b/util/flashrom_tester/src/main.rs index 129d1a9b7..3035ae5f3 100644 --- a/util/flashrom_tester/src/main.rs +++ b/util/flashrom_tester/src/main.rs @@ -41,7 +41,6 @@ mod logger; use clap::{App, Arg}; use flashrom::{FlashChip, Flashrom, FlashromCmd, FlashromLib}; use flashrom_tester::{tester, tests}; -use std::path::PathBuf; use std::sync::atomic::AtomicBool; pub mod built_info { @@ -83,7 +82,7 @@ fn main() { .arg( Arg::with_name("ccd_target_type") .required(true) - .possible_values(&["host", "ec", "servo"]), + .possible_values(&["internal"]), ) .arg( Arg::with_name("print-layout") @@ -91,13 +90,6 @@ fn main() { .long("print-layout") .help("Print the layout file's contents before running tests"), ) - .arg( - Arg::with_name("log-file") - .short("o") - .long("log-file") - .takes_value(true) - .help("Write logs to a file rather than stdout"), - ) .arg( Arg::with_name("log_debug") .short("d") @@ -121,10 +113,7 @@ fn main() { ) .get_matches(); - logger::init( - matches.value_of_os("log-file").map(PathBuf::from), - matches.is_present("log_debug"), - ); + logger::init(matches.is_present("log_debug")); debug!("Args parsed and logging initialized OK"); debug!("Collecting crossystem info"); diff --git a/util/flashrom_tester/src/rand_util.rs b/util/flashrom_tester/src/rand_util.rs index 1b0912bed..a040c89a3 100644 --- a/util/flashrom_tester/src/rand_util.rs +++ b/util/flashrom_tester/src/rand_util.rs @@ -36,10 +36,11 @@ use std::fs::File; use std::io::prelude::*; use std::io::BufWriter; +use std::path::Path; use rand::prelude::*; -pub fn gen_rand_testdata(path: &str, size: usize) -> std::io::Result<()> { +pub fn gen_rand_testdata(path: &Path, size: usize) -> std::io::Result<()> { let mut buf = BufWriter::new(File::create(path)?); let mut a: Vec = vec![0; size]; @@ -58,8 +59,8 @@ mod tests { fn gen_rand_testdata() { use super::gen_rand_testdata; - let path0 = "/tmp/idk_test00"; - let path1 = "/tmp/idk_test01"; + let path0 = Path::new("/tmp/idk_test00"); + let path1 = Path::new("/tmp/idk_test01"); let sz = 1024; gen_rand_testdata(path0, sz).unwrap(); diff --git a/util/flashrom_tester/src/tester.rs b/util/flashrom_tester/src/tester.rs index f2c38465d..c4098f2b5 100644 --- a/util/flashrom_tester/src/tester.rs +++ b/util/flashrom_tester/src/tester.rs @@ -38,10 +38,13 @@ use super::types; use super::utils::{self, LayoutSizes}; use flashrom::FlashromError; use flashrom::{FlashChip, Flashrom}; +use libflashrom::FlashromFlags; use serde_json::json; -use std::mem::MaybeUninit; +use std::fs::File; +use std::io::Write; +use std::path::Path; +use std::path::PathBuf; use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Mutex; // type-signature comes from the return type of lib.rs workers. type TestError = Box; @@ -56,17 +59,21 @@ pub struct TestEnv<'a> { pub cmd: &'a dyn Flashrom, layout: LayoutSizes, - pub wp: WriteProtectState<'a, 'static>, + pub wp: WriteProtectState<'a>, /// The path to a file containing the flash contents at test start. - // TODO(pmarheine) migrate this to a PathBuf for clarity - original_flash_contents: String, + original_flash_contents: PathBuf, /// The path to a file containing flash-sized random data - // TODO(pmarheine) make this a PathBuf too - random_data: String, + random_data: PathBuf, + /// The path to a file containing layout data. + pub layout_file: PathBuf, } impl<'a> TestEnv<'a> { - pub fn create(chip_type: FlashChip, cmd: &'a dyn Flashrom) -> Result { + pub fn create( + chip_type: FlashChip, + cmd: &'a dyn Flashrom, + print_layout: bool, + ) -> Result { let rom_sz = cmd.get_size()?; let out = TestEnv { chip_type, @@ -75,7 +82,11 @@ impl<'a> TestEnv<'a> { wp: WriteProtectState::from_hardware(cmd, chip_type)?, original_flash_contents: "/tmp/flashrom_tester_golden.bin".into(), random_data: "/tmp/random_content.bin".into(), + layout_file: create_layout_file(rom_sz, Path::new("/tmp/"), print_layout), }; + let flags = FlashromFlags::default(); + info!("Set flags: {}", flags); + out.cmd.set_flags(&flags); info!("Stashing golden image for verification/recovery on completion"); out.cmd.read_into_file(&out.original_flash_contents)?; @@ -89,19 +100,10 @@ impl<'a> TestEnv<'a> { } pub fn run_test(&mut self, test: T) -> TestResult { - let use_dut_control = self.chip_type == FlashChip::SERVO; - if use_dut_control && flashrom::dut_ctrl_toggle_wp(false).is_err() { - error!("failed to dispatch dut_ctrl_toggle_wp()!"); - } - let name = test.get_name(); info!("Beginning test: {}", name); let out = test.run(self); info!("Completed test: {}; result {:?}", name, out); - - if use_dut_control && flashrom::dut_ctrl_toggle_wp(true).is_err() { - error!("failed to dispatch dut_ctrl_toggle_wp()!"); - } out } @@ -113,7 +115,7 @@ impl<'a> TestEnv<'a> { /// Return the path to a file that contains random data and is the same size /// as the flash chip. - pub fn random_data_file(&self) -> &str { + pub fn random_data_file(&self) -> &Path { &self.random_data } @@ -147,7 +149,7 @@ impl<'a> TestEnv<'a> { /// path. /// /// Returns Err if they are not the same. - pub fn verify(&self, contents_path: &str) -> Result<(), FlashromError> { + pub fn verify(&self, contents_path: &Path) -> Result<(), FlashromError> { self.cmd.verify_from_file(contents_path)?; Ok(()) } @@ -165,64 +167,33 @@ impl<'a> Drop for TestEnv<'a> { } } +struct WriteProtect { + hw: bool, + sw: bool, +} + /// RAII handle for setting write protect in either hardware or software. /// /// Given an instance, the state of either write protect can be modified by calling -/// `set` or `push`. When it goes out of scope, the write protects will be returned +/// `set`. When it goes out of scope, the write protects will be returned /// to the state they had then it was created. -/// -/// The lifetime `'p` on this struct is the parent state it derives from; `'static` -/// implies it is derived from hardware, while anything else is part of a stack -/// created by `push`ing states. An initial state is always static, and the stack -/// forms a lifetime chain `'static -> 'p -> 'p1 -> ... -> 'pn`. -pub struct WriteProtectState<'a, 'p> { - /// The parent state this derives from. - /// - /// If it's a root (gotten via `from_hardware`), then this is Hardware and the - /// liveness flag will be reset on drop. - initial: InitialState<'p>, - // Tuples are (hardware, software) - current: (bool, bool), +pub struct WriteProtectState<'a> { + current: WriteProtect, + initial: WriteProtect, cmd: &'a dyn Flashrom, fc: FlashChip, } -enum InitialState<'p> { - Hardware(bool, bool), - Previous(&'p WriteProtectState<'p, 'p>), -} - -impl InitialState<'_> { - fn get_target(&self) -> (bool, bool) { - match self { - InitialState::Hardware(hw, sw) => (*hw, *sw), - InitialState::Previous(s) => s.current, - } - } -} - -impl<'a> WriteProtectState<'a, 'static> { +impl<'a> WriteProtectState<'a> { /// Initialize a state from the current state of the hardware. - /// - /// Panics if there is already a live state derived from hardware. In such a situation the - /// new state must be derived from the live one, or the live one must be dropped first. pub fn from_hardware(cmd: &'a dyn Flashrom, fc: FlashChip) -> Result { - let mut lock = Self::get_liveness_lock() - .lock() - .expect("Somebody panicked during WriteProtectState init from hardware"); - if *lock { - drop(lock); // Don't poison the lock - panic!("Attempted to create a new WriteProtectState when one is already live"); - } - let hw = Self::get_hw(cmd)?; let sw = Self::get_sw(cmd)?; - info!("Initial hardware write protect: HW={} SW={}", hw, sw); + info!("Initial write protect state: HW={} SW={}", hw, sw); - *lock = true; Ok(WriteProtectState { - initial: InitialState::Hardware(hw, sw), - current: (hw, sw), + current: WriteProtect { hw, sw }, + initial: WriteProtect { hw, sw }, cmd, fc, }) @@ -242,9 +213,7 @@ impl<'a> WriteProtectState<'a, 'static> { let b = cmd.wp_status(true)?; Ok(b) } -} -impl<'a, 'p> WriteProtectState<'a, 'p> { /// Return true if the current programmer supports setting the hardware /// write protect. /// @@ -253,85 +222,65 @@ impl<'a, 'p> WriteProtectState<'a, 'p> { self.cmd.can_control_hw_wp() } - /// Set the software write protect. - pub fn set_sw(&mut self, enable: bool) -> Result<&mut Self, FlashromError> { - info!("request={}, current={}", enable, self.current.1); - if self.current.1 != enable { - self.cmd.wp_toggle(/* en= */ enable)?; - self.current.1 = enable; + /// Set the software write protect and check that the state is as expected. + pub fn set_sw(&mut self, enable: bool) -> Result<&mut Self, String> { + info!("set_sw request={}, current={}", enable, self.current.sw); + if self.current.sw != enable { + self.cmd + .wp_toggle(/* en= */ enable) + .map_err(|e| e.to_string())?; } - Ok(self) - } - - /// Set the hardware write protect. - pub fn set_hw(&mut self, enable: bool) -> Result<&mut Self, String> { - if self.current.0 != enable { - if self.can_control_hw_wp() { - super::utils::toggle_hw_wp(/* dis= */ !enable)?; - self.current.0 = enable; - } else if enable { - info!( - "Ignoring attempt to enable hardware WP with {:?} programmer", - self.fc - ); - } + if Self::get_sw(self.cmd).map_err(|e| e.to_string())? != enable { + Err(format!( + "Software write protect did not change state to {} when requested", + enable + )) + } else { + self.current.sw = enable; + Ok(self) } - Ok(self) } - /// Stack a new write protect state on top of the current one. - /// - /// This is useful if you need to temporarily make a change to write protection: - /// - /// ```no_run - /// # fn main() -> Result<(), Box> { - /// # let cmd: flashrom::FlashromCmd = unimplemented!(); - /// let wp = flashrom_tester::tester::WriteProtectState::from_hardware(&cmd, flashrom::FlashChip::SERVO)?; - /// { - /// let mut wp = wp.push(); - /// wp.set_sw(false)?; - /// // Do something with software write protect disabled - /// } - /// // Now software write protect returns to its original state, even if - /// // set_sw() failed. - /// # Ok(()) - /// # } - /// ``` - /// - /// This returns a new state which restores the original when it is dropped- the new state - /// refers to the old, so the compiler enforces that states are disposed of in the reverse - /// order of their creation and correctly restore the original state. - pub fn push<'p1>(&'p1 self) -> WriteProtectState<'a, 'p1> { - WriteProtectState { - initial: InitialState::Previous(self), - current: self.current, - cmd: self.cmd, - fc: self.fc, + // Set software write protect with a custom range + pub fn set_range(&mut self, range: (i64, i64), enable: bool) -> Result<&mut Self, String> { + info!("set_range request={}, current={}", enable, self.current.sw); + self.cmd + .wp_range(range, enable) + .map_err(|e| e.to_string())?; + let actual_state = Self::get_sw(self.cmd).map_err(|e| e.to_string())?; + if actual_state != enable { + Err(format!( + "set_range request={}, real={}", + enable, actual_state + )) + } else { + self.current.sw = enable; + Ok(self) } } - fn get_liveness_lock() -> &'static Mutex { - static INIT: std::sync::Once = std::sync::Once::new(); - /// Value becomes true when there is a live WriteProtectState derived `from_hardware`, - /// blocking duplicate initialization. - /// - /// This is required because hardware access is not synchronized; it's possible to leave the - /// hardware in an unintended state by creating a state handle from it, modifying the state, - /// creating another handle from the hardware then dropping the first handle- then on drop - /// of the second handle it will restore the state to the modified one rather than the initial. - /// - /// This flag ensures that a duplicate root state cannot be created. - /// - /// This is a Mutex rather than AtomicBool because acquiring the flag needs to perform - /// several operations that may themselves fail- acquisitions must be fully synchronized. - static mut LIVE_FROM_HARDWARE: MaybeUninit> = MaybeUninit::uninit(); - - unsafe { - INIT.call_once(|| { - LIVE_FROM_HARDWARE.as_mut_ptr().write(Mutex::new(false)); - }); - &*LIVE_FROM_HARDWARE.as_ptr() + /// Set the hardware write protect if supported and check that the state is as expected. + pub fn set_hw(&mut self, enable: bool) -> Result<&mut Self, String> { + info!("set_hw request={}, current={}", enable, self.current.hw); + if self.can_control_hw_wp() { + if self.current.hw != enable { + super::utils::toggle_hw_wp(/* dis= */ !enable)?; + } + // toggle_hw_wp does check this, but we might not have called toggle_hw_wp so check again. + if Self::get_hw(self.cmd)? != enable { + return Err(format!( + "Hardware write protect did not change state to {} when requested", + enable + )); + } + } else { + info!( + "Ignoring attempt to set hardware WP with {:?} programmer", + self.fc + ); } + self.current.hw = enable; + Ok(self) } /// Reset the hardware to what it was when this state was created, reporting errors. @@ -339,91 +288,30 @@ impl<'a, 'p> WriteProtectState<'a, 'p> { /// This behaves exactly like allowing a state to go out of scope, but it can return /// errors from that process rather than panicking. pub fn close(mut self) -> Result<(), String> { - unsafe { - let out = self.drop_internal(); - // We just ran drop, don't do it again - std::mem::forget(self); - out - } + let out = self.drop_internal(); + // We just ran drop, don't do it again + std::mem::forget(self); + out } - /// Internal Drop impl. - /// - /// This is unsafe because it effectively consumes self when clearing the - /// liveness lock. Callers must be able to guarantee that self will be forgotten - /// if the state was constructed from hardware in order to uphold the liveness - /// invariant (that only a single state constructed from hardware exists at any - /// time). - unsafe fn drop_internal(&mut self) -> Result<(), String> { - let lock = match self.initial { - InitialState::Hardware(_, _) => Some( - Self::get_liveness_lock() - .lock() - .expect("Somebody panicked during WriteProtectState drop from hardware"), - ), - _ => None, - }; - let (hw, sw) = self.initial.get_target(); - - fn enable_str(enable: bool) -> &'static str { - if enable { - "en" - } else { - "dis" - } - } - + /// Sets both write protects to the state they had when this state was created. + fn drop_internal(&mut self) -> Result<(), String> { // Toggle both protects back to their initial states. // Software first because we can't change it once hardware is enabled. - if sw != self.current.1 { - // Is the hw wp currently enabled? - if self.current.0 { - super::utils::toggle_hw_wp(/* dis= */ true).map_err(|e| { - format!( - "Failed to {}able hardware write protect: {}", - enable_str(false), - e - ) - })?; - } - self.cmd.wp_toggle(/* en= */ sw).map_err(|e| { - format!( - "Failed to {}able software write protect: {}", - enable_str(sw), - e - ) - })?; - } - - assert!( - self.cmd.can_control_hw_wp() || (!self.current.0 && !hw), - "HW WP must be disabled if it cannot be controlled" - ); - if hw != self.current.0 { - super::utils::toggle_hw_wp(/* dis= */ !hw).map_err(|e| { - format!( - "Failed to {}able hardware write protect: {}", - enable_str(hw), - e - ) - })?; + if self.set_sw(self.initial.sw).is_err() { + self.set_hw(false)?; + self.set_sw(self.initial.sw)?; } + self.set_hw(self.initial.hw)?; - if let Some(mut lock) = lock { - // Initial state was constructed via from_hardware, now we can clear the liveness - // lock since reset is complete. - *lock = false; - } Ok(()) } } -impl<'a, 'p> Drop for WriteProtectState<'a, 'p> { - /// Sets both write protects to the state they had when this state was created. - /// - /// Panics on error because there is no mechanism to report errors in Drop. +impl<'a> Drop for WriteProtectState<'a> { fn drop(&mut self) { - unsafe { self.drop_internal() }.expect("Error while dropping WriteProtectState") + self.drop_internal() + .expect("Error while dropping WriteProtectState") } } @@ -473,6 +361,7 @@ pub enum TestConclusion { pub struct ReportMetaData { pub chip_name: String, pub os_release: String, + pub cros_release: String, pub system_info: String, pub bios_info: String, } @@ -487,17 +376,38 @@ fn decode_test_result(res: TestResult, con: TestConclusion) -> (TestConclusion, } } +fn create_layout_file(rom_sz: i64, tmp_dir: &Path, print_layout: bool) -> PathBuf { + info!("Calculate ROM partition sizes & Create the layout file."); + let layout_sizes = utils::get_layout_sizes(rom_sz).expect("Could not partition rom"); + + let layout_file = tmp_dir.join("layout.file"); + let mut f = File::create(&layout_file).expect("Could not create layout file"); + let mut buf: Vec = vec![]; + utils::construct_layout_file(&mut buf, &layout_sizes).expect("Could not construct layout file"); + + f.write_all(&buf).expect("Writing layout file failed"); + if print_layout { + info!( + "Dumping layout file as requested:\n{}", + String::from_utf8_lossy(&buf) + ); + } + layout_file +} + pub fn run_all_tests( chip: FlashChip, cmd: &dyn Flashrom, ts: TS, terminate_flag: Option<&AtomicBool>, + print_layout: bool, ) -> Vec<(String, (TestConclusion, Option))> where T: TestCase + Copy, TS: IntoIterator, { - let mut env = TestEnv::create(chip, cmd).expect("Failed to set up test environment"); + let mut env = + TestEnv::create(chip, cmd, print_layout).expect("Failed to set up test environment"); let mut results = Vec::new(); for t in ts { @@ -543,6 +453,11 @@ pub fn collate_all_test_runs( ) { match format { OutputFormat::Pretty => { + let color = if atty::is(atty::Stream::Stdout) { + types::COLOR + } else { + types::NOCOLOR + }; println!(); println!(" ============================="); println!(" ===== AVL qual RESULTS ===="); @@ -550,6 +465,7 @@ pub fn collate_all_test_runs( println!(); println!(" %---------------------------%"); println!(" os release: {}", meta_data.os_release); + println!(" cros release: {}", meta_data.cros_release); println!(" chip name: {}", meta_data.chip_name); println!(" system info: \n{}", meta_data.system_info); println!(" bios info: \n{}", meta_data.bios_info); @@ -561,8 +477,8 @@ pub fn collate_all_test_runs( if *result != TestConclusion::Pass { println!( " {} {}", - style!(format!(" <+> {} test:", name), types::BOLD), - style_dbg!(result, types::RED) + style!(format!(" <+> {} test:", name), color.bold, color), + style_dbg!(result, color.red, color) ); match error { None => {} @@ -571,8 +487,8 @@ pub fn collate_all_test_runs( } else { println!( " {} {}", - style!(format!(" <+> {} test:", name), types::BOLD), - style_dbg!(result, types::GREEN) + style!(format!(" <+> {} test:", name), color.bold, color), + style_dbg!(result, color.green, color) ); } } diff --git a/util/flashrom_tester/src/tests.rs b/util/flashrom_tester/src/tests.rs index 1527a6e68..d1e9d6194 100644 --- a/util/flashrom_tester/src/tests.rs +++ b/util/flashrom_tester/src/tests.rs @@ -40,11 +40,11 @@ use flashrom::{FlashChip, Flashrom}; use std::collections::{HashMap, HashSet}; use std::convert::TryInto; use std::fs::{self, File}; -use std::io::{BufRead, Write}; +use std::io::BufRead; use std::sync::atomic::AtomicBool; -const LAYOUT_FILE: &str = "/tmp/layout.file"; const ELOG_FILE: &str = "/tmp/elog.file"; +const FW_MAIN_B_PATH: &str = "/tmp/FW_MAIN_B.bin"; /// Iterate over tests, yielding only those tests with names matching filter_names. /// @@ -91,23 +91,6 @@ pub fn generic<'a, TN: Iterator>( ) -> Result<(), Box> { utils::ac_power_warning(); - info!("Calculate ROM partition sizes & Create the layout file."); - let rom_sz: i64 = cmd.get_size()?; - let layout_sizes = utils::get_layout_sizes(rom_sz)?; - { - let mut f = File::create(LAYOUT_FILE)?; - let mut buf: Vec = vec![]; - utils::construct_layout_file(&mut buf, &layout_sizes)?; - - f.write_all(&buf)?; - if print_layout { - info!( - "Dumping layout file as requested:\n{}", - String::from_utf8_lossy(&buf) - ); - } - } - info!("Record crossystem information.\n{}", crossystem); // Register tests to run: @@ -115,10 +98,10 @@ pub fn generic<'a, TN: Iterator>( &("Get_device_name", get_device_name_test), &("Coreboot_ELOG_sanity", elog_sanity_test), &("Host_is_ChromeOS", host_is_chrome_test), - &("Toggle_WP", wp_toggle_test), + &("WP_Region_List", wp_region_list_test), &("Erase_and_Write", erase_write_test), &("Fail_to_verify", verify_fail_test), - &("Lock", lock_test), + &("HWWP_Locks_SWWP", hwwp_locks_swwp_test), &("Lock_top_quad", partial_lock_test(LayoutNames::TopQuad)), &( "Lock_bottom_quad", @@ -144,7 +127,7 @@ pub fn generic<'a, TN: Iterator>( // ------------------------. // Run all the tests and collate the findings: - let results = tester::run_all_tests(fc, cmd, tests, terminate_flag); + let results = tester::run_all_tests(fc, cmd, tests, terminate_flag, print_layout); // Any leftover filtered names were specified to be run but don't exist for leftover in filter_names.iter().flatten() { @@ -152,12 +135,15 @@ pub fn generic<'a, TN: Iterator>( } let os_release = sys_info::os_release().unwrap_or("".to_string()); + let cros_release = cros_sysinfo::release_description() + .unwrap_or("".to_string()); let system_info = cros_sysinfo::system_info().unwrap_or("".to_string()); let bios_info = cros_sysinfo::bios_info().unwrap_or("".to_string()); let meta_data = tester::ReportMetaData { chip_name, os_release, + cros_release, system_info, bios_info, }; @@ -165,26 +151,25 @@ pub fn generic<'a, TN: Iterator>( Ok(()) } +/// Query the programmer and chip name. +/// Success means we got something back, which is good enough. fn get_device_name_test(env: &mut TestEnv) -> TestResult { - // Success means we got something back, which is good enough. env.cmd.name()?; Ok(()) } -fn wp_toggle_test(env: &mut TestEnv) -> TestResult { - // NOTE: This is not strictly a 'test' as it is allowed to fail on some platforms. - // However, we will warn when it does fail. - // List the write-protected regions of flash. +/// List the write-protectable regions of flash. +/// NOTE: This is not strictly a 'test' as it is allowed to fail on some platforms. +/// However, we will warn when it does fail. +fn wp_region_list_test(env: &mut TestEnv) -> TestResult { match env.cmd.wp_list() { Ok(list_str) => info!("\n{}", list_str), Err(e) => warn!("{}", e), }; - // Fails if unable to set either one - env.wp.set_hw(false)?; - env.wp.set_sw(false)?; Ok(()) } +/// Verify that enabling hardware and software write protect prevents chip erase. fn erase_write_test(env: &mut TestEnv) -> TestResult { if !env.is_golden() { info!("Memory has been modified; reflashing to ensure erasure can be detected"); @@ -211,30 +196,31 @@ fn erase_write_test(env: &mut TestEnv) -> TestResult { Ok(()) } -fn lock_test(env: &mut TestEnv) -> TestResult { +/// Verify that enabling hardware write protect prevents disabling software write protect. +fn hwwp_locks_swwp_test(env: &mut TestEnv) -> TestResult { if !env.wp.can_control_hw_wp() { return Err("Lock test requires ability to control hardware write protect".into()); } env.wp.set_hw(false)?.set_sw(true)?; - // Toggling software WP off should work when hardware is off. - // Then enable again for another go. - env.wp.push().set_sw(false)?; + // Toggling software WP off should work when hardware WP is off. + // Then enable software WP again for the next test. + env.wp.set_sw(false)?.set_sw(true)?; + // Toggling software WP off should not work when hardware WP is on. env.wp.set_hw(true)?; - // Clearing should fail when hardware is enabled if env.wp.set_sw(false).is_ok() { return Err("Software WP was reset despite hardware WP being enabled".into()); } Ok(()) } +/// Check that the elog contains *something*, as an indication that Coreboot +/// is actually able to write to the Flash. This only makes sense for chips +/// running Coreboot, which we assume is just host. fn elog_sanity_test(env: &mut TestEnv) -> TestResult { - // Check that the elog contains *something*, as an indication that Coreboot - // is actually able to write to the Flash. This only makes sense for chips - // running Coreboot, which we assume is just host. - if env.chip_type() != FlashChip::HOST { - info!("Skipping ELOG sanity check for non-host chip"); + if env.chip_type() != FlashChip::INTERNAL { + info!("Skipping ELOG sanity check for non-internal chip"); return Ok(()); } // flash should be back in the golden state @@ -242,7 +228,7 @@ fn elog_sanity_test(env: &mut TestEnv) -> TestResult { const ELOG_RW_REGION_NAME: &str = "RW_ELOG"; env.cmd - .read_region_into_file(ELOG_FILE, ELOG_RW_REGION_NAME)?; + .read_region_into_file(ELOG_FILE.as_ref(), ELOG_RW_REGION_NAME)?; // Just checking for the magic numer // TODO: improve this test to read the events @@ -256,6 +242,7 @@ fn elog_sanity_test(env: &mut TestEnv) -> TestResult { Ok(()) } +/// Check that we are running ChromiumOS. fn host_is_chrome_test(_env: &mut TestEnv) -> TestResult { let release_info = if let Ok(f) = File::open("/etc/os-release") { let buf = std::io::BufReader::new(f); @@ -281,25 +268,27 @@ fn host_is_chrome_test(_env: &mut TestEnv) -> TestResult { } } +/// Verify that software write protect for a range protects only the requested range. fn partial_lock_test(section: LayoutNames) -> impl Fn(&mut TestEnv) -> TestResult { move |env: &mut TestEnv| { // Need a clean image for verification env.ensure_golden()?; let (wp_section_name, start, len) = utils::layout_section(env.layout(), section); - // Disable software WP so we can do range protection, but hardware WP - // must remain enabled for (most) range protection to do anything. - env.wp.set_hw(false)?.set_sw(false)?; - env.cmd.wp_range((start, len), true)?; + // Disable hardware WP so we can modify the protected range. + env.wp.set_hw(false)?; + // Then enable software WP so the range is enforced and enable hardware + // WP so that flashrom does not disable software WP during the + // operation. + env.wp.set_range((start, len), true)?; env.wp.set_hw(true)?; // Check that we cannot write to the protected region. - let rws = flashrom::ROMWriteSpecifics { - layout_file: Some(LAYOUT_FILE), - write_file: Some(env.random_data_file()), - name_file: Some(wp_section_name), - }; - if env.cmd.write_file_with_layout(&rws).is_ok() { + if env + .cmd + .write_from_file_region(env.random_data_file(), wp_section_name, &env.layout_file) + .is_ok() + { return Err( "Section should be locked, should not have been overwritable with random data" .into(), @@ -312,19 +301,28 @@ fn partial_lock_test(section: LayoutNames) -> impl Fn(&mut TestEnv) -> TestResul // Check that we can write to the non protected region. let (non_wp_section_name, _, _) = utils::layout_section(env.layout(), section.get_non_overlapping_section()); - let rws = flashrom::ROMWriteSpecifics { - layout_file: Some(LAYOUT_FILE), - write_file: Some(env.random_data_file()), - name_file: Some(non_wp_section_name), - }; - env.cmd.write_file_with_layout(&rws)?; + env.cmd.write_from_file_region( + env.random_data_file(), + non_wp_section_name, + &env.layout_file, + )?; Ok(()) } } +/// Check that flashrom 'verify' will fail if the provided data does not match the chip data. fn verify_fail_test(env: &mut TestEnv) -> TestResult { - // Comparing the flash contents to random data says they're not the same. + env.ensure_golden()?; + // Verify that verify is Ok when the data matches. We verify only a region + // and not the whole chip because coprocessors or firmware may have written + // some data in other regions. + env.cmd + .read_region_into_file(FW_MAIN_B_PATH.as_ref(), "FW_MAIN_B")?; + env.cmd + .verify_region_from_file(FW_MAIN_B_PATH.as_ref(), "FW_MAIN_B")?; + + // Verify that verify is false when the data does not match match env.verify(env.random_data_file()) { Ok(_) => Err("Verification says flash is full of random data".into()), Err(_) => Ok(()), diff --git a/util/flashrom_tester/src/types.rs b/util/flashrom_tester/src/types.rs index b22ded2b4..9cefb27e9 100644 --- a/util/flashrom_tester/src/types.rs +++ b/util/flashrom_tester/src/types.rs @@ -33,21 +33,40 @@ // Software Foundation. // -pub const BOLD: &str = "\x1b[1m"; +pub struct Color { + pub bold: &'static str, + pub reset: &'static str, + pub magenta: &'static str, + pub yellow: &'static str, + pub green: &'static str, + pub red: &'static str, +} + +pub const COLOR: Color = Color { + bold: "\x1b[1m", + reset: "\x1b[0m", + magenta: "\x1b[35m", + yellow: "\x1b[33m", + green: "\x1b[92m", + red: "\x1b[31m", +}; -pub const RESET: &str = "\x1b[0m"; -pub const MAGENTA: &str = "\x1b[35m"; -pub const YELLOW: &str = "\x1b[33m"; -pub const GREEN: &str = "\x1b[92m"; -pub const RED: &str = "\x1b[31m"; +pub const NOCOLOR: Color = Color { + bold: "", + reset: "", + magenta: "", + yellow: "", + green: "", + red: "", +}; macro_rules! style_dbg { - ($s: expr, $c: expr) => { - format!("{}{:?}{}", $c, $s, types::RESET) + ($s: expr, $c: expr, $col: expr) => { + format!("{}{:?}{}", $c, $s, $col.reset) }; } macro_rules! style { - ($s: expr, $c: expr) => { - format!("{}{}{}", $c, $s, types::RESET) + ($s: expr, $c: expr, $col: expr) => { + format!("{}{}{}", $c, $s, $col.reset) }; } diff --git a/util/flashrom_tester/src/utils.rs b/util/flashrom_tester/src/utils.rs index 4e8dd7cce..017d77d99 100644 --- a/util/flashrom_tester/src/utils.rs +++ b/util/flashrom_tester/src/utils.rs @@ -101,8 +101,9 @@ pub fn construct_layout_file(mut target: F, ls: &LayoutSizes) -> std:: pub fn toggle_hw_wp(dis: bool) -> Result<(), String> { // The easist way to toggle the hardware write-protect is - // to {dis}connect the battery (and/or open the WP screw). + // to {dis}connect the battery (and/or {open,close} the WP screw). let s = if dis { "dis" } else { "" }; + let screw_state = if dis { "open" } else { "close" }; // Print a failure message, but not on the first try. let mut fail_msg = None; while dis == get_hardware_wp()? { @@ -112,7 +113,7 @@ pub fn toggle_hw_wp(dis: bool) -> Result<(), String> { fail_msg = Some(format!("Hardware write protect is still {}!", !dis)); // The following message is read by the tast test. Do not modify. info!("Prompt for hardware WP {}able", s); - eprintln!(" > {}connect the battery (and/or open the WP screw)", s); + eprintln!(" > {}connect the battery (and/or {} the WP screw)", s, screw_state); pause(); } Ok(()) diff --git a/util/flashrom_udev.rules b/util/flashrom_udev.rules index 9fd333082..331fee649 100644 --- a/util/flashrom_udev.rules +++ b/util/flashrom_udev.rules @@ -93,4 +93,7 @@ ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a99", MODE="664", GROUP="plugdev" # Winchiphead (WCH) CH341a based programmer ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="5512", MODE="664", GROUP="plugdev" +# Winchiphead (WCH) CH347 based programmer +ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55db", MODE="664", GROUP="plugdev" + LABEL="flashrom_rules_end" diff --git a/util/getrevision.sh b/util/getrevision.sh deleted file mode 100755 index f7d6bf3b2..000000000 --- a/util/getrevision.sh +++ /dev/null @@ -1,238 +0,0 @@ -#!/bin/sh -# NB: Supposed to be POSIX compatible but at least the usage of 'local' is not. -# -# This file is part of the flashrom project. -# -# Copyright (C) 2005 coresystems GmbH -# Copyright (C) 2009,2010 Carl-Daniel Hailfinger -# Copyright (C) 2010 Chromium OS Authors -# Copyright (C) 2013-2016 Stefan Tauner -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# - -EXIT_SUCCESS=0 -EXIT_FAILURE=1 - -# Make sure we don't get translated output -export LC_ALL=C -# nor local times or dates -export TZ=UTC0 - -# Helper functions -# First argument is the path to inspect (usually optional; without -# it the whole repository will be considered) -git_has_local_changes() { - git update-index -q --refresh >/dev/null - ! git diff-index --quiet HEAD -- "$1" -} - -git_last_commit() { - # git rev-parse --short HEAD would suffice if repository as a whole is of interest (no $1) - git log --pretty=format:"%h" -1 -- "$1" -} - -git_is_file_tracked() { - git ls-files --error-unmatch -- "$1" >/dev/null 2>&1 -} - -is_file_tracked() { - git_is_file_tracked "$1" -} - -# Tries to find a remote source for the changes committed locally. -# This includes the URL of the remote repository including the last commit and a suitable branch name. -# Takes one optional argument: the path to inspect -git_url() { - last_commit=$(git_last_commit "$1") - # get all remote branches containing the last commit (excluding origin/HEAD) - branches=$(git branch -r --contains $last_commit | sed '/\//!d;/.*->.*/d;s/[\t ]*//') - if [ -z "$branches" ] ; then - echo "No remote branch contains a suitable commit">&2 - return - fi - - # find "nearest" branch - local mindiff=9000 - local target= - for branch in $branches ; do - curdiff=$(git rev-list --count $last_commit..$branch) - if [ $curdiff -ge $mindiff ] ; then - continue - fi - mindiff=$curdiff - target=$branch - done - - echo "$(git ls-remote --exit-code --get-url ${target%/*}) ${target#*/}" -} - -# Returns a string indicating where others can get the current source code (excluding uncommitted changes). -# Takes one optional argument: the path to inspect -scm_url() { - local url= - - if git_is_file_tracked "$1" ; then - url="$(git_url "$1")" - else - return ${EXIT_FAILURE} - fi - - echo "${url}" -} - -# Retrieve timestamp since last modification. If the sources are pristine, -# then the timestamp will match that of the SCM's most recent modification -# date. -timestamp() { - local t - - # date syntaxes are manifold: - # gnu date [-d input]... [+FORMAT] - # netbsd date [-ajnu] [-d date] [-r seconds] [+format] [[[[[[CC]yy]mm]dd]HH]MM[.SS]] - # freebsd date [-jnu] [-d dst] [-r seconds] [-f fmt date | [[[[[cc]yy]mm]dd]HH]MM[.ss]] [+format] [...] - # dragonflybsd date [-jnu] [-d dst] [-r seconds] [-f fmt date | [[[[[cc]yy]mm]dd]HH]MM[.ss]] [+format] [...] - # openbsd date [-aju] [-d dst] [-r seconds] [+format] [[[[[[cc]yy]mm]dd]HH]MM[.SS]] [...] - if git_is_file_tracked "$2" ; then - # are there local changes? - if git_has_local_changes "$2" ; then - t=$(date -u "${1}") - else - # No local changes, get date of the last commit - case $(uname) in - # Most BSD dates do not support parsing date values from user input with -d but all of - # them support parsing epoch seconds with -r. Thanks to git we can easily use that: - NetBSD|OpenBSD|DragonFly|FreeBSD) - t=$(date -u -r "$(git log --pretty=format:%ct -1 -- $2)" "$1" 2>/dev/null);; - *) - t=$(date -d "$(git log --pretty=format:%cD -1 -- $2)" -u "$1" 2>/dev/null);; - esac - fi - else - t=$(date -u "$1") - fi - - if [ -z "$t" ]; then - echo "Warning: Could not determine timestamp." 2>/dev/null - fi - echo "${t}" -} - -revision() { - local r - if git_is_file_tracked "$1" ; then - r=$(git describe --always $(git_last_commit "$1")) - if git_has_local_changes "$1" ; then - r="$r-dirty" - fi - else - r="unknown" - fi - - echo "${r}" -} - -is_tracked() { - is_file_tracked "$1" -} - -show_help() { - echo "Usage: - ${0} [path] - -Commands - -h or --help - this message - -c or --check - test if path is under version control at all - -r or --revision - return unique revision information including an indicator for - uncommitted changes - -U or --url - URL associated with the latest commit - -d or --date - date of most recent modification - -t or --timestamp - timestamp of most recent modification -" - return -} - -check_action() { - if [ -n "$action" ]; then - echo "Error: Multiple actions given.">&2 - exit ${EXIT_FAILURE} - fi -} - -main() { - local query_path= - local action= - - # Argument parser loop - while [ $# -gt 0 ]; - do - case ${1} in - -h|--help) - action=show_help; - shift;; - -U|--url) - check_action $1 - action=scm_url - shift;; - -d|--date) - check_action $1 - action="timestamp +%Y-%m-%d" # refrain from suffixing 'Z' to indicate it's UTC - shift;; - -r|--revision) - check_action $1 - action=revision - shift;; - -t|--timestamp) - check_action $1 - action="timestamp +%Y-%m-%dT%H:%M:%SZ" # There is only one valid time format! ISO 8601 - shift;; - -c|--check) - check_action $1 - action=is_tracked - shift;; - -*) - show_help; - echo "Error: Invalid option: ${1}" - exit ${EXIT_FAILURE};; - *) - if [ -z "$query_path" ] ; then - if [ ! -e "$1" ] ; then - echo "Error: Path \"${1}\" does not exist.">&2 - exit ${EXIT_FAILURE} - fi - query_path=$1 - else - echo "Warning: Ignoring overabundant parameter: \"${1}\"">&2 - fi - shift;; - esac; - done - - # default to current directory (usually equals the whole repository) - if [ -z "$query_path" ] ; then - query_path=. - fi - if [ -z "$action" ] ; then - show_help - echo "Error: No actions specified" - exit ${EXIT_FAILURE} - fi - - $action "$query_path" -} - -main $@ diff --git a/util/getversion.sh b/util/getversion.sh deleted file mode 100755 index d3810d29b..000000000 --- a/util/getversion.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/sh -# -# This file is part of the flashrom project. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# - -version() { - if [ -r versioninfo.inc ]; then - v=$(sed -n 's/^VERSION = //p' versioninfo.inc) - else - v=$($(dirname ${0})/getrevision.sh --revision) - if [ $? -ne 0 ]; then - v='unknown' - fi - fi - - echo ${v} -} - -mandate() { - if [ -r versioninfo.inc ]; then - d=$(sed -n 's/^MAN_DATE = //p' versioninfo.inc) - else - d=$($(dirname ${0})/getrevision.sh --date flashrom.8.tmpl) - if [ $? -ne 0 ]; then - d='unknown' - fi - fi - - echo ${d} -} - -show_help() { - echo "Usage: - ${0} - -Commands - -h or --help - this message - -v or --version - return current/release flashrom version - -m or --man-date - return current/release date of the manual page -" -} - -if [ $# -ne 1 ]; then - show_help - echo "Error: Only exactly one command allowed.">&2 - exit 1 -fi - -case $1 in - -h|--help) show_help;; - -m|--man-date) mandate;; - -v|--version) version;; - *) - show_help - echo "Error: Invalid option: $1" - exit 1 - ;; -esac diff --git a/util/git-hooks/commit-msg b/util/git-hooks/commit-msg index d43eb4529..e2f5de512 100755 --- a/util/git-hooks/commit-msg +++ b/util/git-hooks/commit-msg @@ -196,6 +196,7 @@ _gen_ChangeId() { test_signoff() { if ! grep -qi '^[[:space:]]*\+Signed-off-by:' "$MSG"; then + cat "$MSG" printf "\nError: No Signed-off-by line in the commit message.\n" printf "See: ${DEV_GUIDELINES_URL}\n" exit 1 @@ -206,6 +207,7 @@ test_signoff() { test_duplicate_signoffs_acks() { test "" = "$(grep -i '^(Signed-off-by|Acked-by): ' "$MSG" | sort | uniq -c | sed -e '/^[[:space:]]*1[[:space:]]/d')" || { + cat "$MSG" echo "Duplicate Signed-off-by or Acked-by lines." >&2 exit 1 } diff --git a/util/ich_descriptors_tool/Makefile b/util/ich_descriptors_tool/Makefile deleted file mode 100644 index aa1b696c3..000000000 --- a/util/ich_descriptors_tool/Makefile +++ /dev/null @@ -1,83 +0,0 @@ -# -# This file is part of the flashrom project. -# -# This Makefile works standalone, but it is usually called from the main -# Makefile in the flashrom directory. - -include ../../Makefile.include - -PROGRAM=ich_descriptors_tool -EXTRAINCDIRS = ../../ . -DEPPATH = .dep -OBJATH = .obj -SHAREDSRC = ich_descriptors.c -SHAREDSRCDIR = ../.. -# If your compiler spits out excessive warnings, run make WARNERROR=no -# You shouldn't have to change this flag. -WARNERROR ?= yes - -SRC = $(wildcard *.c) - -# If the user has specified custom CFLAGS, all CFLAGS settings below will be -# completely ignored by gnumake. -CFLAGS ?= -Os -Wall -Wshadow -override CFLAGS += -I$(SHAREDSRCDIR)/include - -# Auto determine HOST_OS and TARGET_OS if they are not set as argument -HOST_OS ?= $(shell uname) -TARGET_OS := $(call c_macro_test, ../../Makefile.d/os_test.h) - -ifeq ($(findstring MINGW, $(HOST_OS)), MINGW) -# Explicitly set CC = gcc on MinGW, otherwise: "cc: command not found". -CC = gcc -endif - -ifeq ($(TARGET_OS), DOS) -EXEC_SUFFIX := .exe -# DJGPP has odd uint*_t definitions which cause lots of format string warnings. -CFLAGS += -Wno-format -endif - -ifeq ($(TARGET_OS), MinGW) -EXEC_SUFFIX := .exe -# Some functions provided by Microsoft do not work as described in C99 specifications. This macro fixes that -# for MinGW. See http://sourceforge.net/p/mingw-w64/wiki2/printf%20and%20scanf%20family/ -CFLAGS += -D__USE_MINGW_ANSI_STDIO=1 -endif - -ifeq ($(WARNERROR), yes) -CFLAGS += -Werror -endif - - -FLASHROM_CFLAGS += -MMD -MP -MF $(DEPPATH)/$(@F).d -# enables functions that populate the descriptor structs from plain binary dumps -FLASHROM_CFLAGS += -D ICH_DESCRIPTORS_FROM_DUMP_ONLY -FLASHROM_CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) - -OBJ = $(OBJATH)/$(SRC:%.c=%.o) - -SHAREDOBJ = $(OBJATH)/$(notdir $(SHAREDSRC:%.c=%.o)) - -all:$(PROGRAM)$(EXEC_SUFFIX) - -$(OBJ): $(OBJATH)/%.o : %.c - $(CC) $(CFLAGS) $(CPPFLAGS) $(FLASHROM_CFLAGS) -o $@ -c $< - -# this enables us to share source files without simultaneously sharing .o files -# with flashrom, which would lead to unexpected results (w/o running make clean) -$(SHAREDOBJ): $(OBJATH)/%.o : $(SHAREDSRCDIR)/%.c - $(CC) $(CFLAGS) $(CPPFLAGS) $(FLASHROM_CFLAGS) -o $@ -c $< - -$(PROGRAM)$(EXEC_SUFFIX): $(OBJ) $(SHAREDOBJ) - $(CC) $(LDFLAGS) -o $(PROGRAM)$(EXEC_SUFFIX) $(OBJ) $(SHAREDOBJ) - -# We don't use EXEC_SUFFIX here because we want to clean everything. -clean: - rm -f $(PROGRAM) $(PROGRAM).exe - rm -rf $(DEPPATH) $(OBJATH) - -# Include the dependency files. --include $(shell mkdir -p $(DEPPATH) $(OBJATH) 2>/dev/null) $(wildcard $(DEPPATH)/*) - -.PHONY: all clean diff --git a/util/ich_descriptors_tool/ich_descriptors_tool.c b/util/ich_descriptors_tool/ich_descriptors_tool.c index 44af49b6a..ec77a8821 100644 --- a/util/ich_descriptors_tool/ich_descriptors_tool.c +++ b/util/ich_descriptors_tool/ich_descriptors_tool.c @@ -38,9 +38,9 @@ static const char *const region_names[] = { "Descriptor", "BIOS", "ME", "GbE", "Platform", - "Region5", "BIOS2", "Region7", "EC/BMC", "Region9", - "IE", "10GbE", "Region12", "Region13", "Region14", - "Region15" + "DevExp", "BIOS2", "Region7", "EC/BMC", "DevExp2", + "IE", "10GbE0", "10GbE1", "Region13", "Region14", + "PTT" }; static void dump_file(const char *prefix, const uint32_t *dump, unsigned int len, @@ -129,6 +129,7 @@ static void usage(char *argv[], const char *error) "\t- \"gemini\" for Intel's Gemini Lake SoC.\n" "\t- \"jasper\" for Intel's Jasper Lake SoC.\n" "\t- \"meteor\" for Intel's Meteor Lake SoC.\n" +"\t- \"panther\" for Intel's Panther Lake SoC.\n" "\t- \"5\" or \"ibex\" for Intel's 5 series chipsets,\n" "\t- \"6\" or \"cougar\" for Intel's 6 series chipsets,\n" "\t- \"7\" or \"panther\" for Intel's 7 series chipsets.\n" @@ -139,6 +140,7 @@ static void usage(char *argv[], const char *error) "\t- \"400\" or \"comet\" for Intel's 400 series chipsets.\n" "\t- \"500\" or \"tiger\" for Intel's 500 series chipsets.\n" "\t- \"600\" or \"alder\" for Intel's 600 series chipsets.\n" +"\t- \"700\" or \"raptor\" for Intel's 700 series chipsets.\n" "If '-d' is specified some regions such as the BIOS image as seen by the CPU or\n" "the GbE blob that is required to initialize the GbE are also dumped to files.\n", argv[0], argv[0]); @@ -236,9 +238,11 @@ int main(int argc, char *argv[]) else if ((strcmp(csn, "500") == 0) || (strcmp(csn, "tiger") == 0)) cs = CHIPSET_500_SERIES_TIGER_POINT; - else if (strcmp(csn, "600") == 0) + else if ((strcmp(csn, "600") == 0) || + (strcmp(csn, "alder") == 0)) cs = CHIPSET_600_SERIES_ALDER_POINT; - else if (strcmp(csn, "700") == 0) + else if ((strcmp(csn, "700") == 0) || + (strcmp(csn, "raptor") == 0)) cs = CHIPSET_700_SERIES_RAPTOR_POINT; else if (strcmp(csn, "apollo") == 0) cs = CHIPSET_APOLLO_LAKE; @@ -250,6 +254,8 @@ int main(int argc, char *argv[]) cs = CHIPSET_ELKHART_LAKE; else if (strcmp(csn, "meteor") == 0) cs = CHIPSET_METEOR_LAKE; + else if (strcmp(csn, "panther") == 0) + cs = CHIPSET_PANTHER_LAKE; } ret = read_ich_descriptors_from_dump(buf, len, &cs, &desc); diff --git a/util/lint/helper_functions.sh b/util/lint/helper_functions.sh new file mode 100644 index 000000000..7abdab861 --- /dev/null +++ b/util/lint/helper_functions.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env sh +# +# SPDX-License-Identifier: GPL-2.0-only + +# This file is sourced by the linters so that each one doesn't have to +# specify these routines individually + +LC_ALL=C export LC_ALL + +if [ -z "$GIT" ]; then + GIT="$(command -v git)" +else + # If git is specified, Do a basic check that it runs and seems like + # it's actually git + if ! "${GIT}" --version | grep -q git; then + echo "Error: ${GIT} does not seem to be valid." + exit 1; + fi +fi + +if [ "$(${GIT} rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]; then + IN_GIT_TREE=1 +else + IN_GIT_TREE=0 +fi + +if [ "${IN_GIT_TREE}" -eq 1 ] && [ -z "${GIT}" ]; then + echo "This test needs git to run. Please install it, then run this test again." + exit 1 +fi + +# Use git ls-files if the code is in a git repo, otherwise use find. +if [ "${IN_GIT_TREE}" -eq 1 ]; then + FIND_FILES="${GIT} ls-files" +else + FIND_FILES="find " + FINDOPTS="-type f" +fi + +# Use git grep if the code is in a git repo, otherwise use grep. +if [ "${IN_GIT_TREE}" -eq 1 ]; then + GREP_FILES="${GIT} grep" +else + GREP_FILES="grep -r" +fi diff --git a/util/lint/lint-extended-020-signed-off-by b/util/lint/lint-extended-020-signed-off-by new file mode 100755 index 000000000..ef62a45a2 --- /dev/null +++ b/util/lint/lint-extended-020-signed-off-by @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +# SPDX-License-Identifier: GPL-2.0-or-later +# +# DESCR: Check for a signed-off-by line on the latest commit + + +LINTDIR="$( + cd -- "$(dirname "$0")" > /dev/null 2>&1 || return + pwd -P +)" + +# shellcheck source=helper_functions.sh +. "${LINTDIR}/helper_functions.sh" + +if [ "${IN_GIT_TREE}" -eq 0 ]; then + exit 0 +fi + +# This test is mainly for the jenkins server +if ! ${GIT} log -n 1 | grep -q '[[:space:]]\+Signed-off-by: '; then + echo "No Signed-off-by line in commit message" + exit 1 +fi diff --git a/util/list_yet_unsupported_chips.sh b/util/list_yet_unsupported_chips.sh index 3a4d1b85b..a82326136 100755 --- a/util/list_yet_unsupported_chips.sh +++ b/util/list_yet_unsupported_chips.sh @@ -2,20 +2,20 @@ scriptname=$(readlink -f "$0") 2>/dev/null path=$(dirname "$scriptname")/.. 2>/dev/null -if [ ! -e "$path/flashchips.c" -o ! -e "$path/flashchips.h" ]; then +if [ ! -e "$path/flashchips.c" -o ! -e "$path/include/flashchips.h" ]; then echo "Warning: could not calculate flashchips.[ch]'s directory. Trying current..." path="." - if [ ! -e "$path/flashchips.c" -o ! -e "$path/flashchips.h" ]; then + if [ ! -e "$path/flashchips.c" -o ! -e "$path/include/flashchips.h" ]; then echo "Nope, sorry!" exit 1 fi fi -chips=$(sed -re '/#define [A-Z]/ !d' -e '/_ID\s/d' -e 's/\s*#define\s+([[:alnum:]_]+)\s+.*/\1/' "$path/flashchips.h") +chips=$(sed -re '/#define [A-Z]/ !d' -e '/_ID\s/d' -e 's/\s*#define\s+([[:alnum:]_]+)\s+.*/\1/' "$path/include/flashchips.h") for c in $chips ; do if ! grep "$c" "$path/flashchips.c" >/dev/null ; then if [ -n "$1" ]; then - grep -o "$c.*" "$path/flashchips.h" + grep -o "$c.*" "$path/include/flashchips.h" else echo "$c" fi diff --git a/util/manibuilder/Dockerfile.djgpp b/util/manibuilder/Dockerfile.djgpp index 7bd5c7bd6..b2fa3fa31 100644 --- a/util/manibuilder/Dockerfile.djgpp +++ b/util/manibuilder/Dockerfile.djgpp @@ -14,14 +14,14 @@ RUN cd && \ git clone https://git.kernel.org/pub/scm/utils/pciutils/pciutils.git && \ cd pciutils && \ git checkout v3.5.6 && \ - curl --insecure https://flashrom.org/images/6/6a/Pciutils-3.5.6.patch.gz | zcat | git apply && \ + curl -L --insecure https://flashrom.org/images/6/6a/Pciutils-3.5.6.patch.gz | zcat | git apply && \ make ZLIB=no DNS=no HOST=i386-djgpp-djgpp \ CROSS_COMPILE=i586-pc-msdosdjgpp- \ PREFIX=/ DESTDIR=$PWD/../ \ STRIP="--strip-program=i586-pc-msdosdjgpp-strip -s" \ install install-lib && \ cd ../ && \ - curl --insecure https://flashrom.org/images/3/3d/Libgetopt.tar.gz | zcat | tar x && \ + curl -L --insecure https://flashrom.org/images/3/3d/Libgetopt.tar.gz | zcat | tar x && \ cd libgetopt && \ make && cp libgetopt.a ../lib/ && cp getopt.h ../include/ diff --git a/util/manibuilder/Makefile b/util/manibuilder/Makefile index 98ed30c96..b1b982c49 100644 --- a/util/manibuilder/Makefile +++ b/util/manibuilder/Makefile @@ -56,7 +56,7 @@ $(ALL_TAGS): %: %-check-build --env IDENT=$(call ident,$*) \ --volume manicache:/home/mani/.ccache \ --name mani_$(call ident,$*) mani/$* \ - "git fetch origin $${TEST_REVISION:-master} && \ + "git fetch origin $${TEST_REVISION:-main} && \ git checkout FETCH_HEAD && \ $(MAKECMD) clean && $(MAKECMD) -j$${CPUS:-1} CC='$(CC)' \ $(if $(STRIP),STRIP='$(STRIP)') \ diff --git a/util/manibuilder/README.md b/util/manibuilder/README.md index b00d61818..e2ccd8180 100644 --- a/util/manibuilder/README.md +++ b/util/manibuilder/README.md @@ -38,7 +38,7 @@ Usage example ------------- The most common use case may be testing the current upstream -*master* branch which is the default for `$(TEST_REVISION)`. +*main* branch which is the default for `$(TEST_REVISION)`. You'll need roughly 20GiB for the *Docker* images. Might look like this: diff --git a/w29ee011.c b/w29ee011.c index a570bd6d1..234b865c8 100644 --- a/w29ee011.c +++ b/w29ee011.c @@ -15,9 +15,24 @@ */ #include +#include + #include "flash.h" #include "chipdrivers.h" +bool w29ee011_can_override(const char *const chip_name, const char *const override_chip) +{ + if (!override_chip || strcmp(override_chip, chip_name)) { + msg_cdbg("Old Winbond W29* probe method disabled because " + "the probing sequence puts the AMIC A49LF040A in " + "a funky state. Use 'flashrom -c %s' if you " + "have a board with such a chip.\n", chip_name); + return false; + } + + return true; +} + /* According to the Winbond W29EE011, W29EE012, W29C010M, W29C011A * datasheets this is the only valid probe function for those chips. */ @@ -26,27 +41,19 @@ int probe_w29ee011(struct flashctx *flash) chipaddr bios = flash->virtual_memory; uint8_t id1, id2; - if (!chip_to_probe || strcmp(chip_to_probe, flash->chip->name)) { - msg_cdbg("Old Winbond W29* probe method disabled because " - "the probing sequence puts the AMIC A49LF040A in " - "a funky state. Use 'flashrom -c %s' if you " - "have a board with such a chip.\n", flash->chip->name); - return 0; - } - /* Issue JEDEC Product ID Entry command */ chip_writeb(flash, 0xAA, bios + 0x5555); - programmer_delay(10); + programmer_delay(flash, 10); chip_writeb(flash, 0x55, bios + 0x2AAA); - programmer_delay(10); + programmer_delay(flash, 10); chip_writeb(flash, 0x80, bios + 0x5555); - programmer_delay(10); + programmer_delay(flash, 10); chip_writeb(flash, 0xAA, bios + 0x5555); - programmer_delay(10); + programmer_delay(flash, 10); chip_writeb(flash, 0x55, bios + 0x2AAA); - programmer_delay(10); + programmer_delay(flash, 10); chip_writeb(flash, 0x60, bios + 0x5555); - programmer_delay(10); + programmer_delay(flash, 10); /* Read product ID */ id1 = chip_readb(flash, bios); @@ -54,11 +61,11 @@ int probe_w29ee011(struct flashctx *flash) /* Issue JEDEC Product ID Exit command */ chip_writeb(flash, 0xAA, bios + 0x5555); - programmer_delay(10); + programmer_delay(flash, 10); chip_writeb(flash, 0x55, bios + 0x2AAA); - programmer_delay(10); + programmer_delay(flash, 10); chip_writeb(flash, 0xF0, bios + 0x5555); - programmer_delay(10); + programmer_delay(flash, 10); msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2); diff --git a/w39.c b/w39.c index f58c495d1..114d0b563 100644 --- a/w39.c +++ b/w39.c @@ -27,7 +27,7 @@ static uint8_t w39_idmode_readb(struct flashctx *flash, unsigned int offset) chip_writeb(flash, 0xAA, bios + 0x5555); chip_writeb(flash, 0x55, bios + 0x2AAA); chip_writeb(flash, 0x90, bios + 0x5555); - programmer_delay(10); + programmer_delay(flash, 10); /* Read something, maybe hardware lock bits */ val = chip_readb(flash, bios + offset); @@ -36,7 +36,7 @@ static uint8_t w39_idmode_readb(struct flashctx *flash, unsigned int offset) chip_writeb(flash, 0xAA, bios + 0x5555); chip_writeb(flash, 0x55, bios + 0x2AAA); chip_writeb(flash, 0xF0, bios + 0x5555); - programmer_delay(10); + programmer_delay(flash, 10); return val; } diff --git a/wbsio_spi.c b/wbsio_spi.c index 661ecbb11..9f33b18de 100644 --- a/wbsio_spi.c +++ b/wbsio_spi.c @@ -155,7 +155,7 @@ static int wbsio_spi_send_command(const struct flashctx *flash, unsigned int wri OUTB(writearr[0], data->spibase); OUTB(mode, data->spibase + 1); - programmer_delay(10); + default_delay(10); if (!readcnt) return 0; @@ -186,17 +186,15 @@ static const struct spi_master spi_master_wbsio = { .max_data_read = MAX_DATA_UNSPECIFIED, .max_data_write = MAX_DATA_UNSPECIFIED, .command = wbsio_spi_send_command, - .multicommand = default_spi_send_multicommand, .map_flash_region = physmap, .unmap_flash_region = physunmap, .read = wbsio_spi_read, .write_256 = spi_chip_write_1, .write_aai = spi_chip_write_1, .shutdown = wbsio_spi_shutdown, - .probe_opcode = default_spi_probe_opcode, }; -int wbsio_check_for_spi(void) +int wbsio_check_for_spi(struct board_cfg *cfg) { uint16_t wbsio_spibase = 0; diff --git a/writeprotect.c b/writeprotect.c index 57d0f9bd6..411089def 100644 --- a/writeprotect.c +++ b/writeprotect.c @@ -19,6 +19,7 @@ #include #include +#include "spi.h" #include "flash.h" #include "libflashrom.h" #include "chipdrivers.h" @@ -30,18 +31,38 @@ */ static int wp_write_register(const struct flashctx *flash, enum flash_reg reg, uint8_t value) { + int ret; if ((flash->mst->buses_supported & BUS_PROG) && flash->mst->opaque.write_register) { - return flash->mst->opaque.write_register(flash, reg, value); + ret = flash->mst->opaque.write_register(flash, reg, value); + } else { + ret = spi_write_register(flash, reg, value); + } + + /* Writing SR1 should always be supported, ignore errors for other registers. */ + if (ret == SPI_INVALID_OPCODE && reg != STATUS1) { + msg_pdbg("%s: write to register %d not supported by programmer, ignoring.\n", __func__, reg); + ret = 0; } - return spi_write_register(flash, reg, value); + return ret; } static int wp_read_register(const struct flashctx *flash, enum flash_reg reg, uint8_t *value) { + int ret; if ((flash->mst->buses_supported & BUS_PROG) && flash->mst->opaque.read_register) { - return flash->mst->opaque.read_register(flash, reg, value); + ret = flash->mst->opaque.read_register(flash, reg, value); + } else { + ret = spi_read_register(flash, reg, value); } - return spi_read_register(flash, reg, value); + + /* Reading SR1 should always be supported, ignore errors for other registers. */ + if (ret == SPI_INVALID_OPCODE && reg != STATUS1) { + msg_pdbg("%s: read from register %d not is supported by programmer, " + "writeprotect operations will assume it contains 0x00.\n", __func__, reg); + *value = 0; + ret = 0; + } + return ret; } /** Read and extract a single bit from the chip's registers */ @@ -73,6 +94,25 @@ static enum flashrom_wp_result read_wp_bits(struct wp_bits *bits, struct flashct size_t i; enum flashrom_wp_result ret; + /* + * Write protection select bit (WPS) controls kind of write protection + * that is used by the chip. When set, BP bits are ignored and each + * block/sector has its own WP bit managed by special commands. When + * the bit is set and we can't change it, just bail out until + * implementation is extended to handle this kind of WP. + */ + if (bit_map->wps.reg != INVALID_REG && bit_map->wps.writability != RW) { + bool wps_bit_present; + uint8_t wps; + + ret = read_bit(&wps, &wps_bit_present, flash, bit_map->wps); + if (ret != FLASHROM_WP_OK) + return ret; + + if (wps_bit_present && wps) + return FLASHROM_WP_ERR_UNSUPPORTED_STATE; + } + ret = read_bit(&bits->tb, &bits->tb_bit_present, flash, bit_map->tb); if (ret != FLASHROM_WP_OK) return ret; @@ -93,8 +133,6 @@ static enum flashrom_wp_result read_wp_bits(struct wp_bits *bits, struct flashct if (ret != FLASHROM_WP_OK) return ret; - /* Note: WPS bit isn't read here, because it's not part of any range. */ - for (i = 0; i < ARRAY_SIZE(bits->bp); i++) { if (bit_map->bp[i].reg == INVALID_REG) break; @@ -108,39 +146,51 @@ static enum flashrom_wp_result read_wp_bits(struct wp_bits *bits, struct flashct return ret; } -/** Helper function for write_wp_bits(). */ +/** Helper function for get_wp_bits_reg_values(). */ static void set_reg_bit( - uint8_t *reg_values, uint8_t *write_masks, + uint8_t *reg_values, uint8_t *bit_masks, uint8_t *write_masks, struct reg_bit_info bit, uint8_t value) { if (bit.reg != INVALID_REG) { reg_values[bit.reg] |= value << bit.bit_index; - write_masks[bit.reg] |= 1 << bit.bit_index; + bit_masks[bit.reg] |= 1 << bit.bit_index; + + /* Avoid RO and OTP bits causing a register update */ + if (bit.writability == RW) + write_masks[bit.reg] |= 1 << bit.bit_index; } } +/** Convert wp_bits to register values and write masks */ +static void get_wp_bits_reg_values( + uint8_t *reg_values, uint8_t *bit_masks, uint8_t *write_masks, + const struct reg_bit_map *reg_bits, struct wp_bits bits) +{ + memset(reg_values, 0, sizeof(uint8_t) * MAX_REGISTERS); + memset(bit_masks, 0, sizeof(uint8_t) * MAX_REGISTERS); + memset(write_masks, 0, sizeof(uint8_t) * MAX_REGISTERS); + + for (size_t i = 0; i < bits.bp_bit_count; i++) + set_reg_bit(reg_values, bit_masks, write_masks, reg_bits->bp[i], bits.bp[i]); + + set_reg_bit(reg_values, bit_masks, write_masks, reg_bits->tb, bits.tb); + set_reg_bit(reg_values, bit_masks, write_masks, reg_bits->sec, bits.sec); + set_reg_bit(reg_values, bit_masks, write_masks, reg_bits->cmp, bits.cmp); + set_reg_bit(reg_values, bit_masks, write_masks, reg_bits->srp, bits.srp); + set_reg_bit(reg_values, bit_masks, write_masks, reg_bits->srl, bits.srl); + /* Note: always setting WPS bit to zero until its fully supported. */ + set_reg_bit(reg_values, bit_masks, write_masks, reg_bits->wps, 0); +} + /** Write WP configuration bits to the flash's registers. */ static enum flashrom_wp_result write_wp_bits(struct flashctx *flash, struct wp_bits bits) { - size_t i; - const struct reg_bit_map *reg_bits = &flash->chip->reg_bits; - - /* Convert wp_bits to register values and write masks */ - uint8_t reg_values[MAX_REGISTERS] = {0}; - uint8_t write_masks[MAX_REGISTERS] = {0}; + uint8_t reg_values[MAX_REGISTERS]; + uint8_t bit_masks[MAX_REGISTERS]; /* masks of valid bits */ + uint8_t write_masks[MAX_REGISTERS]; /* masks of written bits */ + get_wp_bits_reg_values(reg_values, bit_masks, write_masks, &flash->chip->reg_bits, bits); - for (i = 0; i < bits.bp_bit_count; i++) - set_reg_bit(reg_values, write_masks, reg_bits->bp[i], bits.bp[i]); - - set_reg_bit(reg_values, write_masks, reg_bits->tb, bits.tb); - set_reg_bit(reg_values, write_masks, reg_bits->sec, bits.sec); - set_reg_bit(reg_values, write_masks, reg_bits->cmp, bits.cmp); - set_reg_bit(reg_values, write_masks, reg_bits->srp, bits.srp); - set_reg_bit(reg_values, write_masks, reg_bits->srl, bits.srl); - /* Note: always setting WPS bit to zero until its fully supported. */ - set_reg_bit(reg_values, write_masks, reg_bits->wps, 0); - - /* Write each register */ + /* Write each register whose value was updated */ for (enum flash_reg reg = STATUS1; reg < MAX_REGISTERS; reg++) { if (!write_masks[reg]) continue; @@ -149,36 +199,65 @@ static enum flashrom_wp_result write_wp_bits(struct flashctx *flash, struct wp_b if (wp_read_register(flash, reg, &value)) return FLASHROM_WP_ERR_READ_FAILED; - value = (value & ~write_masks[reg]) | (reg_values[reg] & write_masks[reg]); + /* Skip unnecessary register writes */ + uint8_t actual = value & write_masks[reg]; + uint8_t expected = reg_values[reg] & write_masks[reg]; + if (actual == expected) + continue; + + value = (value & ~write_masks[reg]) | expected; if (wp_write_register(flash, reg, value)) return FLASHROM_WP_ERR_WRITE_FAILED; } - /* Verify each register */ + enum flashrom_wp_result ret = FLASHROM_WP_OK; + /* Verify each register even if write to it was skipped */ for (enum flash_reg reg = STATUS1; reg < MAX_REGISTERS; reg++) { - if (!write_masks[reg]) + if (!bit_masks[reg]) continue; uint8_t value; if (wp_read_register(flash, reg, &value)) return FLASHROM_WP_ERR_READ_FAILED; - uint8_t actual = value & write_masks[reg]; - uint8_t expected = reg_values[reg] & write_masks[reg]; + msg_cdbg2("%s: wp_verify reg:%u value:0x%x\n", __func__, reg, value); + uint8_t actual = value & bit_masks[reg]; + uint8_t expected = reg_values[reg] & bit_masks[reg]; - if (actual != expected) - return FLASHROM_WP_ERR_VERIFY_FAILED; + if (actual != expected) { + msg_cdbg("%s: wp_verify failed: reg:%u actual:0x%x expected:0x%x\n", + __func__, reg, actual, expected); + ret = FLASHROM_WP_ERR_VERIFY_FAILED; + } } - return FLASHROM_WP_OK; + return ret; } +static decode_range_func_t *lookup_decode_range_func_ptr(const struct flashchip *chip) +{ + switch (chip->decode_range) { + case DECODE_RANGE_SPI25: return &decode_range_spi25; + case DECODE_RANGE_SPI25_64K_BLOCK: return &decode_range_spi25_64k_block; + case DECODE_RANGE_SPI25_BIT_CMP: return &decode_range_spi25_bit_cmp; + case DECODE_RANGE_SPI25_2X_BLOCK: return &decode_range_spi25_2x_block; + /* default: total function, 0 indicates no decode range function set. */ + case NO_DECODE_RANGE_FUNC: return NULL; + }; + + return NULL; +} + + /** Get the range selected by a WP configuration. */ static enum flashrom_wp_result get_wp_range(struct wp_range *range, struct flashctx *flash, const struct wp_bits *bits) { - flash->chip->decode_range(&range->start, &range->len, bits, flashrom_flash_getsize(flash)); + decode_range_func_t *decode_range = lookup_decode_range_func_ptr(flash->chip); + if (decode_range == NULL) + return FLASHROM_WP_ERR_OTHER; + decode_range(&range->start, &range->len, bits, flashrom_flash_getsize(flash)); return FLASHROM_WP_OK; } @@ -424,7 +503,7 @@ static int set_wp_mode(struct wp_bits *bits, const enum flashrom_wp_mode mode) static bool chip_supported(struct flashctx *flash) { - return (flash->chip != NULL) && (flash->chip->decode_range != NULL); + return (flash->chip != NULL) && (flash->chip->decode_range != NO_DECODE_RANGE_FUNC); } @@ -518,3 +597,31 @@ enum flashrom_wp_result wp_get_available_ranges(struct flashrom_wp_ranges **list free(range_pairs); return ret; } + +enum flashrom_wp_result wp_cfg_to_reg_values( + uint8_t *reg_values, uint8_t *bit_masks, uint8_t *write_masks, + struct flashctx *flash, const struct flashrom_wp_cfg *cfg) +{ + struct wp_bits bits; + + if (!chip_supported(flash)) + return FLASHROM_WP_ERR_CHIP_UNSUPPORTED; + + enum flashrom_wp_result ret = read_wp_bits(&bits, flash); + if (ret != FLASHROM_WP_OK) + return ret; + + /* Set protection range */ + ret = set_wp_range(&bits, flash, cfg->range); + if (ret != FLASHROM_WP_OK) + return ret; + + /* Set protection mode */ + ret = set_wp_mode(&bits, cfg->mode); + if (ret != FLASHROM_WP_OK) + return ret; + + get_wp_bits_reg_values(reg_values, bit_masks, write_masks, &flash->chip->reg_bits, bits); + + return FLASHROM_WP_OK; +} diff --git a/writeprotect_ranges.c b/writeprotect_ranges.c index dacce322d..45678f22a 100644 --- a/writeprotect_ranges.c +++ b/writeprotect_ranges.c @@ -17,11 +17,11 @@ #include "writeprotect.h" #include "chipdrivers.h" -/* - * Protection range calculation that works with many common SPI flash chips. - */ -void decode_range_spi25(size_t *start, size_t *len, const struct wp_bits *bits, size_t chip_len) +static void decode_range_generic(size_t *start, size_t *len, const struct wp_bits *bits, size_t chip_len, + bool fixed_block_len, bool apply_cmp_to_bp, int coeff_offset) { + const bool cmp = bits->cmp_bit_present && bits->cmp == 1; + /* Interpret BP bits as an integer */ size_t bp = 0; size_t bp_max = 0; @@ -31,6 +31,15 @@ void decode_range_spi25(size_t *start, size_t *len, const struct wp_bits *bits, bp_max |= 1 << i; } + /* + * Most chips: the CMP bit only negates the range. + * + * Some MX chips: the CMP bit negates the BP bits and the range. + * (CMP bit is often the MSB BP bit in such chips.) + */ + if (cmp && apply_cmp_to_bp) + bp ^= bp_max; + if (bp == 0) { /* Special case: all BP bits are 0 => no write protection */ *len = 0; @@ -40,14 +49,14 @@ void decode_range_spi25(size_t *start, size_t *len, const struct wp_bits *bits, } else { /* * Usual case: the BP bits encode a coefficient in the form - * `coeff = 2 ** (bp - 1)`. + * `coeff = 2 ** (bp - offset)` where `offset == 1`. * * The range's length is given by multiplying the coefficient * by a base unit, usually a 4K sector or a 64K block. */ - size_t coeff = 1 << (bp - 1); - size_t max_coeff = 1 << (bp_max - 2); + size_t coeff = 1 << (bp - coeff_offset); + size_t max_coeff = 1 << (bp_max - coeff_offset - 1); size_t sector_len = 4 * KiB; size_t default_block_len = 64 * KiB; @@ -62,14 +71,19 @@ void decode_range_spi25(size_t *start, size_t *len, const struct wp_bits *bits, } else { /* * SEC=0 or is not present, protect blocks. - * + */ + size_t block_len = default_block_len; + + /* * With very large chips, the 'block' size can be * larger than 64K. This occurs when a larger block * size is needed so that half the chip can be * protected by the maximum possible coefficient. */ - size_t min_block_len = chip_len / 2 / max_coeff; - size_t block_len = max(min_block_len, default_block_len); + if (!fixed_block_len) { + size_t min_block_len = chip_len / 2 / max_coeff; + block_len = max(min_block_len, default_block_len); + } *len = min(block_len * coeff, chip_len); } @@ -79,7 +93,7 @@ void decode_range_spi25(size_t *start, size_t *len, const struct wp_bits *bits, bool protect_top = bits->tb_bit_present ? (bits->tb == 0) : 1; /* Apply CMP bit */ - if (bits->cmp_bit_present && bits->cmp == 1) { + if (cmp) { *len = chip_len - *len; protect_top = !protect_top; } @@ -90,3 +104,41 @@ void decode_range_spi25(size_t *start, size_t *len, const struct wp_bits *bits, else *start = 0; } + +/* + * Protection range calculation that works with many common SPI flash chips. + */ +void decode_range_spi25(size_t *start, size_t *len, const struct wp_bits *bits, size_t chip_len) +{ + decode_range_generic(start, len, bits, chip_len, + /*fixed_block_len=*/false, /*apply_cmp_to_bp=*/false, /*coeff_offset=*/1); +} + +/* + * Do not adjust block size to be able to fill half of the chip. + */ +void decode_range_spi25_64k_block(size_t *start, size_t *len, const struct wp_bits *bits, size_t chip_len) +{ + decode_range_generic(start, len, bits, chip_len, + /*fixed_block_len=*/true, /*apply_cmp_to_bp=*/false, /*coeff_offset=*/1); +} + +/* + * Inverts BP bits when CMP is set and treats all ones in BP bits as a request to protect whole chip regardless + * of the CMP bit. + */ +void decode_range_spi25_bit_cmp(size_t *start, size_t *len, const struct wp_bits *bits, size_t chip_len) +{ + decode_range_generic(start, len, bits, chip_len, + /*fixed_block_len=*/false, /*apply_cmp_to_bp=*/true, /*coeff_offset=*/1); +} + +/* + * This multiplies coefficient by 2. To be used with chips which have more BP bits than needed, such that the + * most significant BP bit effectively acts as "protect whole chip" flag. + */ +void decode_range_spi25_2x_block(size_t *start, size_t *len, const struct wp_bits *bits, size_t chip_len) +{ + decode_range_generic(start, len, bits, chip_len, + /*fixed_block_len=*/false, /*apply_cmp_to_bp=*/false, /*coeff_offset=*/0); +}