Podczas prac nad własnym firmware Coreboot 26.09 dla Lenovo ThinkPad T400 z procesorem Intel Core 2 Quad Q9100 natrafiłem na dwa problemy związane z narzędziami diagnostycznymi. Pierwszym był komunikat „IO space mapped serial not present”, pojawiający się podczas uruchamiania wybranych payloadów. Drugim – nieprawidłowa, czerwono-różowa kolorystyka Memtest86+ 6.20 działającego w trybie graficznym.

Oba problemy udało mi się rozwiązać bez rezygnowania z graficznego GRUB2 i bez przebudowywania całego firmware od początku. Co ważne, nie zastosowałem przypadkowych obejść. Znalazłem przyczyny w konfiguracji biblioteki libpayload oraz w kodzie asemblera narzędzia cbfstool. Poprawki przetestowałem na fizycznym ThinkPadzie T400 i potwierdziłem ich skuteczność.

Postanowiłem dokładnie udokumentować cały proces, ponieważ w przyszłości te informacje mogą przydać mi się podczas aktualizacji Coreboota na innych ThinkPadach. Zapisuję więc nie tylko rozwiązania, ale również błędy popełnione podczas kompilacji, istotne ustawienia i sposoby weryfikacji gotowych obrazów firmware.

ThinkPad T400 Quad Core Edition – konfiguracja sprzętu i firmware

Komputer, na którym przeprowadziłem wszystkie testy, to Lenovo ThinkPad T400 6474-D8B. Laptop został wcześniej zmodyfikowany sprzętowo, aby obsługiwać czterordzeniowy procesor Intel Core 2 Quad Q9100. Modernizacja wymagała między innymi odpowiedniej modyfikacji sygnału GTLREF.

Mój T400 wyposażony jest w 8 GB pamięci RAM, zintegrowany układ graficzny Intel GMA 4500MHD oraz matrycę o rozdzielczości 1280 × 800. Na komputerze działa Debian 13 Trixie ze środowiskiem Cinnamon.

Firmware zbudowałem na podstawie Coreboot 26.09. Jako główny payload wybrałem GRUB2 2.14 z własnym motywem graficznym przygotowanym specjalnie dla tego modelu. Menu umożliwia uruchamianie Debiana, SeaBIOS oraz narzędzi Coreinfo, NVRAMCUI, Tint i Memtest86+.

Do inicjalizacji grafiki wykorzystuję libgfxinit z włączonym liniowym framebufferem:

CONFIG_MAINBOARD_USE_LIBGFXINIT=y
CONFIG_GENERIC_LINEAR_FRAMEBUFFER=y

Prace wykonywałem w środowisku Linux pod WSL. Główny katalog mojego projektu znajdował się pod ścieżką:

~/coreboot-t400-grub2

Źródła Coreboota przechowywałem w podkatalogu coreboot, obrazy firmware w images, natomiast kopie zapasowe konfiguracji i wcześniej zbudowanych komponentów w backup.

W trakcie dopracowywania firmware powstało kilka kolejnych wersji. V4 zawierała gotowy motyw GRUB2, V5 usuwała problem konsoli szeregowej, a V6 naprawiała wyświetlanie kolorów Memtest86+. Każdą następną wersję przygotowywałem na podstawie poprzedniej, zachowując sprawdzone komponenty.

Błąd IO space mapped serial not present – skąd pochodzi komunikat?

Pierwszy problem zauważyłem podczas uruchamiania narzędzi diagnostycznych z poziomu mojego menu GRUB2. Na ekranie pojawiał się komunikat:

IO space mapped serial not present.

Początkowo podejrzewałem problem z konfiguracją konsoli w Coreboocie. Narzędzia działały jednak prawidłowo, więc nie wyglądało to na poważną usterkę. Postanowiłem sprawdzić, gdzie dokładnie generowany jest ten komunikat.

Przeszukanie źródeł doprowadziło mnie do biblioteki libpayload, a konkretnie do pliku:

coreboot/payloads/libpayload/drivers/serial/8250.c

W okolicy linii 118 znalazłem instrukcję:

printf("IO space mapped serial not present.");

Komunikat generowany jest podczas inicjalizacji obsługi UART 8250, gdy biblioteka nie znajduje oczekiwanego portu szeregowego w przestrzeni I/O.

W moim przypadku nie oznaczało to uszkodzenia laptopa. Problem wynikał z tego, że wybrane payloady były kompilowane z obsługą konsoli szeregowej, mimo że do ich działania wykorzystywałem wyłącznie ekran i klawiaturę T400.

Wniosek był prosty: zamiast zmieniać główne ustawienia Coreboota, powinienem wyłączyć niepotrzebny UART w konfiguracjach libpayload poszczególnych narzędzi.

Coreboot i libpayload – dlaczego konfiguracje konsoli szeregowej są niezależne?

To jedna z najważniejszych rzeczy, które ustaliłem podczas rozwiązywania problemu. Coreboot i programy korzystające z libpayload nie muszą używać identycznej konfiguracji konsoli.

W głównym pliku .config mojego Coreboota miałem aktywne następujące opcje:

CONFIG_CONSOLE_SERIAL=y
CONFIG_DRIVERS_UART_8250IO=y
CONFIG_UART_FOR_CONSOLE=0
CONFIG_TTYS0_BAUD=115200

Nie zdecydowałem się ich zmieniać. Główna konsola Coreboota i konsola libpayload to dwie odrębne kwestie, dlatego globalne wyłączanie UART nie było potrzebne.

Sprawdziłem natomiast konfiguracje libpayload wykorzystywane przez Coreinfo, NVRAMCUI i Tint. We wszystkich trzech przypadkach znalazłem aktywne opcje:

CONFIG_LP_SERIAL_CONSOLE=y
CONFIG_LP_8250_SERIAL_CONSOLE=y

Moim celem było uzyskanie konfiguracji, w której konsola szeregowa pozostaje wyłączona, ale obsługa ekranu nadal działa:

# CONFIG_LP_SERIAL_CONSOLE is not set
# CONFIG_LP_8250_SERIAL_CONSOLE is not set
CONFIG_LP_VIDEO_CONSOLE=y
CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y

Nie wszystkie opcje muszą być jawnie widoczne w ostatecznym pliku .config. Zależności Kconfig mogą wyeliminować niektóre ustawienia. Najważniejsze jest to, aby żadna z opcji odpowiedzialnych za niepotrzebną konsolę szeregową nie była aktywna.

Ta poprawka ma sens wtedy, gdy konkretny payload nie wymaga UART. Jeżeli na innym komputerze wykorzystam port szeregowy do diagnostyki, nie powinienem automatycznie wyłączać tych opcji.

Coreinfo – przygotowanie libpayload z Tinycurses bez UART

Najpierw zająłem się Coreinfo. Narzędzie wykorzystuje bibliotekę libpayload oraz Tinycurses, czyli uproszczoną implementację interfejsu curses.

W mojej wersji Coreboota odpowiedni plik konfiguracyjny znajdował się tutaj:

coreboot/payloads/libpayload/configs/defconfig-tinycurses

Nie chciałem modyfikować oryginalnego pliku. Utworzyłem więc jego kopię przeznaczoną specjalnie do przebudowy payloadów T400 bez konsoli szeregowej.

cp coreboot/payloads/libpayload/configs/defconfig-tinycurses coreboot/payloads/libpayload/configs/defconfig-t400-noserial

Do nowej konfiguracji dopisałem:

# CONFIG_LP_SERIAL_CONSOLE is not set
# CONFIG_LP_8250_SERIAL_CONSOLE is not set

Można to zrobić również za pomocą jednej komendy:

printf '\n# CONFIG_LP_SERIAL_CONSOLE is not set\n# CONFIG_LP_8250_SERIAL_CONSOLE is not set\n' >> coreboot/payloads/libpayload/configs/defconfig-t400-noserial

