Леонид МаслаковLenpaste

Установка Coreboot на Thinkpad X230/X230i

20.11.2023

В этой статье рассказывается о том как разобрать Thinkpad X230/X230i, записать/считать BIOS с помощью программатора CH341A, а так же как собрать Coreboot из исходного кода именно под эту модель Thinkpad.

Внимательно читайте всё что написано в этой статье, в противном случаи вы можете по неосторожности превратить ваш ноутбук в жаренную картошку.

Введение

Разница между X230 и X230i

Thinkpad X230i отличается от Thinkpad X230 только используемой моделью процессора, “i”-версия поставляется с процессором i3, а обычная X230 с процессором i5 или i7.

Данная инструкция может применятся как к X230, так и к X230i. Например я произвожу все действия на Thinkpad X230i с процессором “Intel i3-2370M”.

Можно ли прошивать заблокированный Thinkpad?

Да можно, после прошивки пароль BIOS и привязка к Computrace будут удалены. Я например прошиваю Thinkpad, отказывающейся загружаться с ошибкой 0199: System Security - Security password retry count exceeded.

Внешняя или внутренняя прошивка?

Есть два способа установить кастомный BIOS, неподписанный Lenovo, на Thinkpad X230/X230i.

Первый (внешняя прошивка), физически подключиться к чипам BIOS с помощью программатора и загрузить на них требуемую прошивку. В этой статье описывается именно этот способ.

Второй (программный), эксплуатировать уязвимость в штатном механизме обновления BIOS. Прошивка с помощью этого метода не рекомендуется, так как вы можете получить ноутбук с нерабочим BIOS, неспособным загрузить ОС или установить обновления BIOS.

Необходимые инструменты

Для начало вам нужно подготовить всё необходимое:

  • Thinkpad X230/X230i;
  • другой компьютер под управлением Linux с архитектурой AMD64 (Raspberry Pi или Orange Pi не подойдут);
  • программатор CH341A (CH341A Pro) на 3.3 вольта;
  • крестовая отвёртка;
  • магнит (что бы не потерять винты);
  • пластиковая карточка.

Важный момент. Программаторы CH341A с чёрной платой, как на фото выше, могут выдавать 5 вольт вместо 3.3 вольт. В случаи того если вы попытается записать или считать чип BIOS таким программатором, то вы просто сожжёте сам чип или материнскую плату. Внимательно проверьте ваш программатор, он должен быть именно на 3.3 вольта!

Разбираем Thinkpad

Для того что бы добраться до чипов BIOS нужно разобрать Thinkpad, сделать это достаточно просто, сам ноутбук сконструирован так что бы его можно было достаточно быстро разобрать для замены комплектующих.

Отключаем внешнею батарею и выкручиваем 7 винтов, обозначенных на фото ниже. Вытаскивать жёсткий диск и ОЗУ не требуется.

Теперь нужно удалить клавиатуру, для этого открываем ноутбук и просовываем пластиковую карту в щель между топ-кейсом и клавиатурой, как показано на фото ниже (кнопки тачпада являться частью клавиатуры). Не спешите сразу дёргать клавиатуру вверх, под ней находиться шлейф который так же надо будет отключить.

Для отключения шлейф клавиатуры (на фото он жёлтого цвета) просто тянем его наверх за специально сделанный для этого “хлястик”. Так же нужно отключить шлейф тачпада, откидываем пластиковую “застёжку” на разъёме вверх, после чего вытаскиваем шлейф за специально сделанный для этого синий “хлястик”.

С пластиковой накладкой на которой находиться тачпад поступаем точно так же как с клавиатурой, просовываем пластиковую карту в щель и поднимаем вверх. Ни каких шлейфов больше отключать не нужно, так что можно сразу убирать накладку в сторону.

Последнее что следует сделать перед тем как вы начнёте считывать чипы BIOS с помощью программатора - это отключение батарейки CMOS. Батарейка жёлтого цвета, так что вы без проблем её найдёте (на моём фото батарейка уже отключена). Не пренебрегайте этим шагом, в противном случаи есть риск поджарить что нибудь в Thinkpad-е при использовании программатора.

В Thinkpad X230/X230i чипа BIOS два верхний на 4 мегабайта и нижний на 8, находятся они в левом нижнем углу ноутбука под чёрной пластиковой плёнкой.

Сборка программатора

Программаторы CH341A могут достаточно сильно отличаться друг от друга, так что если вдруг вам программатор не похож на мой, то просто поищите инструкцию для вашего программатора в интернете.

