Skip to main content

External Flashing

External flashing is sometimes necessary instead of internal flashing. The main reasons are:

  • Neutralizing Intel ME: Internal flashing can’t access the ME region on stock firmware, so an external flash is required the first time if you want to disable or neutralize Intel ME.
  • Recovery: If an internal flash fails and the laptop no longer boots, an external programmer is the only way to restore the system.
  • Hardware restrictions: Some motherboards simply don’t allow internal flashing at all, so external flashing is the only option.

Detect the Chip​

Now, you need to detect the chip model using flashrom. To ensure accurate detection, follow these steps for the BIOS chip:

  • Prepare your Raspberry Pi Pico with Serprog as explained in the Libreboot guide
  • Based on your BIOS Chip type (SOIC or WSON) Connect the Raspberry Pico to your Pomona Clip (1st photo) or Pogo Pin Adapter (2nd photo) using Dupont cables, as explained in Libreboot guide.
  • Attach the clip firmly onto the BIOS chip, ensuring proper contact with all pins
  • Plug the Raspberry Pico into the laptop using a USB cable
Connection Setup
Connection Clip

Execute the following command to detect the chip

sudo flashrom -p serprog:dev=/dev/ttyACM0,spispeed=16M

If multiple chips are detected, identify the correct BIOS chip based on prior photos or markings. Subsequently, re-run the command, making sure to specify the name of the pertinent chip.

sudo flashrom -p serprog:dev=/dev/ttyACM0,spispeed=16M -c "W25Q128.V"

If the Raspberry Pico detects the chip, you may proceed by creating a backup.

Backup the Factory Bios​

note

If you are coming from a unsuccessful internal flashing, you can skip this part as there is no point to dump a bios that does not work.

To create a reliable backup of the BIOS chip(s), it's advisable to perform a triple dump of them

sudo flashrom -p serprog:dev=/dev/ttyACM0,spispeed=16M -c "W25Q128.V" -r factory.bin
sudo flashrom -p serprog:dev=/dev/ttyACM0,spispeed=16M -c "W25Q128.V" -r factory2.bin
sudo flashrom -p serprog:dev=/dev/ttyACM0,spispeed=16M -c "W25Q128.V" -r factory3.bin

Next, use sha1sum to compare the dumped BIOS images

sha1sum factory.bin factory2.bin factory3.bin

If the hashes match, you should see something like this:

6cf9bfc90df1ed01336872cd159a00c101d0a7b0  factory.bin
6cf9bfc90df1ed01336872cd159a00c101d0a7b0 factory2.bin
6cf9bfc90df1ed01336872cd159a00c101d0a7b0 factory3.bin

Once you've confirmed that the hashes are the same, you can clean up any temporary dump files:

rm -fr factory2.bin factory3.bin

Neutralize Intel ME​

Check if the dumped image has the correct structure by using ifdtool:

cd coreboot/util/ifdtool
make
./ifdtool -d factory.bin

It should print a long output, including the section related to Intel ME:

Output

Warning: No platform specified. Output may be incomplete
File t430s_full_dump_coreboot.bin is 16777216 bytes
PCH Revision: 6 series Cougar Point
FLMAP0: 0x03040003
NR: 3
FRBA: 0x40
NC: 1
FCBA: 0x30
FLMAP1: 0x12100206
ISL: 0x12
FPSBA: 0x100
NM: 2
FMBA: 0x60
FLMAP2: 0x00210120
PSL: 0x2101
FMSBA: 0x200
FLUMAP1: 0x000018df
Intel ME VSCC Table Length (VTL): 24
Intel ME VSCC Table Base Address (VTBA): 0x000df0

