NthTry99
December 2025 (Revised April 2026)
This document describes a process to remove a lost/unknown Supervisor Password (SVP, aka BIOS password) from Lenovo ThinkPads, from approximately between the years 2012-2018 (4th to 8th-gen Intel). Specifically, I will be using a Lenovo ThinkPad T470 (circa 2017). See Appendix 1: Compatible Laptops for a list of ThinkPad models known to work with this process.
To really understand what is happening, it helps to be semi-familiar with the early boot process of these laptops. For a summarization, see Appendix 3: Standard UEFI Platform Initialization (PI) Flow.
For a description of the normal Supervisor Password verification process, see Appendix 5: Normal SVP Verification Process.
Unlike previous generations of ThinkPads where the SVP was literally stored as translatable scancodes on an SOIC-8 EEPROM chip, these models use a more complex Embedded Controller (EC) chip to store a hash of the password in a protected area of its memory (NVRAM) which cannot practically be accessed or modified directly. For more information on this chip, see Appendix 4: The Embedded Controller (EC).
To date, the most efficient way to remove a Supervisor Password for these ThinkPad models is by utilizing a firmware-level software exploit within the BIOS (which is stored on its own chip) and taking advantage of its relationship with the EC.
First, the complete BIOS (technically the UEFI firmware) is dumped/read from the chip via an external programmer. Using a script, the BIOS is modified in a way which will clear the password when booted. This modified firmware is then flashed back to the chip and subsequently executed, allowing it to clear the password. The original firmware is then re-flashed back to the chip and the process is complete. For more details see Appendix 6: How Modified DXE Driver Exploit Works.
For a brief history of the exploit, see Appendix 8: History of DXE Driver Exploit.
For a brief explanation of how this vulnerability was fixed in later generations, see Appendix 7: Why This Doesn’t Work for Newer Laptops.
DISCLAIMER: I am not responsible for any damage caused by, or misuse of, the information in this document. This document is purely for educational/informational purposes in the context of security research.
I also take no credit for the creation of any tools, physical or digital, used in this guide. The physical tools are cheap and widely available, and all of the software/code used is either FOSS (Free and Open-Source Software) or otherwise freely available to download on the internet. Throughout this guide, I have tried my very best to give credit to the creators of any code, packages, scripts, etc and provide sources, websites, or direct URLs from which they were obtained.
This guide assumes some general knowledge of hardware, electronics, and Linux concepts, terminology, and commands. If you decide to try this and there is anything you do not understand in this document, be sure to ask or look it up prior to starting!
Before beginning, make sure your ThinkPad is one of the compatible models for this process. For a list, see Appendix 1: Compatible Laptops.
PARTS/FILES NEEDED:
Once you have gathered all the required parts/files, ensured your laptop’s compatibility, and you know what you are doing, it’s time to locate and identify your BIOS chip. Don’t be afraid to look online first for info/suggestions about its location; you still may have to hunt for it. It will be an SOIC-8/SOP-8 chip (probably Macronix or Winbond).
Disassemble the laptop (gain access to BIOS chip):
Locate all SOIC-8 chips on the laptop motherboard.

Some laptops have more than one of these chips.

“Rear/CMOS battery” chip:

If there are multiple SOIC-8 chips, to verify which is the BIOS/UEFI chip, look at the top side marking on these chips and look up their datasheets on their manufacturer’s website. The one that stores the BIOS will almost always store more memory, such as 128M-bit / 16M-byte. Here are some relevant specs for my Winbond 25Q128FVSQ chip (Winbond, Source 2):
NOTE: the input voltage is important! Most of these flash chips will take an input range of 2.7-3.6V, however some use 1.8V. The Raspberry Pi Pico/Pico2 outputs 3.3V so we are good. Some programmers will use different voltages. Specifically, be careful with the CH341A. While the output to the VCC is typically 3.3V, they are known to output 5V to the SPI data lines.
Regarding the PC/Pico2 configurations, here is generally what is going on:
-The host PC will be running a utility called flashprog (an improved fork of flashrom) and connects to the Raspberry Pi Pico2 via USB using serial protocol. The Pico talks to the target flash chip via SPI interface (using 4 GPIO pins as SPI lines), and of course the 3.3V power and ground from the Pico2.
-The Raspberry Pi Pico2 will be running pico-serprog, which is firmware that turns it into a serprog programmer. Serprog is a simple, open-source, serial communication protocol designed specifically for flash ROM programming.
bash:
sudo pacman -S flashprog
flashprog is in the Extra repository on Arch-based distributions, and in the Universe repository on Ubuntu-based distributions. Check your distribution and make sure the appropriate repository is enabled so you can find the package.
Make sure cmake (Extra), pico-sdk (AUR) , and picotool (AUR) are installed. If not, install them.
echo "export PICO_SDK_PATH=/usr/share/pico-sdk" >> ~/.bashrc
git clone https://codeberg.org/Riku_V/pico-serprog.git .
cmake . -DPICO_BOARD=pico2
make .
This will generate a bunch of files in that directory, one being “pico_serprog.uf2”. This is the firmware we will flash to the Pico2.
NOTE: If using a 1st gen Pico (not Pico2), do not add “-DPICO_BOARD=pico2” in the cmake command above
Hold the BOOTSEL button (on the Pico2) down while plugging it into the host PC via USB. When the computer recognizes it as “RP2350” (or “RP2040” for original Pico), release the button. (Note: it is easier to plug the micro-USB into the Pico2 first, then the USB-A into the host PC while holding the button)
Copy the “pico_serprog.uf2” file to the root directory of the Pico2. There will probably already be 2 files there, INDEX.HTM and INFO_UF2.TXT, just leave them there.
The Pico2 should reboot. It will automatically unmount and display as “libreboot.org pico-serprog (pico2)”. The new firmware has been installed. To verify this:
bash:
lsusb
and among the output you should see something like:
Bus 001 Device 012: ID cafe:4001 libreboot.org pico-serprog (pico2)
Disconnect the Pico2 from the host computer.
Next we will wire the Pico2 to the SOIC-8/SOP-8 test clip:

I recommend using a breakout board (or breadboard) and wiring it to the test clip, then attaching the Pico2 to the breakout board. DO NOT ATTACH THE TEST CLIP TO THE BIOS CHIP YET.
Identify the pinout for the BIOS chip from the datasheet (Winbond, Source 2):
NOTE: the small round notch on the corner of the chip indicates pin 1.
Here is the pinout for the SPI lines on the Pico2 (for use with Riku_V’s pico-serprog, borrowed directly from that page). (Riku_V, Source 3):
NOTE: You MUST follow the pinout configuration on the specific version of pico-serprog you flashed. There is another popular version, by Stacksmashing (Stacksmashing, Source 4), which is the upstream repository and uses a different pinout.
Physically attach jumper wires from the corresponding pins on the test clip (and where they will connect on the BIOS chip) to the pins on the breakout board (where they match up on the Pico2).
INFO: Here is a quick SPI communication line recap:
–WARNING: USING LEGACY TERMINOLOGY FROM DATASHEET, DO NOT GET MAD AT ME–
– Make sure the power adapter and all batteries are still disconnected from the target laptop –
Carefully attach the test clip to the BIOS chip. Be sure the clip is fully, evenly seated all the way down on the chip and that you have the correct pin orientation. Remember pin 1 is indicated by the small round notch on the top of the chip.

In a terminal, run:
bash:
sudo dmesg -wH
While dmesg is running, connect the Pico2 to the host PC. A new line should appear with something like:
[ +0.003208] cdc_acm 1-1:1.0: ttyACM0: USB ACM device
At very bottom of full output:

Take note of the “ttyACM0” or whatever the Pico2 displays as (it will be the line that appeared when you plugged in the Pico2); it should start with “ttyACM”. This is our Pico2’s device node, which is what the Linux Kernel will refer to it as. We will need this when using the flashprog command. Once you have this written down, use CTL+C to stop dmesg.
Create (and navigate to) a new directory to work out of. This is where the BIOS dump will be saved.
READ the contents of the chip (insert your device node from 5.2 if it is not ttyACM0):
bash:
sudo flashprog -p serprog:dev=/dev/ttyACM0,spispeed=10M -r flash.bin