Tak przygotowana konfiguracja zachowała Tinycurses i obsługę grafiki. Następnie przebudowałem Coreinfo, wskazując nowy plik defconfig:

make -C coreboot/payloads/coreinfo LIBPAYLOAD_DEFCONFIG="$PWD/coreboot/payloads/libpayload/configs/defconfig-t400-noserial" defaultbuild

Po zakończeniu kompilacji sprawdziłem plik:

coreboot/payloads/coreinfo/.lp.config

Upewniłem się, że konsola szeregowa została wyłączona, a następnie zweryfikowałem gotowy plik:

coreboot/payloads/coreinfo/build/coreinfo.elf

Kompilacja zakończyła się prawidłowo. Co istotne, w nowym pliku ELF nie występował już komunikat o niedostępnym porcie szeregowym.

NVRAMCUI – problem z form.h i konieczność zastosowania PDCurses

Następnie przeszedłem do NVRAMCUI. Początkowo próbowałem wykorzystać ten sam defconfig oparty na Tinycurses, który wcześniej zastosowałem dla Coreinfo. To okazało się błędem.

Kompilacja zatrzymała się na komunikacie:

nvramcui.c:19:10: fatal error: form.h: No such file or directory

Po analizie przyczyny okazało się, że NVRAMCUI wymaga obsługi formularzy dostępnej w PDCurses. Tinycurses nie zapewnia wszystkich niezbędnych funkcji, dlatego nie można bezrefleksyjnie stosować jednej konfiguracji libpayload dla wszystkich payloadów.

Przygotowałem więc osobny plik konfiguracyjny:

coreboot/payloads/libpayload/configs/defconfig-t400-nvramcui-noserial

Jako punkt wyjścia wykorzystałem standardowy defconfig libpayload, a następnie ustawiłem:

CONFIG_LP_CURSES=y
# CONFIG_LP_TINYCURSES is not set
CONFIG_LP_PDCURSES=y
# CONFIG_LP_SERIAL_CONSOLE is not set
# CONFIG_LP_8250_SERIAL_CONSOLE is not set
CONFIG_LP_VIDEO_CONSOLE=y
CONFIG_LP_COREBOOT_VIDEO_CONSOLE=y

Ważne było również usunięcie pozostałości po wcześniejszej, nieudanej kompilacji z Tinycurses. Zabezpieczyłem stary plik ELF, po czym wykonałem czyszczenie katalogu kompilacji NVRAMCUI:

make -C coreboot/payloads/nvramcui distclean

Następnie uruchomiłem ponowną kompilację:

make -C coreboot/payloads/nvramcui LIBPAYLOAD_DEFCONFIG="$PWD/coreboot/payloads/libpayload/configs/defconfig-t400-nvramcui-noserial" all

Tym razem proces zakończył się pomyślnie. W pliku .lp.config potwierdziłem aktywne PDCurses oraz wyłączoną konsolę szeregową.

Gotowy NVRAMCUI działał prawidłowo, a komunikat IO space mapped serial not present nie występował.

To cenna wskazówka na przyszłość: przed zmianą konfiguracji libpayload trzeba sprawdzić, z której implementacji curses korzysta dane narzędzie i jakich funkcji potrzebuje.

Tint – dlaczego musiałem przebudować osobną bibliotekę libpayload?

Trzecim narzędziem wymagającym poprawki był Tint. W jego przypadku problem okazał się nieco inny, ponieważ projekt przechowywał własną, wcześniej skompilowaną bibliotekę libpayload.

Znajdowała się ona w katalogu:

coreboot/payloads/external/tint/tint/build/libpayload

Sprawdziłem plik libpayload.config i potwierdziłem obecność następujących ustawień:

CONFIG_LP_SERIAL_CONSOLE=y
CONFIG_LP_8250_SERIAL_CONSOLE=y

Użyłem także narzędzia strings do sprawdzenia zawartości biblioteki:

strings coreboot/payloads/external/tint/tint/build/libpayload/lib/libpayload.a | grep -i 'serial not present'

Wynik potwierdził, że biblioteka zawiera tekst:

IO space mapped serial not present.

Analiza Makefile Tint ujawniła dodatkową pułapkę. Jeżeli katalog zawiera już zbudowaną bibliotekę libpayload.a, mechanizm kompilacji może wykorzystać ją ponownie. Samo przekazanie nowej konfiguracji LIB_CONFIG nie wystarczy wówczas do wymuszenia przebudowy.

Dlatego najpierw zabezpieczyłem stare pliki wynikowe, w tym katalog build/libpayload oraz pliki obiektowe Tint. Dopiero później uruchomiłem nową kompilację.

make -C coreboot/payloads/external/tint/tint LIB_CONFIG=configs/defconfig-t400-noserial all

W ten sposób wykorzystałem przygotowaną wcześniej konfigurację Tinycurses z wyłączonym UART.

Po zakończeniu sprawdziłem nowo wygenerowany plik libpayload.config. Potwierdziłem, że Tinycurses pozostało aktywne, konsola graficzna działa, a konsola szeregowa jest wyłączona.

Nowy tint.elf został poprawnie skompilowany i po dodaniu do CBFS działał bez błędów.

Weryfikacja trzech payloadów – sprawdzenie gotowych plików ELF

Nie chciałem opierać się wyłącznie na informacjach z plików konfiguracyjnych. Zależało mi na sprawdzeniu, czy końcowe programy rzeczywiście nie zawierają już problematycznego komunikatu.

W tym celu wykorzystałem polecenie strings dla każdego z trzech plików ELF:

strings coreboot/payloads/coreinfo/build/coreinfo.elf | grep -F 'IO space mapped serial not present'

strings coreboot/payloads/nvramcui/build/nvramcui.elf | grep -F 'IO space mapped serial not present'

strings coreboot/payloads/external/tint/tint/tint.elf | grep -F 'IO space mapped serial not present'

Żadne z poleceń nie znalazło poszukiwanego tekstu. Sprawdziłem również konfiguracje libpayload oraz format wygenerowanych plików wykonywalnych.

Ostatecznie wszystkie trzy payloady skompilowały się prawidłowo. Na ich podstawie przygotowałem nowy ROM V5, podmieniając w CBFS wyłącznie:

img/coreinfo
img/nvramcui
img/tint

Porównałem następnie zawartość V4 i V5. Wszystkie 27 pozostałych plików CBFS były identyczne, włącznie z GRUB2, SeaBIOS, Memtest86+, bootblockiem i zasobami graficznymi.

Po wgraniu V5 na ThinkPada T400 potwierdziłem, że narzędzia działają bez wcześniejszego komunikatu. Pierwszą poprawkę mogłem więc uznać za zakończoną.

Memtest86+ 6.20 wyświetla czerwone kolory – analiza problemu

Po dopracowaniu firmware zauważyłem kolejny szczegół. Memtest86+ 6.20 uruchamiał się i działał prawidłowo, ale jego interfejs miał nieprawidłową kolorystykę. Zamiast charakterystycznego niebieskiego tła widziałem czerwono-różowe odcienie.

Program poprawnie rozpoznawał procesor Intel Core 2 Quad Q9100, pamięć RAM i wykonywał testy. Nie wyglądało to na problem sprzętowy, lecz na nieprawidłową interpretację kolorów obrazu.

Mój GRUB2 uruchamiał się w rozdzielczości 1280 × 800 i korzystał z graficznego terminala:

set gfxmode=1280x800,auto
terminal_output gfxterm

Memtest86+ był uruchamiany bezpośrednio z CBFS:

chainloader /img/memtest

Postanowiłem sprawdzić, jak Memtest interpretuje informacje o framebufferze. Źródła znajdowały się w katalogu:

coreboot/payloads/external/Memtest86Plus/memtest86plus_v6

Najważniejszy okazał się plik:

system/screen.c