ME VSCC table:
JID0: 0x001620c2
SPI Component Vendor ID: 0xc2
SPI Component Device ID 0: 0x20
SPI Component Device ID 1: 0x16
VSCC0: 0x20052005
Lower Erase Opcode: 0x20
Lower Write Enable on Write Status: 0x50
Lower Write Status Required: No
Lower Write Granularity: 64 bytes
Lower Block / Sector Erase Size: 4KB
Upper Erase Opcode: 0x20
Upper Write Enable on Write Status: 0x50
Upper Write Status Required: No
Upper Write Granularity: 64 bytes
Upper Block / Sector Erase Size: 4KB
JID1: 0x001720c2
SPI Component Vendor ID: 0xc2
SPI Component Device ID 0: 0x20
SPI Component Device ID 1: 0x17
VSCC1: 0x20052005
Lower Erase Opcode: 0x20
Lower Write Enable on Write Status: 0x50
Lower Write Status Required: No
Lower Write Granularity: 64 bytes
Lower Block / Sector Erase Size: 4KB
Upper Erase Opcode: 0x20
Upper Write Enable on Write Status: 0x50
Upper Write Status Required: No
Upper Write Granularity: 64 bytes
Upper Block / Sector Erase Size: 4KB
JID2: 0x001820c2
SPI Component Vendor ID: 0xc2
SPI Component Device ID 0: 0x20
SPI Component Device ID 1: 0x18
VSCC2: 0x20052005
Lower Erase Opcode: 0x20
Lower Write Enable on Write Status: 0x50
Lower Write Status Required: No
Lower Write Granularity: 64 bytes
Lower Block / Sector Erase Size: 4KB
Upper Erase Opcode: 0x20
Upper Write Enable on Write Status: 0x50
Upper Write Status Required: No
Upper Write Granularity: 64 bytes
Upper Block / Sector Erase Size: 4KB
JID3: 0x001640ef
SPI Component Vendor ID: 0xef
SPI Component Device ID 0: 0x40
SPI Component Device ID 1: 0x16
VSCC3: 0x20052005
Lower Erase Opcode: 0x20
Lower Write Enable on Write Status: 0x50
Lower Write Status Required: No
Lower Write Granularity: 64 bytes
Lower Block / Sector Erase Size: 4KB
Upper Erase Opcode: 0x20
Upper Write Enable on Write Status: 0x50
Upper Write Status Required: No
Upper Write Granularity: 64 bytes
Upper Block / Sector Erase Size: 4KB
JID4: 0x001740ef
SPI Component Vendor ID: 0xef
SPI Component Device ID 0: 0x40
SPI Component Device ID 1: 0x17
VSCC4: 0x20052005
Lower Erase Opcode: 0x20
Lower Write Enable on Write Status: 0x50
Lower Write Status Required: No
Lower Write Granularity: 64 bytes
Lower Block / Sector Erase Size: 4KB
Upper Erase Opcode: 0x20
Upper Write Enable on Write Status: 0x50
Upper Write Status Required: No
Upper Write Granularity: 64 bytes
Upper Block / Sector Erase Size: 4KB
JID5: 0x001840ef
SPI Component Vendor ID: 0xef
SPI Component Device ID 0: 0x40
SPI Component Device ID 1: 0x18
VSCC5: 0x20052005
Lower Erase Opcode: 0x20
Lower Write Enable on Write Status: 0x50
Lower Write Status Required: No
Lower Write Granularity: 64 bytes
Lower Block / Sector Erase Size: 4KB
Upper Erase Opcode: 0x20
Upper Write Enable on Write Status: 0x50
Upper Write Status Required: No
Upper Write Granularity: 64 bytes
Upper Block / Sector Erase Size: 4KB
JID6: 0x0016ba20
SPI Component Vendor ID: 0x20
SPI Component Device ID 0: 0xba
SPI Component Device ID 1: 0x16
VSCC6: 0x20052005
Lower Erase Opcode: 0x20
Lower Write Enable on Write Status: 0x50
Lower Write Status Required: No
Lower Write Granularity: 64 bytes
Lower Block / Sector Erase Size: 4KB
Upper Erase Opcode: 0x20
Upper Write Enable on Write Status: 0x50
Upper Write Status Required: No
Upper Write Granularity: 64 bytes
Upper Block / Sector Erase Size: 4KB
JID7: 0x0017ba20
SPI Component Vendor ID: 0x20
SPI Component Device ID 0: 0xba
SPI Component Device ID 1: 0x17
VSCC7: 0x20052005
Lower Erase Opcode: 0x20
Lower Write Enable on Write Status: 0x50
Lower Write Status Required: No
Lower Write Granularity: 64 bytes
Lower Block / Sector Erase Size: 4KB
Upper Erase Opcode: 0x20
Upper Write Enable on Write Status: 0x50
Upper Write Status Required: No
Upper Write Granularity: 64 bytes
Upper Block / Sector Erase Size: 4KB