Мой программатор пришёл в разобранном виде без инструкции, так что нужно его собрать.

И так инструкция по сборке в картинках. Смотрите куда идёт красный провод от “прищепки” внимательно!

Отдельно стоит отметить перемычку (на фото она чёрного цвета), она должна быть установлена в положение “1-2 программирование” (есть ещё положение 2-3). Все возможные состояния перемычки можно посмотреть на обратной стороне программатора (Google Translate для перевода с китайского вам в помощь).

Считываем оригинальный BIOS

Оригинальный BIOS Thinkpad нужен нам по двум причинам. Во первых хорошо бы было сделать бэкап на случай, если что то пойдёт не так. А во вторых нам нужно достать из дампа BIOS регион Intel ME, серийник материнской платы, MAC адрес адаптера отвечающего за порт Ethernet, а так же некоторый другие вещи.

Для работы с программатором CH341A из под Linux существует утилита Flashrom, устанавливаем её:

sudo apt install flashrom

Сначала нужно подключить программатор к чипу, а только потом вставлять его в USB порт компьютера! Разборка производиться в обратном порядки, сначала выключить из USB, а потом снять “прищепку” с чипа. В противном случаи при подключении “прищепки” к чипу может проскочить искра которая сожжёт вам чип BIOS.

Считывать чипы BIOS можно в любом порядке, я начну с верхнего чипа объёмом 4 мегабайта.

Нужно подключиться к чипам BIOS с помощью “прищепки”. Важном что бы первый контакт программатора (провод красного цвета, идущий к “прищепке”) был подключен к первому контакту чипа, обозначенному на текстолите материнской платы белым треугольником (обведён на фото в красный круг).

Если при попытки считывания чипа вы получите ошибку приведённую ниже, то проверьте контакт программатора и USB порта компьютера. Так же эта ошибка может означать что программатор не исправен.

flashrom unknown on Linux 6.1.0-13-amd64 (x86_64)
flashrom is free software, get the source code at https://flashrom.org

Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Couldn't open device 1a86:5512.
Error: Programmer initialization failed.

Если в процессе считывания вы будете наблюдать ошибку приведённую ниже, то попробуйте отключить “прищепку”, а затем подключить её к чипу BIOS снова, возможно у вас просто плохой контакт с чипом BIOS. Иногда для установления хорошего контакта может потребоваться 5-10 попыток.

flashrom unknown on Linux 6.1.0-13-amd64 (x86_64)
flashrom is free software, get the source code at https://flashrom.org

Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
No EEPROM/flash device found.
Note: flashrom can never write if the flash chip isn't found automatically.

Попробуем считать данные с чипа BIOS:

sudo flashrom --programmer ch341a_spi -r ./bios_top_1.bin
flashrom unknown on Linux 6.1.0-13-amd64 (x86_64)
flashrom is free software, get the source code at https://flashrom.org

Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Macronix flash chip "MX25L3205(A)" (4096 kB, SPI) on ch341a_spi.
Found Macronix flash chip "MX25L3205D/MX25L3208D" (4096 kB, SPI) on ch341a_spi.
Found Macronix flash chip "MX25L3206E/MX25L3208E" (4096 kB, SPI) on ch341a_spi.
Found Macronix flash chip "MX25L3233F/MX25L3273E" (4096 kB, SPI) on ch341a_spi.
Multiple flash chip definitions match the detected chip(s): "MX25L3205(A)", "MX25L3205D/MX25L3208D", "MX25L3206E/MX25L3208E", "MX25L3233F/MX25L3273E"
Please specify which chip definition to use with the -c <chipname> option.

Как видите считывание закончилось не удачей из-за того что Flashrom не смог определить модель чипа. Самый очевидный способа узнать модель чипа BIOS, это просто посмотреть маркировку на самом чипе. Но на моём чипе маркировка стёрта, так что я не могу её прочитать, по этому я просто перебирал все варианты, предложенные Flashrom, пока не нашёл нужный.

sudo flashrom --programmer ch341a_spi -c "MX25L3206E/MX25L3208E" -r ./bios_top_1.bin
flashrom unknown on Linux 6.1.0-13-amd64 (x86_64)
flashrom is free software, get the source code at https://flashrom.org

Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Macronix flash chip "MX25L3206E/MX25L3208E" (4096 kB, SPI) on ch341a_spi.
===
This flash part has status UNTESTED for operations: WP
The test status of this chip may have been updated in the latest development
version of flashrom. If you are running the latest development version,
please email a report to flashrom@flashrom.org if any of the above operations
work correctly for you with this flash chip. Please include the flashrom 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!
Reading flash... done.