Memtest86+ pobiera informacje o obrazie ze struktury boot_params > screen_info. Na ich podstawie oblicza wartości kolorów, wykorzystując pozycje i rozmiary kanałów RGB:

screen_info->red_pos
screen_info->green_pos
screen_info->blue_pos
screen_info->red_size
screen_info->green_size
screen_info->blue_size

Jeżeli informacje o położeniu kanałów czerwonego i niebieskiego zostaną uszkodzone, program może nadal poprawnie wyświetlać interfejs, ale z niewłaściwymi kolorami.

Początkowo rozważałem poprawienie interpretacji RGB/BGR w samym Memteście. Dalsza analiza wykazała jednak, że przyczyna znajdowała się wcześniej, podczas przygotowywania payloadu przez Coreboot.

Linux trampoline w Coreboot – rzeczywista przyczyna czerwonego Memtest86+

Przełomem okazało się znalezienie błędu w pliku:

coreboot/util/cbfstool/linux_trampoline.S

W wykorzystywanym przeze mnie Coreboot 26.09, w okolicy linii 147, znajdowała się instrukcja:

rol %ax

Fragment odpowiadał za przekształcenie informacji o położeniu i rozmiarze składowych kolorów framebufferu do formatu oczekiwanego przez protokół uruchamiania Linuksa.

Problem polegał na tym, że instrukcja rol bez jawnie podanej liczby bitów wykonuje obrót o jeden bit. Tymczasem w tym przypadku konieczna była zamiana kolejności dwóch bajtów zapisanych w 16-bitowym rejestrze AX.

Poprawna instrukcja wygląda następująco:

rol $8, %ax

Obrót o osiem bitów zamienia miejscami oba bajty, zachowując ich zawartość. Obrót o jeden bit prowadzi natomiast do nieprawidłowego przekształcenia danych, w tym wartości odpowiadających za pozycje i rozmiary kanałów kolorów.

Dlaczego błąd dotyczył właśnie Memtest86+? Sprawdziłem format jego obrazu i ustaliłem, że w moim projekcie jest to:

Linux kernel x86 boot executable bzImage

Podczas dodawania takiego pliku do CBFS narzędzie cbfstool wykorzystuje funkcję:

parse_bzImage_to_payload()

Ta z kolei korzysta z mechanizmu:

bzp_add_trampoline()

Oznaczało to, że Memtest86+ przechodził przez wadliwy kod w linux_trampoline.S. Tym samym znalazłem konkretną przyczynę problemu, a nie tylko jego widoczny objaw.

Po poprawieniu instrukcji i ponownym spakowaniu Memtest86+ kolory wróciły do normy. Skuteczność poprawki potwierdziłem bezpośrednio na ThinkPadzie T400.

Poprawka linux_trampoline.S w Coreboot 26.09

Najpierw sprawdziłem wystąpienia instrukcji rol w pliku źródłowym:

grep -n 'rol.*%ax' coreboot/util/cbfstool/linux_trampoline.S

Następnie przygotowałem kopię zapasową oryginalnego pliku:

cp coreboot/util/cbfstool/linux_trampoline.S backup/linux_trampoline-before-v6.S

Zmiana polegała na zastąpieniu:

rol %ax

przez:

rol $8, %ax

W moim drzewie źródłowym było to jedno konkretne wystąpienie odpowiedzialne za kopiowanie parametrów kolorów.

Nie musiałem modyfikować kodu Memtest86+, zmieniać ustawień libgfxinit ani rezygnować z graficznego menu GRUB2. Wystarczyło poprawić fragment konwertera wykorzystywanego do pakowania obrazu bzImage.

Przy przyszłych aktualizacjach zamierzam zawsze sprawdzać ten plik, ale nie zakładam, że błąd występuje w każdej wersji Coreboota. Jeżeli instrukcja rol $8, %ax jest już obecna, nie ma potrzeby ponownego stosowania poprawki.

Przebudowa cbfstool – pułapka z wygenerowanym linux_trampoline.c