OEM Section:
00: 47 31 52 4e 31 36 57 57 ff 38 2e 31 2e 34 30 2e
10: 31 34 31 36 ff 31 36 4d 42 ff 53 49 47 4e 45 44
20: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

Found Region Section
FLREG0: 0x00000000
Flash Region 0 (Flash Descriptor): 00000000 - 00000fff
FLREG1: 0x0fff0500
Flash Region 1 (BIOS): 00500000 - 00ffffff
FLREG2: 0x04ff0003
Flash Region 2 (Intel ME): 00003000 - 004fffff
FLREG3: 0x00020001
Flash Region 3 (GbE): 00001000 - 00002fff
FLREG4: 0x00001fff
Flash Region 4 (Platform Data): 00fff000 - 00000fff (unused)

Found Component Section
FLCOMP 0x4990001d
Dual Output Fast Read Support: supported
Read ID/Read Status Clock Frequency: 33MHz
Write/Erase Clock Frequency: 33MHz
Fast Read Clock Frequency: 50MHz
Fast Read Support: supported
Read Clock Frequency: 20MHz
Component 2 Density: 4MB
Component 1 Density: 16MB
FLILL 0x00000000
Invalid Instruction 3: 0x00
Invalid Instruction 2: 0x00
Invalid Instruction 1: 0x00
Invalid Instruction 0: 0x00
FLPB 0x00000000
Flash Partition Boundary Address: 0x000000

Found PCH Strap Section
PCHSTRP0 : 0x4810d782
PCHSTRP1 : 0x0000010f
PCHSTRP2 : 0x00000000
PCHSTRP3 : 0x00000000
PCHSTRP4 : 0x00c8e102
PCHSTRP5 : 0x00000000
PCHSTRP6 : 0x00000000
PCHSTRP7 : 0x00000000
PCHSTRP8 : 0x00000000
PCHSTRP9 : 0x30000b8c
PCHSTRP10 : 0x00410044
PCHSTRP11 : 0x99000097
PCHSTRP12 : 0x00000000
PCHSTRP13 : 0x00000000
PCHSTRP14 : 0x00000000
PCHSTRP15 : 0x0000437e
PCHSTRP16 : 0x00000000
PCHSTRP17 : 0x00000002
AltMeDisable bit is not set

Found Master Section
FLMSTR1: 0x0a0b0000 (Host CPU/BIOS)
Platform Data Region Write Access: disabled
GbE Region Write Access: enabled
Intel ME Region Write Access: disabled
Host CPU/BIOS Region Write Access: enabled
Flash Descriptor Write Access: disabled
Platform Data Region Read Access: disabled
GbE Region Read Access: enabled
Intel ME Region Read Access: disabled
Host CPU/BIOS Region Read Access: enabled
Flash Descriptor Read Access: enabled
Requester ID: 0x0000

FLMSTR2: 0x0c0d0000 (Intel ME)
Platform Data Region Write Access: disabled
GbE Region Write Access: enabled
Intel ME Region Write Access: enabled
Host CPU/BIOS Region Write Access: disabled
Flash Descriptor Write Access: disabled
Platform Data Region Read Access: disabled
GbE Region Read Access: enabled
Intel ME Region Read Access: enabled
Host CPU/BIOS Region Read Access: disabled
Flash Descriptor Read Access: enabled
Requester ID: 0x0000

FLMSTR3: 0x08080118 (GbE)
Platform Data Region Write Access: disabled
GbE Region Write Access: enabled
Intel ME Region Write Access: disabled
Host CPU/BIOS Region Write Access: disabled
Flash Descriptor Write Access: disabled
Platform Data Region Read Access: disabled
GbE Region Read Access: enabled
Intel ME Region Read Access: disabled
Host CPU/BIOS Region Read Access: disabled
Flash Descriptor Read Access: disabled
Requester ID: 0x0118