После указания модели чипа чтение чипа завершилось успешно.

Теперь я считываю содержимое чипа, после чего сверяю хэш суммы двух дампов BIOS, для того что бы убедиться что всё прошло успешно.

$ sudo flashrom --programmer ch341a_spi -c "MX25L3206E/MX25L3208E" -r ./bios_top_2.bin
...

$ md5sum ./bios_top_1.bin ./bios_top_2.bin
e1d6b576a43195edd0f0835d5c5c4e86  ./bios_top_1.bin
e1d6b576a43195edd0f0835d5c5c4e86  ./bios_top_2.bin

Повторяем всё тоже самое для нижнего чипа, не забыв предварительно подключить к нему “прищепку”:

$ sudo flashrom --programmer ch341a_spi -c "MX25L6406E/MX25L6408E" -r ./bios_bottom_1.bin
flashrom unknown on Linux 6.1.0-13-amd64 (x86_64)
flashrom is free software, get the source code at https://flashrom.org

Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Macronix flash chip "MX25L6406E/MX25L6408E" (8192 kB, SPI) on ch341a_spi.
===
This flash part has status UNTESTED for operations: WP
The test status of this chip may have been updated in the latest development
version of flashrom. If you are running the latest development version,
please email a report to flashrom@flashrom.org if any of the above operations
work correctly for you with this flash chip. Please include the flashrom 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!
Reading flash... done.

$ sudo flashrom --programmer ch341a_spi -c "MX25L6406E/MX25L6408E" -r ./bios_bottom_2.bin
...

$ md5sum ./bios_bottom_1.bin ./bios_bottom_2.bin
4723606a47fcf5586ad687b920cf24cb  ./bios_bottom_1.bin
4723606a47fcf5586ad687b920cf24cb  ./bios_bottom_2.bin

Компиляция Coreboot

Устанавливаем зависимости для сборки:

sudo apt install bison build-essential curl flex git gnat libncurses5-dev m4 zlib1g-dev autopoint python-is-python3

Скачиваем исходный код:

git clone https://review.coreboot.org/coreboot
cd ./coreboot/
git checkout 4.21
git submodule update --init --checkout

Coreboot использует toolchain содержащий компиляторы и другие инструменты (GCC, GMP, NASM), это нужно для поддержания воспроизводимости сборок (reproducible build). Например Coreboot будет использовать версию GCC из своего тулчейна, а не ту что установлена в системе. И так собираем toolchain (сборка будет длиться несколько часов):

make crossgcc-i386 CPUS=$(nproc)

Собираем утилиту ifdtool, позволяющею достать нужные данные из дампа BIOS:

make -C ./util/ifdtool

Разбираем дамп BIOS на части:

cat ../bios_bottom_1.bin ../bios_top_1.bin > ../x230_bios.bin
./util/ifdtool/ifdtool -x ../x230_bios.bin
Warning: No platform specified. Output may be incomplete
File /home/leonidm/Downloads/x230_bios.bin is 12582912 bytes
  Flash Region 0 (Flash Descriptor): 00000000 - 00000fff 
  Flash Region 1 (BIOS): 00500000 - 00bfffff 
  Flash Region 2 (Intel ME): 00003000 - 004fffff 
  Flash Region 3 (GbE): 00001000 - 00002fff 
  Flash Region 4 (Platform Data): 00fff000 - 00000fff (unused)

WARNING можем смело игнорировать. Перемещаем полученные части в соответствующее место в дереве исходного кода Coreboot:

mkdir -p ./3rdparty/blobs/mainboard/lenovo/x230/
mv ./flashregion_0_flashdescriptor.bin ./3rdparty/blobs/mainboard/lenovo/x230/descriptor.bin
mv ./flashregion_1_bios.bin ./3rdparty/blobs/mainboard/lenovo/x230/bios.bin
mv ./flashregion_2_intel_me.bin ./3rdparty/blobs/mainboard/lenovo/x230/me.bin
mv ./flashregion_3_gbe.bin ./3rdparty/blobs/mainboard/lenovo/x230/gbe.bin

Теперь конфигурируем Coreboot под Thinkpad X230/X230i:

make menuconfig