READ the chip several more times, making sure to change the output filename (flash.bin) for each additional read to avoid overwriting previous dumps. We will perform multiple redundant reads throughout this process and will be comparing them; this is to ensure we are getting consistent and accurate data from the chip.
At first I had trouble with reading and the connection. For details, see Appendix 10: Problems and Notes 1.
Use a binary comparison to ensure they are all identical. For example, to compare two files:
bash:
cmp flash1.bin flash2.bin
—OR—
You can compare the checksums (MD5 for example) of multiple files. For the sake of data integrity, if they are the same, the files are the same:
bash:
md5sum flash1.bin flash2.bin flash3.bin
If all of the dumps/reads from the chip are identical, you can be confident your connections/wires are reliable and you have the true contents of the flash chip.
THIS IS YOUR FACTORY, ORIGINAL BIOS. BACK IT UP. MULTIPLE TIMES. DO NOT LOSE IT!
To remove the SVP, we will modify our BIOS/firmware in a way where it will actually clear the password by itself. To do this, we will run the Autopatch script on our BIOS, which injects it with modified DXE drivers (aka “patching” it). These modified drivers exploit a vulnerability which facilitates bypassing/removing the supervisor password.
We will flash this patched BIOS back to the chip and run it, allowing it to remove the supervisor password. Once the password has been removed, we will flash our original, unpatched BIOS back onto the target laptop and we will be finished. NOTE: the patched BIOS is only used to remove the password and must be replaced with the original BIOS afterward to restore the laptop’s functionality.
Here is a brief explanation directly from the creator of the Autopatch script:
“The autopatcher has 2 steps. On the first pass it injects the patched DXE drivers. If the bios is from an older gen it ends there and its work is done. If it’s a newer generation on the second pass it replaces parts of the NVRAM with clean ones and then it’s done.” (Knucklegrumble, Source 6)
Download lenovo_autopatcher_0.2.zip from Source 1 or Source 7.
Also, make sure you have Python installed:
bash:
sudo pacman -S python
Create (and navigate to) a new directory containing a copy of your BIOS (ex. flash.bin or bios.bin) as well as the extracted files from the lenovo_autopatcher_0.2.zip. In total, your directory should contain:
chmod +x autopatch
chmod +x ./tools/UEFIReplace
Now execute the script:
bash:
./autopatch bios.bin
Using UEFIReplace to inject 2 DXE drivers...
[1/2] LenovoTranslateService (GUID 826bcf56-bac4-43f4-8ea1-8cdf0a121abd)
[2/2] BootOption (GUID e0746c42-d3f9-4f8b-b211-1410957b9ff5)
Looking for volumes to patch...
[1/1] NVRAM_EfiSystemNvDataFvGuid (checksum 2609h):
Found volume at offset 800000h (checksum 2609h)
Replacing volume.
Done.
PATCH FILE: bios_PATCHED.bin
Good luck.
After running the script, you should have an additional, _PATCHED version of your BIOS in your working directory. (i.e bios_PATCHED.bin)
For more info about DXE drivers and these modified drivers injected here by the script, see Appendix 9: Role of the Injected Drivers.
If you get an error, you may have forgotten to add execute permission to either the script or UEFIReplace like I did. For details, see Appendix 11: Problems and Notes 2.
Create (and navigate to) a new directory to work out of. Make sure a copy of the original BIOS and patched BIOS are in it.
READ the chip again:
bash:
sudo flashprog -p serprog:dev=/dev/ttyACM0,spispeed=10M -r confirm_ORIG_READ.bin
Compare it to the original BIOS dumps. If they match, you have a solid connection.
WRITE the patched BIOS to the chip. NOTE: the write command will automatically erase the chip then write to it.
bash:
sudo flashprog -p serprog:dev=/dev/ttyACM0,spispeed=10M -w T470bios_PATCHED.bin

READ the chip:
bash:
sudo flashprog -p serprog:dev=/dev/ttyACM0,spispeed=10M -r CONFIRMpatchedREAD.bin
Compare it to the patched BIOS we just flashed and make sure they match.
Disconnect the Pico2 from the host PC first (USB-A), then disconnect the test clip from the chip.
Now we will actually run the patched BIOS and let it work its magic:
If needed, reassemble the laptop enough to where you can use the keyboard, display, and safely power it on.
Connect the power adapter to the target laptop and press the power button. It may take multiple attempts to power it on and it may restart multiple times on its own without displaying anything on the screen. When it finally shows the red Lenovo splash screen or prompts to enter the BIOS settings, follow these instructions from the Autopatcher_0_2 (Knucklegrumble, Source 1):
Step 1. Press ENTER/F1/etc. to enter BIOS settings
Step 2. Enter any character and press Enter when asked for Supervisor Password
Step 3. Press Enter when it shows Hardware ID
Step 4. Press space bar 2x when asked
Step 5. Turn off machine when prompted
[ NOTES ]
When booting the patched BIOS you might have to:
- Hold the anti-tamper switch down the whole time (use tape)
- Remove the hard disk or replace it with a locked one
***I did not have to do either of these last 2***
Disconnect the power adapter and hold the power button for 30 seconds. Disassemble the laptop one last time as needed to regain access to the BIOS chip.
Now we flash the original, unpatched BIOS back to the chip:
Reattach the clip to the BIOS chip and reconnect the Pico2 to the host computer.
Again, READ the contents of the chip a few times:
bash:
sudo flashprog -p serprog:dev=/dev/ttyACM0,spispeed=10M -r CONFIRMpatchedREADfinal.bin
Verify all of them match to ensure physical connection integrity.
NOTE: These dumps will NOT match the patched BIOS we flashed to it earlier because by booting it (in 8.2), it modifies itself.
Now WRITE the original, unpatched BIOS back to the chip:
bash:
sudo flashprog -p serprog:dev=/dev/ttyACM0,spispeed=10M -w T470bios.bin

READ the chip one last time:
bash:
sudo flashprog -p serprog:dev=/dev/ttyACM0,spispeed=10M -r CONFIRM_T470_READfinal.bin
Make sure it matches the original BIOS we flashed.
Disconnect the Pico2 from the host PC first (USB-A), then disconnect the test clip from the chip.
Now we just need to verify that it worked and reassemble the laptop:
Reinstall the internal battery, SSD/HDD, CMOS battery and anything you previously disconnected/removed, including all covers and screws.
ThinkPads between 2012-2018, 4th to 8th gen Intel, see compatible models list below. The ThinkPad with the supervisor password will be referred to as the target in this guide. Also do some research on your specific ThinkPad’s model and make sure its BIOS is stored on an SOIC-8 (package type) chip. Some ThinkPads use a WSON-8, which will require a different “test clip” (actually a WSON-8 Probe Line/Pogo Pin Adapter) for in-circuit programming and is substantially more difficult. Instead of clipping to the chip, you would have to manually hold the adapter to the chip in the precise position during programming, create a fixture to hold it, or you would have to desolder the chip and place it into a dedicated ZIF (Zero Insertion Force) or clamshell socket for programming. For this route, it is popular to remove the WSON-8 chip, read the BIOS/firmware, then replace the WSON-8 chip with a compatible SOIC-8 chip on the motherboard, and then use a test clip for programming.
ALLEGED KNOWN WORKING COMPATIBLE LENOVO THINKPAD MODELS From post: https://www.badcaps.net/forum/troubleshooting-hardware-devices-and-electronics-theory/troubleshooting-laptops-tablets-and-mobile-devices/bios-requests-only/78215-lenovo-bios-auto-patcher-for-supervisor-password-removal?p=1809652#post1809652
By: AAAC
This is the list I use, seems like it contains most of the models compatible with the DXE driver patch solution, if it’s not in the list, most likely the DXE driver patch won’t work, specially if BIOS is 32MB:
ThinkPad 13 (20GJ, 20GK, 20J1, 20J2)
ThinkPad 25 (20K7)
ThinkPad A485 (20MU, 20MV)
ThinkPad Helix Gen 3
ThinkPad E14 (20RA, 20RB)
ThinkPad E470 (20H1, 20H2)
ThinkPad E480 (20KN, 20KQ)
ThinkPad E485 (20KU)
ThinkPad E490 (20N8, 20N9)
ThinkPad E495 (20NE)
ThinkPad E490s (20NG)
ThinkPad E570 (20H5, 20H6)
ThinkPad E580 (20KS, 20KT)
ThinkPad E585 (20KV)
ThinkPad E590 (20NB, 20NC)
ThinkPad E595 (20NF)
ThinkPad L380 (20M5, 20M6)
ThinkPad L380 Yoga (20M7, 20M8)
ThinkPad L390 (20NR, 20NS) [32MB]
ThinkPad L390 Yoga (20NT, 20NU) [32MB]
ThinkPad L440 (20AS, 20AT)
ThinkPad L450 (20DS, 20DT)
ThinkPad L460 (20FU, 20FV)
ThinkPad L470 (20JU, 20JV)
ThinkPad L540 (20AU, 20AV)
ThinkPad L560 (20F1, 20F2)
ThinkPad L570 (20J8, 20J9, 20JQ, 20JR)
ThinkPad P40 Yoga (20GQ, 20GR)
ThinkPad P50 (20EN, 20EQ)
ThinkPad P50s (20FK, 20FL)
ThinkPad P51 (20HH, 20HJ)
ThinkPad P51s (20HB, 20HC, 20JY, 20K0)
ThinkPad P52 (20M9, 20MA) [32MB]
ThinkPad P52s (20LB, 20LC)
ThinkPad P70 (20ER, 20ES)
ThinkPad P72 (20MB, 20MC) [32MB]
ThinkPad T440 (20B6, 20B7)
ThinkPad T440p (20AN, 20AW)
ThinkPad T440s (20AQ, 20AR)
ThinkPad T450 (20BU, 20BV, 20DJ)
ThinkPad T450s (20BW, 20BX)
ThinkPad T460 (20FM, 20FN)
ThinkPad T460p (20FW, 20FX)
ThinkPad T460s (20F9, 20FA)
ThinkPad T470 (20HD, 20HE, 20JM, 20JN)
ThinkPad T470p (20J6, 20J7)
ThinkPad T470s (20HF, 20HG, 20JS, 20JT)
ThinkPad T480 (20L5, 20L6)
ThinkPad T480s (20L7, 20L8)
ThinkPad T495 (20NJ, 20NK)
ThinkPad T540p (20BE, 20BF)
ThinkPad T550 (20CJ, 20CK)
ThinkPad T560 (20FH, 20FJ)
ThinkPad T570 (20H9, 20HA, 20JW, 20JX)
ThinkPad T580 (20L9, 20LA)
ThinkPad W540 (20BG, 20BH)
ThinkPad W541 (20EF, 20EG)
ThinkPad W550s (20E1, 20E2)
ThinkPad X1 Carbon Gen 2 (20A7, 20A8)
ThinkPad X1 Carbon Gen 3 (20BS, 20BT)
ThinkPad X1 Carbon Gen 4 (20FB, 20FC)
ThinkPad X1 Carbon Gen 5 (20HQ, 20HR, 20K3, 20K4)
ThinkPad X1 Carbon Gen 6 (20KH, 20KG)
ThinkPad X1 Tablet 3rd Gen (20KJ, 20KK)*
ThinkPad X1 Yoga Gen 1 (20FQ, 20FR)
ThinkPad X1 Yoga Gen 2 (20JD, 20JE, 20JF, 20JG)
ThinkPad X1 Yoga Gen 3 (20LD, 20LE, 20LF, 20LG)
ThinkPad X240 (20AL, 20AM)
ThinkPad X240s (20AJ, 20AK)
ThinkPad X250 (20CL, 20CM)
ThinkPad X260 (20F5, 20F6)
ThinkPad X270 (20HM, 20HN, 20K5, 20K6)
ThinkPad X280 (20KE, 20KF)
ThinkPad Yoga 14 (20FY)
ThinkPad Yoga 260 (20FD, 20FE, 20GS, 20GT)
ThinkPad Yoga 370 (20JH, 20JJ, 20JK, 20JL)
ThinkPad Yoga 460 (20EL, 20EM)
ThinkPad Yoga X380 (20LH, 20LJ)
We will refer to the Linux computer as the host PC. The process can be done with Windows using Windows Subsystem for Linux (WSL), or other native, specific applications for Windows (like ASprogrammer) but the specifics will be different. If you are using a distribution other than an Arch-based one, package manager commands will be different, but everything else should be the same.
Essentially, this is the technical blueprint for the entire boot process:
—OVERVIEW—
—DETAILS—
1. SEC (Security) Phase
The main purpose of the SEC phase is to establish the system’s initial Root of Trust and a minimal, secure environment for the transition to the Pre-EFI Initialization (PEI) phase. This process begins at the x86 reset vector (0xFFFFFFF0), the first instruction the CPU fetches immediately following a power-on or hardware reset.
(source: https://uefi.org/specs/PI/1.8/V1_Security_SEC_Phase_Information.html)
(source: https://uefi.org/specs/PI/1.8/V2_Boot_Manager.html)
(source: https://github.com/tianocore/tianocore.github.io/wiki/PI-Boot-Flow)
(source: https://uefi.org/specs/UEFI/2.10_A/02_Overview.html)
On my T470, the Embedded Controller, a Microchip MEC1653, is a specialized microprocessor which manages essential hardware-level functions that operate independently of the main CPU and Operating System. The EC utilizes an internal EEPROM to maintain a dedicated NVRAM partition, which is where the supervisor password hash is securely stored as a system variable.
The MEC1653 uses a BGA (Ball Grid Array) package, specifically a 169-pin LFBGA. Unlike the 8-pin SOIC-8 (Small Outline Integrated Circuit) chips commonly used for the system BIOS or Thunderbolt firmware, this chip has a dense grid of solder balls on its underside. It is physically larger and more complex to replace or flash manually, typically requiring professional tools like an SVOD3 programmer and connection via a JTAG port. Also, attempting to desolder a BGA chip to read it requires advanced hot-air rework skills (ideally a professional BGA rework station) and carries a high risk of permanently damaging the motherboard.
Even if you could access the data on the EC, only the hash of the SVP is stored and simply erasing it would almost certainly trigger a data verification error. Because of this, injecting a modified DXE driver (i.e tricking the EC into clearing it itself) is easier and safer than directly modifying EC data.
This is an overview of how the SVP is verified under normal operating circumstances:
-After the laptop is powered on, relatively early in the boot process (immediately after RAM initializes) DXE drivers and SMM modules load. Some of the relevant ones are:
-LenovoSvpManagerSMM immediately checks with the EC for the presence of the Supervisor Password hash during its own initialization phase within the DXE stage. This happens before anything even displays on the screen
-LenovoSvpManagerDxe asks LenovoSvpManagerSMM the status of the SVP and prepares the GUI logic based on that status
-If a password hash exists, LenovoSvpManagerSmm requests the “true” hash from the EC
-EmulatedEepromSmm returns the “true” hash from the EC internal EEPROM and hands it to LenovoSvpManagerSmm, which stores it in a protected buffer within System Management Mode RAM (SMRAM)
-If you just let the computer boot normally (i.e don’t try to access BIOS/setup menu), LenovoSvpManagerDxe stays “quiet” in the background and lets you pass
-If you press F1 or Enter to access the ThinkPad Setup program, the BIOS sends a signal that “intercepts” the boot process and hands control over to the security driver, LenovoSvpManagerDxe. If an SVP is set, LenovoSvpManagerDxe draws the password prompt window GUI (the little lock or “Enter Password” icon) onto the screen. It then sits in an infinite loop, waiting for input from the keyboard
-LenovoSvpManagerDxe captures plaintext input from the keyboard (user types in a password)
-LenovoSvpManagerDxe requests LenovoCryptService (possibly LenovoCryptServiceSmm) to calculate the hash of that input (likely a salted SHA-256)
-LenovoSvpManagerSmm performs the hash comparison:
-MATCH: LenovoSvpManagerSmm sets a secure variable in the SMM-protected range of memory, allowing access to BIOS/UEFI menu
-NO MATCH: The GUI prompt typically clears the entry and displays a small “X” or a generic “Password Invalid” message
-If you press Enter without a password or enter an incorrect one, the system may still allow you into the ThinkPad Setup program, but almost all critical settings (like boot order, security, and hardware config) will be grayed out and unmodifiable
-LenovoSvpManagerSMM is responsible for managing the retry logic. It increments a failure counter stored in the Embedded Controller (EC). By default, after three incorrect attempts, the system will stop accepting input and often require a reboot before you can try again
-If the maximum retry count is exceeded across multiple boot sessions, the firmware triggers POST Error 0199: Security password retry count exceeded
(source for this process summary: https://www.synacktiv.com/en/publications/a-journey-in-reversing-uefi-lenovo-passwords-management)

The EC memory driver modules:

For another in-depth analysis on exactly how this works and even more details, Mark Juvan at Radboud University Nijmegen in 2024 did his Master of Science (MSc) thesis report on this very topic. It is publicly available online at https://www.cs.ru.nl/masters-theses/2024/M_Juvan___Bypassing_the_BIOS_supervisor_password.pdf which actually references many of the same exact sources/posts I found my info from.
DXE Driver Injection: The autopatcher injects modified DXE drivers into the BIOS image. When you boot this patched BIOS, these drivers load early in the boot sequence and signal the Embedded Controller to “wipe” or reset the password hash stored in its internal EEPROM.
NVRAM Cleanup (Newer Generations): For “newer” generations like the T470, simply clearing the hash in the EC isn’t enough. The BIOS itself also stores status flags in the NVRAM variables on the SPI chip. If these variables aren’t “cleaned” (reset to defaults), the system may still think a password is set or trigger a security “tamper” state.
For newer 9th-generation models and beyond, this modified DXE driver method doesn’t work due to improvements in both digital signature verification (i.e the DXE drivers signature being checked by the CPU) as well as Intel Boot Guard (which prevents a modified BIOS from booting).
In newer models, the SVP hash has been moved to more advanced Embedded Controllers, such as the MEC1663 where the communication between the BIOS and these new controllers is often encrypted or restricted. Even if you could bypass Boot Guard to run a custom driver, that driver would lack the necessary permissions to command the newer EC to erase its internal password storage.
This exploit was discovered by Romanian developer and security researcher Victor Voinea around late 2018 or early 2019 (according to various forums on badcaps.net and ALLservice.ro). Victor Voinea is the same guy who founded ALLservice.ro and makes IBMpass (a proprietary tool for decoding the SVP from IBM-era ThinkPads).
He typically provided his exploits as proprietary, paid services. He would often require users to send him a dump of their BIOS, which he would then patch and return for a fee.
His discovery of the DXE injection method was eventually reverse-engineered by members of the community on forums like badcaps.net. This led to the creation of the free, automated “Auto Patcher” by Knucklegrumble.
Here is relevant output again from the autopatch script:
Using UEFIReplace to inject 2 DXE drivers...
[1/2] LenovoTranslateService (GUID 826bcf56-bac4-43f4-8ea1-8cdf0a121abd)
[2/2] BootOption (GUID e0746c42-d3f9-4f8b-b211-1410957b9ff5)
Looking for volumes to patch...
[1/1] NVRAM_EfiSystemNvDataFvGuid (checksum 2609h):
Found volume at offset 800000h (checksum 2609h)
Replacing volume.
Done.
Analyzing my original BIOS using UEFITool (both the regular and the New Engine (NE) versions), both of these replaced DXE drivers and the patched volume can be located:
DXE drivers:
Both of these can be seen in UEFITool as well as their GUIDs:



“Found volume at offset 800000h” (from the autopatch output) and “Base: 800000h” (in UEFITool_NE) are two ways of describing the same location in the BIOS file.
The difference in the checksum (2609h in the script output vs 0926h in UEFITool_NE) is due to Endianness, specifically how multi-byte numbers are stored in memory versus how they are displayed by software.
Initially, I tried using the following suggested command from Riku_V’s webpage (Riku_V, Source 3) (note the spispeed):
bash:
flashprog -p serprog:dev=/dev/ttyACM0,spispeed=32M -r flash.bin
I got this error:
flashprog v1.4-dirty on Linux 6.17.9-arch1-1 (x86_64)
flashprog is free software, get the source code at https://flashprog.org
Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
serprog: Programmer name is "pico-serprog"
Found Generic flash chip "unknown SPI chip (RDID)" (0 kB, SPI) on serprog.
===
This flash part has status NOT WORKING for operations: PROBE READ ERASE WRITE
The test status of this chip may have been updated in the latest development
version of flashprog. If you are running the latest development version,
please email a report to flashprog@flashprog.org if any of the above
operations work correctly for you with this flash chip. Please include the
flashprog log file for all operations you tested (see the man page for details),
and mention which mainboard or programmer you tested in the subject line.
Thanks for your help!
Read is not working on this chip. Aborting.
At first, I thought it might be because I was using a Pico2 and not a 1st gen Pico. I had read on libreboot.org (Libreboot, Source 5) (as well as elsewhere) that there are known compatibility issues with the Pico2. So I got out my 1st gen Pico, and also decided to try Stacksmashing’s version of serprog (Stacksmashing, Source 4) (the upstream repository of Riku_V’s fork). Stacksmashing’s version uses a different pinout than Riku_V’s so I rewired everything and reattached the clip.
I got the same error as before. At this point, I was leaning towards something else being the issue. After some more research on badcaps.net and github.com, I saw suggestions to try a slower SPI speed (the original command I was trying used 32M).
So I changed this to 800k and ran the command again. This time it worked and after about 5 minutes I got an output file. I tried another SPI speed (10M) and it also worked, and took about 20 seconds.
I ran each command a few more times, knowing I would need to compare them and make sure they all matched exactly (using a binary comparison) to ensure nothing was corrupted during the reading. Unfortunately, none of them matched each other. At this point, since there was no consistency to the corruption amongst the dumps, I thought it was likely a bad connection (there is substantial room for error: the Pico2 (which has soldered headers, probably not the problem) is plugged into a breakout board, jumper wires are connected from the breakout board to the test clip, and the test clip is clipped onto the flash chip).
I disconnected the test clip, all the jumper wires, and cleaned the BIOS chip pins with some 90% isopropyl alcohol on a q-tip.
Unsure what to do next, just out of sheer curiosity, knowing that the SPI speed was likely the reason the chip wasn’t even recognized the first time, I got out the Pico2 again and freshly downloaded and recompiled Riku_V’s pico-serprog firmware for it (just in case):
bash:
git clone https://codeberg.org/Riku_V/pico-serprog.git .
cmake . -DPICO_BOARD=pico2
make
bash:
sudo flashprog -p serprog:dev=/dev/ttyACM0,spispeed=10M -r flash.bin
and it again finished in about 20 seconds.
I ran this command several more times, changing the output file name to save the additional dumps. Then I changed the SPI speed from 10M to 500k and ran it another couple of times. This time it took around 5-6 minutes.
I did binary comparisons and checked the MD5 checksums and every one of them matched, both 10MHz and 500kHz SPI speed dumps.
In the process of hooking everything back up and cleaning the BIOS chip with isopropyl, I must have solved my intermittent connectivity issue which led to my inconsistent reads in my first attempt.
The datasheet for the BIOS flash chip says it supports up to 104MHz. Here is my theory: first, I had a dirty/bad connection. Second, the reason I was unable to get the 32MHz SPI speed to work is likely due to the physical hardware setup (like the Pico2’s “12-Mbps” Micro-USB connection) and signal integrity issues. If everything was soldered (i.e no DuPont connections on jumper wires, very short wires, etc) I probably could have gotten higher speeds to work. Additionally, regarding using a Pico2 as a serial programmer, libreboot.org (Libreboot, Source 5) says:
“spispeed=32M usually works, but since it’s not much faster it’s probably not worth it. The 12Mbps USB port is limiting the actual speed here.”
During my first attempt, I did not add execute permissions for UEFIReplace (7.5) before running the script. It DID generate an output file (bios_PATCHED.bin) and the following error:
PermissionError: [Errno 13] Permission denied: '/home/Matt/Documents/bios_extract_project/ztest/patch/../tools/UEFIReplace'
Also, the output file was identical (checksum and binary comparison) to the original unpatched file, which means it just copied the input file as the output file and did not change anything.
The script uses UEFIReplace (which is a program, included from the .zip for the autopatcher, located in ./tools) and thus also needs execute permission. After adding execute permission to UEFIReplace, I ran the autopatch and got the output:
output:
Using UEFIReplace to inject 2 DXE drivers...
[1/2] LenovoTranslateService (GUID 826bcf56-bac4-43f4-8ea1-8cdf0a121abd)
[2/2] BootOption (GUID e0746c42-d3f9-4f8b-b211-1410957b9ff5)
Looking for volumes to patch...
[1/1] NVRAM_EfiSystemNvDataFvGuid (checksum 2609h):
Found volume at offset 800000h (checksum 2609h)
Replacing volume.
Done.
PATCH FILE: bios_PATCHED.bin
Good luck.
No error message and this output means the autopatch was successful. Comparing checksums and doing a binary comparison, this patched file is indeed different from the original BIOS. I ran the autopatch script a few extra times (making sure not to overwrite the output file) to ensure it was generating the same patched BIOS every time, and it was.
(Source 1)
https://www.badcaps.net/forum/troubleshooting-hardware-devices-and-electronics-theory/troubleshooting-laptops-tablets-and-mobile-devices/bios-requests-only/78215-lenovo-bios-auto-patcher-for-supervisor-password-removal?t=87588
(Knucklegrumble, source1)
(Source 2)
https://www.winbond.com/hq/support/documentation/levelOne.jsp?__locale=en&DocNo=DA00-W25Q128FV
(Winbond, source2)
(Source 3)
https://codeberg.org/Riku_V/pico-serprog
(Riku_V, source3)
(Source 4)
https://github.com/stacksmashing/pico-serprog
(Stacksmashing, source4)
(Source 5)
https://libreboot.org/docs/install/spi.html#raspberry-pi-pico
(Libreboot, source5)
(post 14, from Knucklegrumble, the maker of the Autopatcher):
“The autopatcher has 2 steps. On the first pass it injects the patched DXE drivers. If the bios is from an older gen it ends there and its work is done. If it’s a newer generation on the second pass it replaces parts of the NVRAM with clean ones and then it’s done. I’ve patched some of the ones you have listed in NOK and they all reported working.”
(Knucklegrumble, source6)
(Source 7)
https://github.com/lilianalillyy/t470s-uefi-unlock
Alternate source for lenovo_autopatcher_0.2.zip if the badcaps.net source (Source 1) gets taken down.