Found Processor Strap Section
????: 0x00000000
????: 0xffffffff
????: 0xffffffff
????: 0xffffffff
????: 0xffffffff
????: 0xffffffff
????: 0xffffffff
????: 0xffffffff

Now to check if the dumped ME image is valid just run:

python me_cleaner.py -c factory.bin

You should get an output like the one below:

Output

Full image detected
The ME/TXE region goes from 0x3000 to 0x500000
Found FPT header at 0x3010
Found 23 partition(s)
Found FTPR header: FTPR partition spans from 0x180000 to 0x24a000
ME/TXE firmware version 8.1.40.1416
Public key match: Intel ME, firmware versions 7.x.x.x, 8.x.x.x
The AltMeDisable bit is NOT SET
Checking the FTPR RSA signature... VALID

Apply me_cleaner

To neutralize Intel ME you can just use me_cleaner on it:

python me_cleaner.py -S -O factory_me_neutralized.bin factory.bin

You should get an output like the one below:

Output

Full image detected
The ME/TXE region goes from 0x3000 to 0x500000
Found FPT header at 0x3010
Found 23 partition(s)
Found FTPR header: FTPR partition spans from 0x180000 to 0x24a000
ME/TXE firmware version 8.1.40.1416
Public key match: Intel ME, firmware versions 7.x.x.x, 8.x.x.x
The AltMeDisable bit is NOT SET
Reading partitions list...
???? (0x000003c0 - 0x000000400, 0x00000040 total bytes): removed
FOVD (0x00000400 - 0x000001000, 0x00000c00 total bytes): removed
MDES (0x00001000 - 0x000002000, 0x00001000 total bytes): removed
FCRS (0x00002000 - 0x000003000, 0x00001000 total bytes): removed
EFFS (0x00003000 - 0x0000df000, 0x000dc000 total bytes): removed
BIAL (NVRAM partition, no data, 0x0000add0 total bytes): nothing to remove
BIEL (NVRAM partition, no data, 0x00003000 total bytes): nothing to remove
BIIS (NVRAM partition, no data, 0x00036000 total bytes): nothing to remove
NVCL (NVRAM partition, no data, 0x00010511 total bytes): nothing to remove
NVCM (NVRAM partition, no data, 0x0000493f total bytes): nothing to remove
NVCP (NVRAM partition, no data, 0x0000a553 total bytes): nothing to remove
NVJC (NVRAM partition, no data, 0x00004000 total bytes): nothing to remove
NVKR (NVRAM partition, no data, 0x0001257d total bytes): nothing to remove
NVOS (NVRAM partition, no data, 0x00034af5 total bytes): nothing to remove
NVSH (NVRAM partition, no data, 0x00007609 total bytes): nothing to remove
NVTD (NVRAM partition, no data, 0x00001eac total bytes): nothing to remove
PLDM (NVRAM partition, no data, 0x0000a000 total bytes): nothing to remove
GLUT (0x000df000 - 0x0000e3000, 0x00004000 total bytes): removed
LOCL (0x000e3000 - 0x0000e7000, 0x00004000 total bytes): removed
WCOD (0x000e7000 - 0x000140000, 0x00059000 total bytes): removed
MDMV (0x00140000 - 0x000180000, 0x00040000 total bytes): removed
FTPR (0x00180000 - 0x00024a000, 0x000ca000 total bytes): NOT removed
NFTP (0x0024a000 - 0x0004a4000, 0x0025a000 total bytes): removed
Removing partition entries in FPT...
Removing EFFS presence flag...
Correcting checksum (0x2f)...
Reading FTPR modules list...
UPDATE (LZMA , 0x1cc507 - 0x1cc6c5 ): removed
ROMP (Huffman, fragmented data, ~2 KiB ): NOT removed, essential
BUP (Huffman, fragmented data, ~56 KiB ): NOT removed, essential
KERNEL (Huffman, fragmented data, ~135 KiB ): removed
POLICY (Huffman, fragmented data, ~91 KiB ): removed
HOSTCOMM (LZMA , 0x1cc6c5 - 0x1d349f ): removed
RSA (LZMA , 0x1d349f - 0x1d86f5 ): removed
CLS (LZMA , 0x1d86f5 - 0x1dde8a ): removed
TDT (LZMA , 0x1dde8a - 0x1e4580 ): removed
FTCS (Huffman, fragmented data, ~18 KiB ): removed
ClsPriv (LZMA , 0x1e4580 - 0x1e4961 ): removed
SESSMGR (LZMA , 0x1e4961 - 0x1f328b ): removed
The ME minimum size should be 1667072 bytes (0x197000 bytes)
The ME region can be reduced up to:
00003000:00199fff me
Setting the AltMeDisable bit in PCHSTRP10 to disable Intel ME...
Checking the FTPR RSA signature... VALID
Done! Good luck!

