Tools & Common Procedures
Shared tools, wiring, and procedures used across all coreboot guides on this site. Individual guides reference sections here rather than duplicating them.
SPI Programmers
Do not use a CH341A unless you have confirmed it uses 3.3V logic on data lines. Many clones output 5V on MOSI/MISO/CLK which can damage the SPI flash and the PCH.
What You Need
| Item | Notes |
|---|---|
| SOIC-8 test clip | Pomona 5250 is best; generic clips work |
| Female–female Dupont wires | 10–15 wires |
| IPA (isopropyl alcohol) | Clean chip legs before clipping |
| Raspberry Pi 3/4/5 or Raspberry Pi Pico (RP2040) | See below for differences |
flashprog vs flashrom: Use flashprog (Libreboot’s fork of flashrom). It is more robust in practice — fewer detection failures, better chip support. Commands are identical; just replace
flashromwithflashprogin any guide. All examples on this site use flashprog.
Choosing a Programmer
Raspberry Pi 3/4/5 — the more convenient option. Runs headless with SSH, so you can flash from any terminal on your network while the Pi sits next to the open machine with all wires connected. No screen needed. Has two 3.3V pins (physical pins 1 and 17) making multi-wire distribution easy.
Raspberry Pi Pico (RP2040) — cheapest option but requires a host computer physically nearby running flashprog over USB serial. Only one 3.3V output pin (pin 36) which needs multi-way splits or a breadboard. Do not use Pico 2 (RP2350) — serprog stability issues.
Method A — Raspberry Pi 3B / 3B+ / 4
Parts:
| Item | Notes |
|---|---|
| Raspberry Pi 3B, 3B+, or 4 | Raspberry Pi OS Lite is fine |
| MicroSD card (8 GB+) | With Raspberry Pi OS flashed |
| 5V PSU | Stable power matters |
| Ethernet or WiFi | SSH in headless |
Enable SPI on the Pi
sudo raspi-config
Navigate to Interface Options → SPI and enable it. Reboot.
ls /dev/spidev*
# Should show: /dev/spidev0.0 /dev/spidev0.1
Build flashprog on the Pi
sudo apt install git build-essential libpci-dev libusb-1.0-0-dev libftdi1-dev \
libgpiod-dev meson ninja-build pkg-config
git clone https://review.sourcearcade.org/flashprog.git
cd flashprog
meson setup builddir
ninja -C builddir
sudo ninja -C builddir install
Verify:
sudo flashprog -p linux_spi:dev=/dev/spidev0.0,spispeed=512
# Expected: "No EEPROM/flash device found." — correct, nothing connected
Pi GPIO → SOIC-8 Wiring
Pi GPIO header: SOIC-8 chip:
Pin 24 — GPIO8/SPI0_CE0 ────────── Pin 1 (/CS)
Pin 21 — GPIO9/SPI0_MISO ───────── Pin 2 (MISO/DO)
Pin 17 — 3.3V ──────────┬────────── Pin 8 (VCC)
└──────────── (board-specific connections)
Pin 25 — GND ────────────────────── Pin 4 (GND)
Pin 19 — GPIO10/SPI0_MOSI ──────── Pin 5 (MOSI/DI)
Pin 23 — GPIO11/SPI0_SCLK ──────── Pin 6 (CLK)
| Pi Physical Pin | Pi Signal | SOIC-8 Pin | Signal | Required? |
|---|---|---|---|---|
| 24 | GPIO8 / CE0 | 1 | /CS | Yes |
| 21 | GPIO9 / MISO | 2 | MISO (DO) | Yes |
| 17 | 3.3V | 3 | /WP | No by default — see /WP and /HOLD Troubleshooting |
| 25 | GND | 4 | GND | Yes |
| 19 | GPIO10 / MOSI | 5 | MOSI (DI) | Yes |
| 23 | GPIO11 / SCLK | 6 | CLK | Yes |
| — | — | 7 | /HOLD | No by default — see /WP and /HOLD Troubleshooting |
| 17 | 3.3V | 8 | VCC | Yes |
Verify your wiring against Libreboot’s SPI guide before first use — it covers the Pi 3/4 GPIO pinout in detail and is the authoritative reference: https://libreboot.org/docs/install/spi.html
Pi flashprog command syntax
-p linux_spi:dev=/dev/spidev0.0,spispeed=1000
Method B — Raspberry Pi Pico (RP2040)
Flash serprog Firmware onto the Pico
Use Libreboot’s pico-serprog — it has multi-CS handling and tuned 12 mA drive strength.
git clone https://codeberg.org/libreboot/lbmk
cd lbmk
./mk dependencies debian
./mk -b pico-serprog
# Output: bin/serprog_pico/serprog_pico.uf2
Flash onto the Pico:
- Hold BOOTSEL, plug Pico into USB, release BOOTSEL — mounts as
RPI-RP2 cp bin/serprog_pico/serprog_pico.uf2 /media/$USER/RPI-RP2/- Pico reboots. Verify:
sudo dmesg | grep ttyACM→ttyACM0: USB ACM device
sudo usermod -aG dialout $USER # avoid sudo on every flashprog call (re-login after)
Install flashprog on the host machine:
sudo apt install flashprog
# If not available: sudo apt install flashrom (commands are identical)
Pico GPIO → SOIC-8 Wiring
Critical: GP3 = MOSI and GP5 = /CS. These are commonly documented in reverse. Using the wrong mapping gives garbage reads.
Pico (corner near USB):
Pin 4 — GP2 — SCK ──────────────── SOIC-8 Pin 6
Pin 5 — GP3 — MOSI ──────────────── SOIC-8 Pin 5
Pin 6 — GP4 — MISO ──────────────── SOIC-8 Pin 2
Pin 7 — GP5 — /CS ──────────────── SOIC-8 Pin 1
Pin 36 — 3V3(OUT) ──┬──────────────── SOIC-8 Pin 8 (VCC)
└───────────────── (board-specific connections)
Pin 38 — GND ──────────────────────── SOIC-8 Pin 4
| SOIC-8 Pin | Signal | Pico Physical Pin | Pico GPIO | Required? |
|---|---|---|---|---|
| 1 | /CS | Pin 7 | GP5 | Yes |
| 2 | MISO | Pin 6 | GP4 | Yes |
| 3 | /WP | — | — | No by default — see /WP and /HOLD Troubleshooting |
| 4 | GND | Pin 38 | GND | Yes |
| 5 | MOSI | Pin 5 | GP3 | Yes |
| 6 | SCK | Pin 4 | GP2 | Yes |
| 7 | /HOLD | — | — | No by default — see /WP and /HOLD Troubleshooting |
| 8 | VCC | Pin 36 | 3V3(OUT) | Yes |
Pin 37 (3V3_EN) is NOT a power output — do not use it.
Pico flashprog command syntax
-p serprog:dev=/dev/ttyACM0,spispeed=16M
SOIC-8 Pinout Reference
┌───────┐
/CS 1│● │8 VCC
DO 2│ │7 /HOLD
/WP 3│ │6 CLK
GND 4│ │5 DI
└───────┘
Pin 1 = dot on IC package. Pin numbering goes anti-clockwise.
Triple-Read Methodology
Always take three reads of every chip. All three SHA256 checksums must match before proceeding. If they don’t, reseat the clip, clean chip legs with IPA, and read again.
# Example (adjust programmer, chip string, and filename per your board)
sudo flashprog -p <programmer> -c "<chip>" -r dump1.bin
sudo flashprog -p <programmer> -c "<chip>" -r dump2.bin
sudo flashprog -p <programmer> -c "<chip>" -r dump3.bin
sha256sum dump*.bin
# All three MUST match
Troubleshooting inconsistent reads:
- Clean chip legs with IPA
- Try lower speed:
spispeed=512(Pi) orspispeed=4M(Pico) - Specify chip explicitly:
flashprog ... -c "<chip_string>" - On dual-chip boards: confirm idle chip’s /CS is held high
- Try different /WP and /HOLD states — see below
/WP and /HOLD Troubleshooting
Rule of thumb: do not hold /WP (pin 3) or /HOLD (pin 7) high by default. Many boards have on-board pull-ups on these lines, and actively driving them can sometimes interfere. Start with only the six core connections (VCC, GND, /CS, MOSI, MISO, CLK) and leave /WP and /HOLD floating.
If reads are inconsistent, writes fail, or the chip is not detected, work through these /WP and /HOLD combinations until one works:
| /WP (pin 3) | /HOLD (pin 7) | Try when |
|---|---|---|
| floating | floating | Start here — default, no extra wires |
| HIGH (3.3V) | floating | Writes fail or chip reports write-protected |
| floating | HIGH (3.3V) | Reads corrupt mid-transfer, chip pauses randomly |
| HIGH (3.3V) | HIGH (3.3V) | Both issues, or nothing else works |
Both /WP and /HOLD are active-low signals. Driving them high is always electrically safe — it cannot damage the chip. Driving them high simply ensures write-protect is disabled (/WP) and the chip never pauses (/HOLD).
Some boards pull these lines high through on-board resistors and do not need external wiring. Others leave them floating or weakly pulled, and the state becomes marginal — especially with longer clip wires acting as antennas. If you see intermittent failures that cleaning and speed changes don’t fix, /WP and /HOLD state is the next thing to try.
Per-board notes: Individual guides note which /WP and /HOLD wiring is confirmed working for that board. The combinations above are a general fallback when the default doesn’t work or when working with a board not covered by these guides.
ifdtool — Extract Flash Regions
Build ifdtool from the coreboot tree:
git clone https://review.coreboot.org/coreboot.git
cd coreboot
git submodule update --init --checkout
cd util/ifdtool && make && cd ../..
Extract regions from a full flash dump:
util/ifdtool/ifdtool -x <dump.bin> # Haswell / Broadwell
util/ifdtool/ifdtool -p cnl -x <dump.bin> # Coffee Lake (Cannon Lake PCH)
Produces:
| Output File | Contents |
|---|---|
flashregion_0_flashdescriptor.bin | Intel Flash Descriptor |
flashregion_1_bios.bin | BIOS region |
flashregion_2_intel_me.bin | Intel CSME firmware |
flashregion_3_gbe.bin | Gigabit Ethernet NVM (contains MAC address) |
Build Dependencies (Debian / Ubuntu)
sudo apt install -y \
build-essential gnat flex bison libncurses-dev wget zlib1g-dev \
git python3 libelf-dev nasm pkg-config libssl-dev m4 iasl acpica-tools curl
The W541 guide additionally uses:
imagemagick gcc-multilib libc6-dev-i386 unifont
Cross-Compiler Toolchain
Build once per coreboot checkout:
cd coreboot
make crossgcc-i386 CPUS=$(nproc)
# Takes 30–90 minutes on first run
Internal Re-Flashing (Subsequent Updates)
Once running coreboot, subsequent updates can be done internally without an external programmer.
Single-chip boards (e.g. T580):
sudo flashrom -p internal -w coreboot.rom
Multi-chip boards writing BIOS region only (e.g. M920q):
sudo flashrom -p internal -N -w coreboot.rom --ifd -i bios
Full ROM write (e.g. W541):
sudo flashprog -p internal -w build/coreboot.rom
If your kernel restricts iomem access:
# Add to GRUB_CMDLINE_LINUX in /etc/default/grub:
GRUB_CMDLINE_LINUX="iomem=relaxed"
sudo update-grub
# Reboot, then retry
Internal flashing uses the full combined ROM — no splitting needed.
Programmer Comparison
| Raspberry Pi 3/4 | Raspberry Pi Pico | |
|---|---|---|
| Read speed | ~500 KB/s at 1 MHz | ~2 MB/s at 16 MHz |
| 3.3V pins | 2 (pins 1 and 17) — easy multi-wire crimps | 1 (pin 36) — needs multi-way split or breadboard |
| flashprog interface | linux_spi (native kernel driver) | serprog (USB serial) |
| Setup | Full OS, raspi-config, build flashprog | Flash UF2, done |
| Remote flashing | Yes — headless SSH from any terminal | No — host computer must be physically nearby |
| Verdict | More convenient overall | Cheapest, fastest reads |
References
- Libreboot SPI flashing guide — authoritative wiring reference for Pi 3/4 and Pico
- flashprog
- pico-serprog (Libreboot fork)
- Coreboot FAQ — ME and HAP bit