В открывшемся псевдографическом окне выбираем следующие настройки:

  • Mainboard
    • Mainboard vendor = Lenovo
    • Mainboard model = Thinkpad X230
    • ROM chip size = 12 MB
    • Size of CBFS filesystem in ROM = 0x100000 (1 мегабайт)
  • Chipset
    • Include CPU microcode in CBFS = Generate from tree
    • Add Intel description.bin file = включен
    • Add Intel ME/TXE firmware = включен
    • Verify the integrity of the supplied ME/TXE firmware = включен
    • Strip down the Intel ME/TXE firmware = включен
    • Add gigabit ethernet configuration = включен
    • Protect flash regions = Unlock flash regions
  • Devices
    • Graphics initialization = Use libgfxinit
    • Display
      • Framebuffer mode = Legacy VGA text mode
    • Add a Video BIOS Table (VBT) binary to CBFS = включен
  • Generic Drivers
    • PS/2 keyboard = включен
  • Payload
    • Payload to add = SeaBIOS
    • PS/2 keyboard controller initialization timeout = 10
    • Include generated option rom that implements legacy VGA BIOS compatibility = включен
    • Use LZMA compression for secondary payloads = включен
    • Secondary payloads
      • Load coreinfo as a secondary payload = включен
      • Load nvramcui as a secondary payload = включен

После того как все настройки выбраны сохраняем конфиг с помощью SAVE и выходим с помощью EXIT.

Теперь можно компилировать Coreboot:

make

Прошиваем Coreboot

Coreboot собрался в виде одного бинарника на 12 мегабайт, а чипа у нас два, так что результат сборки Coreboot надо разбить на два файла:

dd if=./build/coreboot.rom of=../x230_coreboot_bottom.bin bs=1M count=8
dd if=./build/coreboot.rom of=../x230_coreboot_top.bin bs=1M skip=8

Теперь подключаем прищепку к верхнему чипу и прошиваем его:

sudo flashrom --programmer ch341a_spi -c "MX25L3206E/MX25L3208E" -w ../x230_coreboot_top.bin

Тоже самое делаем с нижним чипом:

sudo flashrom --programmer ch341a_spi -c "MX25L6406E/MX25L6408E" -w ../x230_coreboot_bottom.bin

Теперь нужно собрать Thinkpad:

  1. подключаем батарейку BIOS;
  2. устанавливаем на место нижнею накладку;
  3. подключаем два шлейфа (от тачпада и от клавиатуры);
  4. ставим на место клавиатуру;
  5. закручиваем 7 винтов на задней части Thinkpad;
  6. подключаем батарею;
  7. включаем.

Обновление Coreboot без программатора

Так как в Coreboot при компиляции была установлена настройка Chipset –> Protect flash regions = Unlock flash regions, то теперь можно обновляться с помощью штатных средств Coreboot.

Обновляется выполняется из запущенного на вашем Thinkpad-е Linux-а:

sudo flashrom -p internal -w ./build/coreboot.rom
flashrom unknown on Linux 6.1.0-13-amd64 (x86_64)
flashrom is free software, get the source code at https://flashrom.org

Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
coreboot table found at 0x7ff64000.
Found chipset "Intel QM77".
Enabling flash write... SPI Configuration is locked down.
FREG0: Flash Descriptor region (0x00000000-0x00000fff) is read-write.
FREG1: BIOS region (0x00500000-0x00bfffff) is read-write.
FREG2: Management Engine region (0x00003000-0x004fffff) is read-write.
FREG3: Gigabit Ethernet region (0x00001000-0x00002fff) is read-write.
Enabling hardware sequencing due to multiple flash chips detected.
OK.
Found Programmer flash chip "Opaque flash chip" (12288 kB, Programmer-specific) on internal.
Reading old flash chip contents... done.
Erasing and writing flash chip... Erase/write done.
Verifying flash... VERIFIED.

Если вы видите ошибку вроде приведённой ниже, то попробуйте запустить ядро Linux с параметром iomem=relaxed.

flashrom unknown on Linux 6.1.0-13-amd64 (x86_64)
flashrom is free software, get the source code at https://flashrom.org

Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
coreboot table found at 0x7ff64000.
Found chipset "Intel QM77".
Enabling flash write... Error accessing ICH RCRB, 0x4000 bytes at 0x00000000fed1c000
/dev/mem mmap failed: Operation not permitted
FAILED!
FATAL ERROR!
Error: Programmer initialization failed.

Ссылки