Flash the Neutralized Intel ME​

Now flash the full factory image with the neutralized Intel ME:

sudo flashrom -p serprog:dev=/dev/ttyACM0,spispeed=16M -c "W25Q128.V" -w factory_me_neutralized.bin

To double-check, you can dump the newly flashed image

sudo flashrom -p serprog:dev=/dev/ttyACM0,spispeed=16M -c "W25Q128.V" -r flashed.bin

Next, use sha1sum to compare the dumped BIOS image with the original libreboot_bottom.rom file

sha1sum factory_me_neutralized.bin flashed.bin

If the hashes match, you should see something like this:

4b9f06ccd2ce11dad757e337829a450a05df7929  factory_me_neutralized.bin
4b9f06ccd2ce11dad757e337829a450a05df7929 flashed.bin

Once you've confirmed that the hashes are the same, you can clean up any temporary dump files:

rm -fr flashed.bin

Flash the Coreboot BIOS Region​

Before flashing the BIOS, remove the CMOS battery. Some laptops use CMOS/EC settings to protect the SPI chip, and removing the battery also adds a layer of safety.

note

If you’ve already flashed Coreboot internally, you can skip this section as you’re all set and ready to go.

Make sure the writing protection is disabled:

sudo flashrom -p serprog:dev=/dev/ttyACM0,spispeed=16M -c "W25Q128.V" --wp-disable

You will get the below output:

Disabled hardware protection

Now flash ONLY the BIOS region from your Coreboot image by doing:

sudo flashrom -p serprog:dev=/dev/ttyACM0,spispeed=16M -c "W25Q128.V" -w coreboot.rom --ifd -i bios -N

Finally, verify the flashed bios region.

Verify Intel ME Neutralization​

To check whether Intel ME has been successfully neutralized, you can use intelmetool:

cd coreboot/util/intelmetool
make
sudo ./intelmetool -m

The output you want to see should look similar to this:

Output

Bad news, you have a `QM77 Express Chipset LPC Controller` so you have ME hardware on board and you can't control or disable it, continuing...

MEI found: [8086:1e3a] 7 Series/C216 Chipset Family MEI Controller #1

ME Status : 0x1c020191
ME Status 2 : 0x120a0150

ME: FW Partition Table : OK
ME: Bringup Loader Failure : NO
ME: Firmware Init Complete : NO
ME: Manufacturing Mode : YES
ME: Boot Options Present : NO
ME: Update In Progress : NO
ME: Current Working State : Initializing
ME: Current Operation State : Bring up
ME: Current Operation Mode : Debug
ME: Error Code : No Error
ME: Progress Phase : BUP Phase
ME: Power Management Event : Clean global reset
ME: Progress Phase State : Check to see if straps say ME DISABLED

ME: Extend SHA-256: f9acfe9c2b5b199d321a1580417f5c4334d710175ad70bdaf4350eb1bef276fe

ME: failed to become ready
ME: failed to become ready
ME: GET FW VERSION message failed

In this output, Intel ME remains in the initializing state and fails to become fully ready. This is exactly what you expect when ME has been neutralized: the hardware is present, but the ME firmware is disabled and cannot initialize.