Podczas wdrażania tej poprawki natrafiłem na jeszcze jedną istotną rzecz.

Po zmodyfikowaniu linux_trampoline.S wykonałem zwykłą przebudowę cbfstool. Program został skompilowany, ale sprawdzenie dat plików wykazało, że wygenerowany linux_trampoline.c nadal pochodził ze starej kompilacji.

W efekcie istniało ryzyko, że nowy cbfstool nadal zawiera stary kod trampoliny, mimo że plik źródłowy .S został już poprawiony.

Rozwiązaniem było jawne wymuszenie ponownego wygenerowania linux_trampoline.c:

make -C coreboot/util/cbfstool linux_trampoline.c

Dopiero później przebudowałem właściwy program:

make -C coreboot/util/cbfstool cbfstool

Następnie sprawdziłem daty plików:

stat -c '%y %n' coreboot/util/cbfstool/linux_trampoline.S coreboot/util/cbfstool/linux_trampoline.c coreboot/util/cbfstool/linux_trampoline.o coreboot/util/cbfstool/cbfstool

Otrzymałem prawidłową kolejność: najpierw zmodyfikowany plik asemblera, później nowy linux_trampoline.c, następnie plik obiektowy i ostatecznie nowy cbfstool.

To bardzo ważna informacja na przyszłość. Samo poprawienie linux_trampoline.S i przebudowanie cbfstool może nie wystarczyć, jeżeli wygenerowany wcześniej linux_trampoline.c nie zostanie odświeżony.

Coreboot V6 – ponowne spakowanie Memtest86+ z poprawioną trampoliną

Kiedy miałem już poprawiony cbfstool, przygotowałem nowy obraz firmware V6. Jako bazę wykorzystałem sprawdzoną wersję V5.

Najpierw skopiowałem istniejący ROM:

cp images/t400-grub2-theme-v5.rom images/t400-grub2-theme-v6.rom

Następnie usunąłem stary Memtest86+ z nowej kopii obrazu:

coreboot/util/cbfstool/cbfstool images/t400-grub2-theme-v6.rom remove -n img/memtest

Po tej operacji ponownie dodałem oryginalny obraz Memtest86+ 6.20:

coreboot/util/cbfstool/cbfstool images/t400-grub2-theme-v6.rom add-payload -f coreboot/payloads/external/Memtest86Plus/memtest86plus_v6/memtest -n img/memtest -c lzma

Celowo wykorzystałem narzędzie znajdujące się w coreboot/util/cbfstool/cbfstool, ponieważ to właśnie jego przebudowę z poprawioną trampoliną wcześniej zweryfikowałem.

Nie przebudowywałem ponownie Memtest86+. Wykorzystałem ten sam obraz bzImage, a zmiana dotyczyła wyłącznie procesu konwersji do formatu payloadu CBFS.

Po operacji zauważyłem niewielką różnicę rozmiaru nowego pliku img/memtest. W V5 zajmował on 137 683 bajty, natomiast w V6 137 685 bajtów.

Ta różnica była zgodna z wprowadzoną modyfikacją, ale nie traktuję jej jako uniwersalnego kryterium poprawności. Rozmiary mogą różnić się między wersjami narzędzi i konfiguracjami kompilacji.

Weryfikacja V5 i V6 – zmieniłem tylko img/memtest

Przed flashowaniem chciałem mieć pewność, że w trakcie przygotowywania nowego obrazu nie zmodyfikowałem przypadkowo innych elementów firmware.

Porównałem więc listy plików CBFS oraz zawartość poszczególnych komponentów w obrazach V5 i V6.

Wynik był dokładnie taki, jakiego oczekiwałem:

  • Payload img/memtest został zmieniony.
  • Wszystkie 29 pozostałych plików CBFS pozostało identycznych z V5.
  • GRUB2, motyw graficzny, Coreinfo, NVRAMCUI, Tint, SeaBIOS i bootblock nie zostały zmodyfikowane.
  • Pierwsze 6 MiB pełnego obrazu ROM było identyczne z poprzednią wersją.

