{"id":14128439,"url":"https://github.com/gch1p/thinkpad-bios-software-flashing-guide","last_synced_at":"2025-03-17T14:13:42.703Z","repository":{"id":46547317,"uuid":"219623363","full_name":"gch1p/thinkpad-bios-software-flashing-guide","owner":"gch1p","description":"flashing coreboot on thinkpads without external programmer","archived":false,"fork":false,"pushed_at":"2021-02-15T13:58:20.000Z","size":502,"stargazers_count":244,"open_issues_count":3,"forks_count":23,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-03-05T00:53:07.350Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gch1p.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-11-05T00:32:53.000Z","updated_at":"2025-03-04T19:10:09.000Z","dependencies_parsed_at":"2022-08-30T14:40:54.645Z","dependency_job_id":null,"html_url":"https://github.com/gch1p/thinkpad-bios-software-flashing-guide","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gch1p%2Fthinkpad-bios-software-flashing-guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gch1p%2Fthinkpad-bios-software-flashing-guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gch1p%2Fthinkpad-bios-software-flashing-guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gch1p%2Fthinkpad-bios-software-flashing-guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gch1p","download_url":"https://codeload.github.com/gch1p/thinkpad-bios-software-flashing-guide/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244047646,"owners_count":20389206,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-15T16:01:43.755Z","updated_at":"2025-03-17T14:13:42.660Z","avatar_url":"https://github.com/gch1p.png","language":"Perl","funding_links":[],"categories":["Perl","Documentation and Community"],"sub_categories":["Mechanical \u0026 Ortholinear Keyboard Swaps"],"readme":"This document describes known methods of flashing BIOS on Lenovo ThinkPads\nwithout external programmer. The main goal is flashing coreboot while running\nstock BIOS, but it may be used for flashing modified vendor BIOS as well.\n\n\n# Table of Contents\n\n- [Ivy Bridge series (X230, T430, etc.)](#ivy-bridge-series-x230-t430-etc)\n  - [Introduction](#ivy-bridge-series-x230-t430-etc)\n  - [Requirements](#requirements)\n  - [BIOS versions](#bios-versions)\n  - [Downgrading BIOS](#downgrading-bios)\n    - [Enabling UEFI mode](#enabling-uefi-mode)\n  - [Examining protections (theory)](#examining-protections-theory)\n  - [Creating a backup](#creating-a-backup)\n    - [Restoring](#restoring)\n  - [Removing protections (practice)](#removing-protections-practice)\n  - [About Intel ME](#about-intel-me)\n- [Sandy Bridge series (X220, T420, etc.): WIP](#sandy-bridge-series-x220-t420-etc-wip)\n- [Penryn and Nehalem series (X200, T400, X201, T410, etc.): WIP](#penryn-and-nehalem-series-x200-t400-x201-t410-etc-wip)\n- [Common methods](#common-methods)\n  - [HDA_SDO/GPIO33](#hda_sdogpio33)\n- [Credits](#credits)\n- [License](#license)\n\n# Ivy Bridge series (X230, T430, etc.)\n\n\u003e A guide for Ivy Bridge ThinkPads has also been merged to coreboot\n  documentation, [see here](https://doc.coreboot.org/mainboard/lenovo/ivb_internal_flashing.html).\n\nOld versions of stock BIOS for these models have several security issues. In\ncontext of this guide, two of them are of interest.\n\n**First** is the fact the SMM_BWP and BLE are not enabled in BIOS versions\nreleased before 2014. I have tested many versions on T430 and X230 and found out\nthat SMM_BWP=1 only since the update, the changelog of which contains following\nline:\n\n\u003e (New) Improved the UEFI BIOS security feature.\n\n**Second** is [S3 Boot Script vulnerability](https://support.lenovo.com/eg/ru/product_security/s3_boot_protect),\nthat was discovered and fixed later.\n\n## Requirements\n\n- USB drive (in case you need to downgrade BIOS). There were reports that\n  GPT-partitioned drive didn't work and the fix was to change partition table to\n  MBR.\n- Linux install that (can be) loaded in UEFI mode.\n- [CHIPSEC](https://github.com/chipsec/chipsec)\n- Recent [flashrom](https://flashrom.org). At least version 1.0 is required,\n  older versions of flashrom do not have `--ifd` option. (Workaround by using\n  layout file is possible, but it's more complicated.)\n- `iomem=relaxed` kernel parameter for using internal programmer.\n\n## BIOS versions\n\nBelow is a table of BIOS versions that are vulnerable enough for our goals, per\nmodel. The version number means that you need to downgrade to that or earlier\nversion.\n\n| Model      | BIOS version |\n|------------|--------------|\n| X230       | 2.60         |\n| X230t      | 2.58         |\n| T430       | 2.64         |\n| T430s      | 2.59         |\n| T530       | 2.60         |\n| W530       | 2.58         |\n\nIf your BIOS version is equal or lower, skip to the\n**[Examining protections](#examining-protections-theory)** section. If not, go\nthrough the downgrade process, described next.\n\n## Downgrading BIOS\n\nGo to the Lenovo web site and download BIOS Update Bootable CD for your machine\nof needed version (see above).\n\nLenovo states that BIOS has \"security rollback prevention\", meaning once you\nupdate it to some version X, you will not be able to downgrade it to pre-X\nversion. That's not true. It seems that this is completely client-side\nrestriction in flashing utilities (both Windows utility and Bootable CD). You\njust need to call `winflash.exe` or `dosflash.exe` directly. Therefore you need\nto modify the bootable CD image you just downloaded.\n\nExtract an El Torito image:\n```\ngeteltorito -o ./bios.img g1uj41us.iso\n```\nMount the partition in that image:\n```\nsudo mount -t vfat ./bios.img /mnt -o loop,offset=16384\n```\nList files, find the `AUTOEXEC.BAT` file and the `FLASH` directory:\n```\nls /mnt\nls /mnt/FLASH\n```\n\nInside the `FLASH` directory, there should be a directory called `G1ET93WW` or\nsimilar (exact name depends on your ThinkPad model). See what's inside:\n```\nls /mnt/FLASH/G1ET93WW\n```\nThere must be a file with `.FL1` extension called `$01D2000.FL1` or something\nsimilar.\n\nNow open the `AUTOEXEC.BAT` file:\n```\nsudo vim /mnt/AUTOEXEC.BAT\n```\nYou will see a list of commands:\n```\n@ECHO OFF\nPROMPT $p$g\ncd c:\\flash\ncommand.com\n```\nReplace the last line (`command.com`) with this (change path to the `.FL1` file\naccording to yours):\n```\ndosflash.exe /sd /file G1ET93WW\\$01D2000.FL1\n```\n\nSave the file, then unmount the partition:\n```\nsudo umount /mnt\n```\n\nWrite this image to a USB drive (replace `/dev/sdX` with your USB drive device\nname):\n```\nsudo dd if=./bios.img of=/dev/sdX bs=1M\n```\n\nNow reboot and press F1 to enter BIOS settings. Open the **Startup** tab and set\nthe startup mode to **Legacy** (or **Both**/**Legacy First**):\n\n\u003ca href=\"/screenshots/bios-legacy-only.jpg\"\u003e\u003cimg src=\"/screenshots/bios-legacy-only.jpg\" width=\"250px\" /\u003e\u003c/a\u003e\n\u003ca href=\"/screenshots/bios-legacy-first.jpg\"\u003e\u003cimg src=\"/screenshots/bios-legacy-first.jpg\" width=\"250px\" /\u003e\u003c/a\u003e\n\nPress F10 to save changes and reboot.\n\nNow, before you process, make sure that AC adapter is connected! If your battery\nwill die during the process, you'll likely need external programmer to recover.\n\nBoot from the USB drive (press F12 to select boot device), and BIOS flashing\nprocess should begin:\n\n\u003ca href=\"/screenshots/flashing1.jpg\"\u003e\u003cimg src=\"/screenshots/flashing1.jpg\" width=\"250px\" /\u003e\u003c/a\u003e\n\u003ca href=\"/screenshots/flashing2.jpg\"\u003e\u003cimg src=\"/screenshots/flashing2.jpg\" width=\"250px\" /\u003e\u003c/a\u003e\n\nIt may reboot a couple of times in the process. Do not interrupt it.\n\n#### Enabling UEFI mode\n\nWhen downgrade is completed, go back to the BIOS settings and set startup mode\nto **UEFI** (or **Both**/**UEFI First**). This is required for vulnerability\nexploitation.\n\n\u003ca href=\"/screenshots/bios-uefi-only.jpg\"\u003e\u003cimg src=\"/screenshots/bios-uefi-only.jpg\" width=\"250px\" /\u003e\u003c/a\u003e\n\u003ca href=\"/screenshots/bios-uefi-first.jpg\"\u003e\u003cimg src=\"/screenshots/bios-uefi-first.jpg\" width=\"250px\" /\u003e\u003c/a\u003e\n\nThen boot to your system and make sure that `/sys/firmware/efi` or\n`/sys/firmware/efivars` exist.\n\n## Examining protections (theory)\n\nThere are two main ways that Intel platform provides to protect BIOS chip:\n- **BIOS_CNTL** register of LPC Interface Bridge Registers (accessible via PCI\n  configuration space, offset 0xDC). It has:\n  * **SMM_BWP** (*SMM BIOS Write Protect*) bit. If set to 1, the BIOS is\n    writable only in SMM. Once set to 1, cannot be changed anymore.\n  * **BLE**  (*BIOS Lock Enable*) bit. If set to 1, setting BIOSWE to 1 will\n    raise SMI. Once set to 1, cannot be changed anymore.\n  * **BIOSWE** (*BIOS Write Enable*) bit. Controls whether BIOS is writable.\n    This bit is always R/W.\n- SPI Protected Range Registers (**PR0**-**PR4**) of SPI Configuration Registers\n  (SPIBAR+0x74 - SPIBAR+0x84). Each register has bits that define protected\n  range, plus WP bit, that defines whether write protection is enabled.\n\n  There's also **FLOCKDN** bit of HSFS register (SPIBAR+0x04) of SPI\n  Configuration Registers. When set to 1, PR0-PR4 registers cannot be written.\n  Once set to 1, cannot be changed anymore.\n\nTo be able to flash, we need SMM_BWP=0, BIOSWE=1, BLE=0, FLOCKDN=0 or SPI\nprotected ranges (PRx) to have a WP bit set to 0.\n\nLet's see what we have. Make sure that you have\n[enabled and booted in UEFI mode](#enabling-uefi-mode), then examine HSFS\nregister:\n```\nsudo chipsec_main -m chipsec.modules.common.spi_lock\n```\nYou should see that FLOCKDN=1:\n```\n[x][ =======================================================================\n[x][ Module: SPI Flash Controller Configuration Locks\n[x][ =======================================================================\n[*] HSFS = 0xE009 \u003c\u003c Hardware Sequencing Flash Status Register (SPIBAR + 0x4)\n    [00] FDONE            = 1 \u003c\u003c Flash Cycle Done\n    [01] FCERR            = 0 \u003c\u003c Flash Cycle Error\n    [02] AEL              = 0 \u003c\u003c Access Error Log\n    [03] BERASE           = 1 \u003c\u003c Block/Sector Erase Size\n    [05] SCIP             = 0 \u003c\u003c SPI cycle in progress\n    [13] FDOPSS           = 1 \u003c\u003c Flash Descriptor Override Pin-Strap Status\n    [14] FDV              = 1 \u003c\u003c Flash Descriptor Valid\n    [15] FLOCKDN          = 1 \u003c\u003c Flash Configuration Lock-Down\n```\n\n\nThen check BIOS_CNTL and PR0-PR4:\n```\nsudo chipsec_main -m common.bios_wp\n```\nGood news: on old BIOS versions, SMM_BWP=0 and BLE=0.\n\nBad news: there are 4 write protected SPI ranges:\n\n```\n[x][ =======================================================================\n[x][ Module: BIOS Region Write Protection\n[x][ =======================================================================\n[*] BC = 0x 8 \u003c\u003c BIOS Control (b:d.f 00:31.0 + 0xDC)\n    [00] BIOSWE           = 0 \u003c\u003c BIOS Write Enable\n    [01] BLE              = 0 \u003c\u003c BIOS Lock Enable\n    [02] SRC              = 2 \u003c\u003c SPI Read Configuration\n    [04] TSS              = 0 \u003c\u003c Top Swap Status\n    [05] SMM_BWP          = 0 \u003c\u003c SMM BIOS Write Protection\n[-] BIOS region write protection is disabled!\n\n[*] BIOS Region: Base = 0x00500000, Limit = 0x00BFFFFF\nSPI Protected Ranges\n------------------------------------------------------------\nPRx (offset) | Value    | Base     | Limit    | WP? | RP?\n------------------------------------------------------------\nPR0 (74)     | 00000000 | 00000000 | 00000000 | 0   | 0\nPR1 (78)     | 8BFF0B40 | 00B40000 | 00BFFFFF | 1   | 0\nPR2 (7C)     | 8B100B10 | 00B10000 | 00B10FFF | 1   | 0\nPR3 (80)     | 8ADE0AD0 | 00AD0000 | 00ADEFFF | 1   | 0\nPR4 (84)     | 8AAF0800 | 00800000 | 00AAFFFF | 1   | 0\n```\n\nOther way to examine SPI configuration registers is to just dump SPIBAR:\n```\nsudo chipsec_util mmio dump SPIBAR\n```\n\nYou will see SPIBAR address (0xFED1F800) and registers (for example, 00000004 is\nHSFS):\n```\n[mmio] MMIO register range [0x00000000FED1F800:0x00000000FED1F800+00000200]:\n+00000000: 0BFF0500\n+00000004: 0004E009\n...\n```\nAs you can see, the only thing we need is to unset WP bit on PR0-PR4. But that\ncannot be done once FLOCKDN is set to 1.\n\nNow the fun part!\n\nFLOCKDN may only be cleared by a hardware reset, which includes S3 state. On S3\nresume boot path, the chipset configuration has to be restored and it's done by\nexecuting so-called S3 Boot Scripts. You can dump these scripts by executing:\n```\nsudo chipsec_util uefi s3bootscript\n```\nThere are many entries. Along them, you can find instructions to write to HSFS\n(remember, we know that SPIBAR is 0xFED1F800):\n```\nEntry at offset 0x2B8F (len = 0x17, header len = 0x0):\nData:\n02 00 17 02 00 00 00 01 00 00 00 04 f8 d1 fe 00 |\n00 00 00 09 e0 04 00                            |\nDecoded:\n  Opcode : S3_BOOTSCRIPT_MEM_WRITE (0x0002)\n  Width  : 0x02 (4 bytes)\n  Address: 0xFED1F804\n  Count  : 0x1\n  Values : 0x0004E009\n```\nThese scripts are stored in memory. The vulnerability is that we can overwrite\nthis memory, change these instructions and they will be executed on S3 resume.\nOnce we patch that instruction to not set FLOCKDN bit, we will be able to write\nto PR0-PR4 registers.\n\n## Creating a backup\n\nBefore you proceed, please create a backup of the `bios` region. Then, in case\nsomething goes wrong, you'll be able to flash it back externally.\n\nThe `me` region is locked due to active ME, so an attempt to create a full dump\nwill fail. But you can back up the `bios`:\n```\nsudo flashrom -p internal -r bios_backup.rom --ifd -i bios\n```\n\n#### Restoring\nIf you will even need to flash it back, use `--ifd -i bios` as well:\n```\nsudo flashrom -p \u003cYOUR_PROGRAMMER\u003e -w bios_backup.rom --ifd -i bios\n```\n**Important:** if you will omit `--ifd -i bios` for flashing, you will brick\nyour machine, because your backup has `FF`s in place of `fd` and `me` regions.\nFlash only `bios` region!\n\n## Removing protections (practice)\nThe original boot script writes 0xE009 to HSFS. FLOCKDN is 15th bit, so let's\nwrite 0x6009 instead:\n\nRun this:\n```\nsudo chipsec_main -m tools.uefi.s3script_modify -a replace_op,mmio_wr,0xFED1F804,0x6009,0x2\n```\nYou will get a lot of output and in the end you should see something like this:\n```\n[*] Modifying S3 boot script entry at address 0x00000000DAF49B8F..\n[mem] 0x00000000DAF49B8F\n[*] Original entry:\n 2  0 17  2  0  0  0  1  0  0  0  4 f8 d1 fe  0 |\n 0  0  0  9 e0  4  0                            |\n[mem] buffer len = 0x17 to PA = 0x00000000DAF49B8F\n 2  0 17  2  0  0  0  1  0  0  0  4 f8 d1 fe  0 |\n 0  0  0  9 60  0  0                            |     `\n[mem] 0x00000000DAF49B8F\n[*] Modified entry:\n 2  0 17  2  0  0  0  1  0  0  0  4 f8 d1 fe  0 |\n 0  0  0  9 60  0  0                            |     `\n[*] After sleep/resume, check the value of register 0xFED1F804 is 0x6009\n[+] PASSED: The script has been modified. Go to sleep..\n```\nNow go to S3, then resume and check FLOCKDN. It should be 0:\n```\nsudo chipsec_main -m chipsec.modules.common.spi_lock\n```\n```\n...\n[x][ =======================================================================\n[x][ Module: SPI Flash Controller Configuration Locks\n[x][ =======================================================================\n[*] HSFS = 0x6008 \u003c\u003c Hardware Sequencing Flash Status Register (SPIBAR + 0x4)\n    [00] FDONE            = 0 \u003c\u003c Flash Cycle Done\n    [01] FCERR            = 0 \u003c\u003c Flash Cycle Error\n    [02] AEL              = 0 \u003c\u003c Access Error Log\n    [03] BERASE           = 1 \u003c\u003c Block/Sector Erase Size\n    [05] SCIP             = 0 \u003c\u003c SPI cycle in progress\n    [13] FDOPSS           = 1 \u003c\u003c Flash Descriptor Override Pin-Strap Status\n    [14] FDV              = 1 \u003c\u003c Flash Descriptor Valid\n    [15] FLOCKDN          = 0 \u003c\u003c Flash Configuration Lock-Down\n[-] SPI Flash Controller configuration is not locked\n[-] FAILED: SPI Flash Controller not locked correctly.\n...\n```\nSet BIOSWE:\n```\nsudo setpci -s 00:1f.0 dc.b=09\n```\nRemove WP from protected ranges:\n```\nsudo chipsec_util mmio write SPIBAR 0x74 0x4 0xAAF0800\nsudo chipsec_util mmio write SPIBAR 0x78 0x4 0xADE0AD0\nsudo chipsec_util mmio write SPIBAR 0x7C 0x4 0xB100B10\nsudo chipsec_util mmio write SPIBAR 0x80 0x4 0xBFF0B40\n```\nVerify that it worked:\n```\nsudo chipsec_main -m common.bios_wp\n```\n```\n[x][ =======================================================================\n[x][ Module: BIOS Region Write Protection\n[x][ =======================================================================\n[*] BC = 0x 9 \u003c\u003c BIOS Control (b:d.f 00:31.0 + 0xDC)\n    [00] BIOSWE           = 1 \u003c\u003c BIOS Write Enable\n    [01] BLE              = 0 \u003c\u003c BIOS Lock Enable\n    [02] SRC              = 2 \u003c\u003c SPI Read Configuration\n    [04] TSS              = 0 \u003c\u003c Top Swap Status\n    [05] SMM_BWP          = 0 \u003c\u003c SMM BIOS Write Protection\n[-] BIOS region write protection is disabled!\n\n[*] BIOS Region: Base = 0x00500000, Limit = 0x00BFFFFF\nSPI Protected Ranges\n------------------------------------------------------------\nPRx (offset) | Value    | Base     | Limit    | WP? | RP?\n------------------------------------------------------------\nPR0 (74)     | 0AAF0800 | 00800000 | 00AAF000 | 0   | 0\nPR1 (78)     | 0ADE0AD0 | 00AD0000 | 00ADE000 | 0   | 0\nPR2 (7C)     | 0B100B10 | 00B10000 | 00B10000 | 0   | 0\nPR3 (80)     | 0BFF0B40 | 00B40000 | 00BFF000 | 0   | 0\nPR4 (84)     | 00000000 | 00000000 | 00000000 | 0   | 0\n```\n\nBingo!\n\nNow you can flash coreboot (or anything else) with flashrom.\n\nRemember to flash only `bios` region (use `--ifd -i bios -N`). `fd` and `me` are\nstill not writable.\n\n**Note:** if you're flashing coreboot for the first time, you should have an\nexternal SPI programmer just in case. It will help you recover if you flash\nnon-working ROM.\n\n## About Intel ME\n\nUnlocking PRx doesn't allow you to flash ME or Flash Descriptor, so you cannot\nuse [me_cleaner](https://github.com/corna/me_cleaner). Both `me` and `fd`\nregions will still be write-protected even if you flash coreboot. For now, the\nbest way to get rid of ME is to flash me_cleaned firmware externally.\n\nAs an alternative, you can use Soft Temporary Disable Mode. This is ME's\nbuilt-in mechanism that BIOS can use to \"ask\" ME to disable itself on the next\nboot. In this mode ME doesn't load its kernel and stops at BUP phase. This mode\nis saved to ME NVRAM and thus preserved between reboots and poweroffs. Working\npatch for coreboot is [available](https://review.coreboot.org/c/coreboot/+/37115).\n\nSome possible future solutions are described below.\n\n#### HMRFPO (updated: won't work)\n\n**HMRFPO** (Host ME Region Flash Protection Override) is a command BIOS can use\nto unlock ME region on SPI flash for writing. Vendor can disable it during\nmanufacturing. Unfortunately it's disabled on ThinkPads and can't be used.\n\n#### HDA_SDO (not implemented)\n\nIt is possible to make flash descriptor writable for one boot by asserting\nHDA_SDO pin high on boot. It should be possible to flash unlocked descriptor\nwhile in this state, and that should open ability to flash ME afterwards.\n[See here for more info](#hda_sdogpio33).\n\n# Sandy Bridge series (X220, T420, etc.): WIP\nS3 Boot Scripts are unprotected on these models too (even on the most recent\nBIOS versions), but it's not useful, because FLOCKDN and SPI protected ranges\nare set by **LenovoFlashProtectPei** UEFI module. It is trivial to patch it, but\nit resides in protected range, so it can only be flashed externally.\n\nCurrently there are no known methods to unlock PRs on these devices internally,\nbut investigation is ongoing.\n\n\n# Penryn and Nehalem series (X200, T400, X201, T410, etc.): WIP\nCurrently, the only known way to flash these models without external SPI\nprogrammer is by using GPIO33. It is not properly documented yet, and no scripts\nto automate the process were written. There was a success story though: a user\nfrom #coreboot/#libreboot IRC channels has successfully corebooted his X201\nwithout touching the SPI chip.\n\nProgress is tracked [here](https://notabug.org/libreboot/libreboot/issues/689).\n\n# Common methods\n\n## HDA_SDO/GPIO33\nThere's known Intel \"feature\", sometimes called \"pinmod\": you can make flash\ndescriptor writable for one boot by asserting HDA_SDO pin on the motherboard\nhigh (on older platforms, you need to assert GPIO33 pin low) at boot time.\n**Writable flash descriptor** sometimes **allows to flash whole BIOS region**\nusing a couple of neat tricks.  I will show this using X220 as an example.\n\nThis is SPI flash layout on X220:\n```\n00000000:00000fff fd\n00500000:007fffff bios\n00003000:004fffff me\n00001000:00002fff gbe\n```\nLenovo BIOS protects, using PR0 register, only small (but critical) part of it:\n`0x00780000-0x1ffffff`.\n\n\u003e PR0 defines the end of protected range as `0x1ffffff`, but since it's 8MB chip\nand `bios` ends at `0x007fffff`, `0x00780000-0x007fffff` is what actually is\nprotected. This is the last 512K.\n\nAs you can see, `0x00500000-0x0077ffff` part is totally writable.\n\nSince flash descriptor is writable too, here is what we can do:\n- patch flash descriptor:\n  - redefine `bios` as `00500000:0077ffff` using ifdtool;\n  - define the rest of it (`00780000:007fffff`) as `pd` (Platform Data). This is\n    **required**, otherwise you will not be able to flash it in future;\n  - unlock FD and ME regions (`ifdtool -u`);\n- build and flash (small enough) coreboot ROM to this region (must be careful\n  and make sure that reset vector is at the end of our custom region and not at\n  the end of 8MB ROM; use dd or ifdtool for that);\n- flash modified descriptor;\n- power off (new FD takes effect after cold boot);\n- wait a few seconds and power on.\n\nAfter this, new FD will be in effect and coreboot will be loaded from\n`0x00500000-0x0077ffff` region, instead of Lenovo BIOS. At this point whole\n`0x00500000-0x007fffff` will be writable and you will be able to flash coreboot\nagain or patched vendor BIOS (don't forget to revert `fd` changes regarding the\n`bios` region).\n\nA user from #coreboot/#libreboot IRC channels was able to flash his X201\ninternally using the idea described above. However, this is not for mass use\nyet: we need to write scripts to automate the process, locate HDA_SDO or GPIO33\npins on all motherboards in interest, take their photos and explain, what to do\nwith what.\n\n# Credits\n**Rafal Wojtczuk** and **Corey Kallenberg** for discovering the S3 Boot Scripts\nvulnerability\n\n[pgera](https://github.com/hamishcoleman/thinkpad-ec/issues/70#issuecomment-417903315)\nfor the initial research and working solution\n\nLenovo for fake rollback protection\n\n# License\n\nThis document is licensed under [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/)\nterms.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgch1p%2Fthinkpad-bios-software-flashing-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgch1p%2Fthinkpad-bios-software-flashing-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgch1p%2Fthinkpad-bios-software-flashing-guide/lists"}