Dzięki temu mogłem mieć dużą pewność, że nowa wersja firmware różni się od poprzedniej wyłącznie poprawionym Memtest86+.

Po przeniesieniu obrazu na ThinkPada T400, sprawdzeniu sumy SHA256 i wykonaniu flashowania uruchomiłem Memtest86+. Program działał prawidłowo, a jego interfejs odzyskał standardową niebieską kolorystykę.

W ten sposób potwierdziłem, że źródłem problemu był błędny sposób konwersji parametrów framebufferu w linux_trampoline.S.

Flashowanie Coreboota na ThinkPadzie T400 – region BIOS i kopie zapasowe

Podczas wszystkich aktualizacji stosowałem zasadę ograniczania zapisu wyłącznie do potrzebnego regionu pamięci SPI.

Mój ThinkPad T400 wykorzystuje układ MX25L6405D o pojemności 8 MiB. W tej konkretnej konfiguracji region BIOS obejmuje zakres:

0x600000–0x7FFFFF

Oznacza to, że właściwy obszar BIOS ma rozmiar 2 MiB. Pozostałe regiony pamięci, w tym IFD, ME i GbE, pozostawiałem bez zmian.

Do wyodrębnienia regionu BIOS z pełnego obrazu wykorzystałem:

dd if=images/t400-grub2-theme-v6.rom of=images/t400-grub2-theme-v6-bios-2mb.bin bs=1M skip=6 count=2

Przed zapisem sprawdzałem rozmiar pliku, sumę SHA256 oraz zgodność niezmienianych fragmentów ROM-u.

Na T400 korzystałem z flashrom i pliku layout zawierającego:

00600000:007fffff bios

Przed dostępem do pamięci SPI konieczne było również wyładowanie modułu lpc_ich:

sudo modprobe -r lpc_ich

Do flashowania wykorzystywałem pełny obraz 8 MiB, ograniczając zapis do regionu BIOS. W mojej konfiguracji polecenie wyglądało następująco:

sudo flashrom -p internal -c MX25L6405D -l /tmp/t400-bios.layout -i bios --noverify-all -w ~/Pobrane/t400-grub2-theme-v6.rom

Opcja –noverify-all była potrzebna ze względu na ograniczenia odczytu pozostałych regionów pamięci. Nie oznaczała pominięcia weryfikacji zapisywanego obszaru BIOS.

Wszystkie aktualizacje wykonywałem z podłączonym zasilaczem. Przed każdą z nich zachowywałem kopię poprzedniego firmware, a po zapisie sprawdzałem komunikaty flashrom.

Podane adresy, nazwa układu SPI i polecenie flashrom dotyczą mojego egzemplarza T400. Nie należy przenosić ich bez sprawdzenia na inne komputery.

Finalny Coreboot 26.09 V6 – sumy SHA256 i wyniki testów

Ostateczną wersję mojego firmware oznaczyłem jako T400 Quad Core Edition V6. Prace zakończyłem 11 listopada 2026 roku.

Wersja ta zawiera Coreboot 26.09, GRUB2 2.14 z własnym motywem graficznym, SeaBIOS, Coreinfo, NVRAMCUI, Tint i Memtest86+ 6.20.

W Coreinfo, NVRAMCUI i Tint wyłączyłem niepotrzebną konsolę szeregową libpayload. W Memtest86+ zastosowałem poprawioną trampolinę framebufferu, naprawiając problem z kolorami.

Po wgraniu firmware wszystkie narzędzia działały prawidłowo. Nie zaobserwowałem już komunikatu IO space mapped serial not present, a Memtest86+ wyświetlał poprawne kolory.

Poniżej zapisuję sumy kontrolne SHA256 najważniejszych plików, aby móc w przyszłości jednoznacznie zidentyfikować przygotowane przeze mnie obrazy.

Plik SHA256
Coreboot V5, ROM 8 MiB d7d8131c56d40ee73018ae9b079b15529d3fcd55778089263c25d72120aa95a6
Coreboot V6, ROM 8 MiB 1c7df5dd730e1d159a588d375daf4e4bb86a8d9411c318e8c082c0782ac2f0b8
Coreboot V6, BIOS 2 MiB 758293507d0671060b9d17ce38829fecc2d2beb7a5bd25ae8d046c4360d9027c

Pełny obraz V6 zapisałem jako:

~/coreboot-t400-grub2/images/t400-grub2-theme-v6.rom

Plik zawierający sam region BIOS:

~/coreboot-t400-grub2/images/t400-grub2-theme-v6-bios-2mb.bin

Podane sumy odnoszą się do konkretnych plików z mojego projektu. Przy kompilacji firmware dla innych komputerów lub z użyciem innych wersji narzędzi wyniki SHA256 będą inne.

Jak wykorzystam te poprawki w kolejnych projektach Coreboot?

Głównym powodem przygotowania tej dokumentacji jest możliwość wykorzystania zdobytej wiedzy podczas przyszłych aktualizacji Coreboota na kolejnych komputerach. Nie chcę za każdym razem ponownie analizować problemów, których przyczyny udało mi się już ustalić.

Jeżeli podczas uruchamiania Coreinfo, NVRAMCUI lub Tint zobaczę komunikat IO space mapped serial not present, w pierwszej kolejności sprawdzę konfigurację libpayload i aktywność CONFIG_LP_SERIAL_CONSOLE. Zwrócę również uwagę na to, czy dany program korzysta z Tinycurses, czy PDCurses.

Jeżeli natomiast Memtest86+ będzie wyświetlał nieprawidłowe kolory w trybie graficznym, sprawdzę sposób przygotowania jego payloadu i zawartość linux_trampoline.S. Szczególną uwagę zwrócę na instrukcję rol odpowiedzialną za zamianę kolejności bajtów parametrów framebufferu.

Będę również pamiętał o konieczności ponownego wygenerowania linux_trampoline.c i przebudowania cbfstool. To szczegół, który łatwo przeoczyć, a który ma bezpośredni wpływ na to, czy poprawiony kod rzeczywiście znajdzie się w końcowym payloadzie.

Nie zakładam jednak, że oba błędy wystąpią w każdej wersji Coreboota. Zanim zastosuję opisane rozwiązania, sprawdzę aktualny kod źródłowy i konfigurację danego komputera. Nowsze wydania mogą już zawierać poprawki lub wykorzystywać inny sposób inicjalizacji grafiki i uruchamiania payloadów.

Projekt T400 pokazał mi, jak duże znaczenie ma szczegółowa diagnostyka. Ostatecznie pierwszy problem rozwiązałem przez zmianę kilku ustawień libpayload, a drugi przez poprawienie jednej instrukcji asemblera.

Najważniejsze jest dla mnie to, że obie poprawki zostały zweryfikowane na rzeczywistym sprzęcie, a nie tylko na poziomie poprawnej kompilacji.

Mój ThinkPad T400 Quad Core Edition z Coreboot V6 jest obecnie dopracowanym, stabilnie działającym komputerem, z własnym interfejsem startowym i kompletem narzędzi diagnostycznych. Dokumentacja pozostaje natomiast technicznym punktem odniesienia, do którego będę mógł wrócić przy kolejnych projektach związanych z Corebootem.


mgr Bartłomiej_Speth

Absolwent wydziału Fizyki Uniwersytetu im. Adama Mickiewicza w Poznaniu na kierunku Fizyka z informatyką. Miłośnik komputerów, sprzętu komputerowego oraz otwartego oprogramowania. Specjalizuje się w budowie, naprawach, modyfikacjach laptopów jak i jednostek stacjonarnych. Zapalony PC'towiec od momentu, w którym otrzymał swój pierwszy komputer z procesorem 80286.

0 komentarzy

Dodaj komentarz

Symbol zastępczy awatara

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *