Przedstawiamy firmware UEFI, dzięki któremu możliwe jest coraz śmielsze wkraczanie architektury ARM64 do świata urządzeń serwerowych, czyli królestwa władanego przez Intel. Standardy, ich założenia i realizacja zostałą przybliżona na przykładzie dodawania wsparcia dla n
2. Plan prezentacji
● UEFI - wprowadzenie
● EDK2 Build System - jak zbudować swój firmware?
● UEFI Driver model
● Aplikacje w UEFI
● Interakcje UEFI/OS
● Co z tego wyszło?
3. ARM64 jako serwer lub PC?
● ARM wychodzi poza embedded
● Potrzebna unifikacja rozwiązań - nowe standardy wokół ARMv8
○ Server Base System Architecture (SBSA)
○ Server Base Boot Requirements (SBBR)
● Serwery - Qualcom Falkor i Cavium Thunder X2
● Próby ARM PC - Socionext/Gigabyte i Marvell
4. SBBR
● UEFI 2.5 lub wyżej w implementacji EDK2
● UEFI uruchomione na EL1/EL2
● Odpowiedni format plików binarnych - PE/COFF
● Boot services
● Runtime services
● ACPI 6.0
● SMBIOS 3.0
5. UEFI (Unified Extensible Firmware Interface)
● Specyfikacja standardu interfejsu między poszczególnymi etapami
uruchamiania systemu komputerowego;
● Unified od 2006 roku;
● EDK2 - najbardziej popularna implementacja specyfikacji UEFI. Opublikowana
na licencji BSD, mocno wykorzystywana przez współczesnych producentów
firmware’u (np. AMI). Dostępna pod adresem https://github.com/tianocore/edk2.
● Od kilku lat aktywny udział ARM
8. Plan prezentacji
● UEFI - wprowadzenie
● EDK2 Build System - jak zbudować swój firmware?
● UEFI Driver model
● Aplikacje w UEFI
● Interakcje UEFI/OS
● Co z tego wyszło?
9. Kod platformowy w EDK2 - zależności
● edk2 - wyłącznie kod generyczny (prawie :) )
● edk2-platforms - właściwy kod platformowy
● edk2-non-osi - kod platformowy niezgodny z licencjami BSD
● Zależności definiowane przy użyciu zmiennych $PACKAGES_PATH i
$WORKSPACE
10.
11. Etapy budowy EDK2
1. AutoGen - parsowanie metadanych w wyniku czego powstają pliki z kodem C
oraz pliki Makefile
2. Make - kompilacja kodu źródłowego, stworzenie wynikowych plików
PE32/PE32+/COFF
3. ImageGen - przetwarzanie plików wynikowych z poprzedniego etapu w celu
stworzenia obrazów UEFI gotowych do wgrania do pamięci flash
12. Najważniejsze typy plików EDK2
● .DSC - opis platformy, jej bibliotek i komponentów
● .DEC - deklaracje interfejsów platformy
● .FDF - opis budowy końcowego pliku binarnego
● .INF - definicja modułu
13. Package Declaration File (.DEC)
● Deklaruje informacje na temat zawartości danej paczki (grupy plików)
● Max jeden plik .DEC per Package
● Od strony praktycznej - pliki .DEC wykorzystywane są przez build system
EDK2 do tworzenia plików AutoGen.c oraz AutoGen.h
● Zawiera sekcję [Includes], której wpisy wykorzystywane są do wyszukiwania
plików nagłówkowych przez kompilatory
● Przypisanie wartości GUID do obiektów w C
14. Platform Description File (.DSC)
● Plik opisuje jakie komponenty, moduły i biblioteki zostaną wykorzystane podczas budowy platformy
● Definiuje biblioteki wykorzystane podczas linkowania modułów
● Innymi słowy - zbiór plików INF, które opisują poszczególne moduły
● Inicjalizacja PCD
● Opcjonalnie może zmieniać konfigurację budowy poszczególnych modułów
15. Flash Description File (.FDF)
● Opisuje, co zawiera binarny plik wyjściowy platformy
● Opisuje layout wyjściowego pliku binarnego platformy
● Ścieżka do tego pliku podawana jest w .DSC
16. Module Information File (.INF)
● Definicja typu
● Lista plików źródłowych
● Lista wykorzystywanych PCD
● Lista wykorzystywanych protokołów
17. Platform Configuration Database (PCD)
● Celem jest zastąpienie #define preprocesora
● PCD definiują parametry modułów
● Redukują potrzebę zmian w kodzie - są definiowane w plikach
konfigurujących platformę
● Maksymalizacja wykorzystania modułów pomiędzy różnymi platformami
● Udostępnione API, które pozwala dostawać się do wartości PCD w trakcie
wykonywania programu
● PCD wykorzystywane są do przechowywania informacji na temat platformy
● Zdefiniowane w .DEC, inicjalizowane wartościami w .DSC, wylistowane w
pliku .INF modułu. Podczas dodawania nowych PCD trzeba pamiętać o tym,
że wymaga to edycji kilku plików konfigurujących
18. Plan prezentacji
● UEFI - wprowadzenie
● EDK2 Build System - jak zbudować swój firmware?
● UEFI Driver model
● Aplikacje w UEFI
● Interakcje UEFI/OS
● Co z tego wyszło?
19. UEFI driver model - założenia
Środowisko sterowników w UEFI charakteryzują następujące podstawowe cechy:
● Brak SMP
● Mało współbieżności
● Sterowniki komunikują się z generycznym kodem przez:
○ globalne struktury gBS, gDS, gRS
○ interfejsy (protokoły)
○ eventy
● Identyfikacja “trwałych” elementów przez GUID
● Brak userspace
20. UEFI driver model – kolejność inicjalizacji
Faza wykonywania zdefiniowana
przez MODULE_TYPE w pliku INF.
Możliwe wartości to m.in.:
● PEIM
● DXE_DRIVER
● UEFI_DRIVER
● UEFI_APPLICATION
Kolejność przyłączania sterowników
DXE jest zdefiniowana przez
wyrażenia DEPEX (w pliku INF
danego modułu).
21. UEFI driver model – producent-konsument
Z punktu widzenia piszącego sterownik:
● chcemy skorzystać z jakichś już dostępnych
funkcjonalności.
● chcemy udostępnić nowe funkcjonalności
UEFI standaryzuje interakcje między sterownikami
poprzez protokoły (interfejsy):
● koncepcyjnie – protokół może być produkowany
(sterownik udostępnia funkcjonalność) lub
konsumowany (korzysta z czyjejś funkcjonalności)
● technicznie – protokół to struktura w C, która
zawiera wskaźniki na funkcje + parę skojarzonych
definicji
22. UEFI driver model – handle
Handle, czyli “uchwyt” na jakiś obiekt. Koncepcyjnie:
● handle reprezentuje sterownik, urządzenie, plik
binarny – jakiś obiekt w modelu
● handle można rozumieć jako kolekcję protokołów
skojarzonych ze sobą
● handle są zgromadzone w płaskiej strukturze;
hierarchia pomiędzy urządzeniami reprezentowanymi
przez handle może być ustalona poprzez protokół
DevicePath (ale nie musi)
Każdy sterownik ma skojarzony ze sobą Driver Image
Handle, na którym instaluje swoje protokoły.
Na handle’u może być wiele protokołów – aby powiązać
sterownik z urządzeniem, instalujemy na jego uchwycie
dodatkowy protokół DevicePath, który ustala
hierarchię urządzeń.
24. UEFI driver model – handle technicznie
Handle “pod maską” – wskaźnik na strukturę
IHANDLE.
Przy tworzeniu nowego uchwytu:
● Inicjalizacja listy Protocols
● Dodanie adresu AllHandles do globalnej listy
● Wypełnienie sygnatury, klucza, instalacja
protokołów
Wszystkie te operacje wykonują się w generycznym
kodzie UEFI. Sterownik po prostu woła
odpowiednią funkcję (np.
InstallMultipleProtocolInterfaces).
25. UEFI driver model – device driver
Każdy sterownik ma swój entry point – funkcję inicjalizującą
jego zasoby, która wywołuje się dokładnie raz. Typowy
schemat postępowania:
1. Sterownik w entry point instaluje protokół Driver
Binding
2. W trakcie bootowania UEFI dispatcher wywołuje
funkcję Supported dla każdego controller handle.
Sterownik zwraca, czy ten handle mu odpowiada (np.
sprawdza protokoły)
3. Jeśli handle jest dobry, wywoływana jest funkcja Start
z dobrym handlem jako parametrem. W funkcji Start
driver otwiera niezbędne mu protokoły.
4. Podczas etapu ExitBootServices wywołuje się funkcja
Stop
26. UEFI driver model – bus driver
Sterownik magistrali zachowuje się prawie tak samo jak
sterownik urządzenia, lecz dodatkowo w funkcji Start()
tworzy nowe uchwyty dla dzieci i instaluje na nich
protokoły IO.
Przykład: sterownik magistrali SPI na każdym uchwycie
instaluje protokół SPI IO oraz Device Path, po czym
wywołuje ConnectController na danym handle.
Przyłączone dzieci korzystają z udostępnionych funkcji.
Wyjątek: szyna CPU<->pamięć nie jest w UEFI
obsługiwana w ten sposób. Zamiast tego, wszystkie
sterowniki mają bezpośredni dostęp do pamięci poprzez
MmioRead, MmioWrite bez potrzeby używania protokołów.
27. UEFI driver model – jak to napisać?
Konsumowanie protokołów:
● OpenProtocol
● LocateProtocol
● LocateHandle, LocateHandleBuffer
● LocateDevicePath
● CloseProtocol
Produkowanie:
● InstallMultipleProtocolInterfaces
● UninstallMultipleProtocolInterfaces
28. Plan prezentacji
● UEFI - wprowadzenie
● EDK2 Build System - jak zbudować swój firmware?
● UEFI Driver model
● Aplikacje w UEFI
● Interakcje UEFI/OS
● Co z tego wyszło?
30. Aplikacje w UEFI – wstęp
Aplikacje kompilowane są do formatu .efi. W tej formie mogą
być:
● dostarczone wraz z obrazem firmware (modyfikacja
pliku FDF)
● załadowane na jakiś zewnętrzny nośnik, np. HDD,
pendrive
● pobrane przez TFTP
Pod kątem pisania kodu jest niewiele różnic względem
driverów, w tym:
● konstruktory/destruktory zamiast entry point lub Driver
Binding
Aplikacja ma dostęp do wszystkiego (może instalować,
otwierać protokoły, wołać inne funkcje z gBS) – w UEFI nie ma
pojęcia userspace.
31. Aplikacje w UEFI – przykład: EepromCmd
Przykład – bardzo prosta aplikacja do obsługi
platformowego protokołu EEPROM, skojarzona ze
sterownikiem EepromDxe.
Użytkownik wywołuje komendę “eeprom” z shella
UEFI, podając komendę (read/write) oraz parametry
do niej (skąd / dokąd, id urządzenia, bus I2C).
Aplikacja:
● Rejestruje komendę do shella w konstruktorze
● Parsuje argumenty przy wywołaniu i na ich
podstawie znajduje protokół odpowiedni dla
urządzenia
● Korzystając z protokołu, wywołuje żądanie
transferu danych
EepromCmd
Eeprom DXE
I2C DXE
UEFI Shell
MarvellEepromProtocol
EfiI2cIoProtocol
EfiDriverBindingProtocol
32. Aplikacje w UEFI – OS loader
OS loader jest odpowiedzialny za przekazanie kontroli z firmware do systemu
operacyjnego. Po kolei:
1. Ustala swoją lokalizację, ładuje dodatkowe pliki.
2. Ustala gdzie jest OS i zyskuje dostęp do jego obrazu. Może wymagać
dostępu do systemów plików niewspieranych przez UEFI.
3. Przekazuje mapę pamięci fizycznej i udostępnia ją do OS przez interfejsy
UEFI. Opcjonalnie udostępnia też inne dane.
4. Woła ExitBootServices() – od tego punktu gBS jest niedostępne.
5. Wykonuje skok do kernela.
33. Bootowanie OS – EFISTUB w detalach
Sekwencja bootowania przy pomocy EFISTUB:
1. Od UEFI otrzymuje wskaźniki na EFI_SYSTEM_TABLE
2. Znajduje skojarzony ze sobą Loaded Image Protocol,
pobiera swój cmdline. Rozpoznaje adres fizyczny
RAMu z System Table.
3. Relokacja
4. Pobiera FDT z FdtConfigurationTable; jeśli nie UEFI nie
udostępniło FDT, generowany jest pusty plik.
5. Mapa pamięci (zarezerwowanych regionów) jest
przekształcana (na podstawie danych z FDT) i na
powrót zapisywana.
6. Wywoływane jest ExitBootServices, po czym następuje
aktualizacja mapy wirtualnej pamięci w UEFI poprzez
EfiSetVirtualAddressMap.
34. Plan prezentacji
● UEFI - wprowadzenie
● EDK2 Build System - jak zbudować swój firmware?
● UEFI Driver model
● Aplikacje w UEFI
● Interakcje UEFI/OS
● Co z tego wyszło?
36. EFI Configuration Tables
Polimorficzna struktura – w zależności od GUID wskaźnik
jest rzutowany na ustalony typ, na przykład:
● DTB
● Zmienne środowiskowe
● Tablice SMBIOS
● Root System Descriptor (ACPI)
37. EFI Runtime Services
Struktura wskaźników na funkcje implementowane
przez UEFI, dostępne w czasie działania systemu
operacyjnego.
● Aktualizacja secure firmware przez OS
● Ustawianie zmiennych środowiskowych
● Zyskanie dostępu do informacji niezależnych
od OS
Sterowniki w UEFI, które implementują Runtime
Services muszą korzystać z odpowiedniej pamięci,
która nie zniknie po EfiBootServices.
38. Opis sprzętu - podejście embedded
(Flattened) Device Tree to drzewiasta struktura, która ma za zadanie przekazać informacje o platformie
do OS. Zawiera wyłącznie statyczny opis platformy, w tym informacje o:
● zasobach
● zależnościach między urządzeniami
Pliki .dts (Device Tree Source) są kompilowane do postaci .dtb (Device Tree Blob). Mogą być dołączone
do obrazu firmware. Opcjonalnie, zanim DTB trafi do systemu operacyjnego, jest modyfikowane przez
FW.
39. Opis sprzętu - podejście serwerowe/PC
ACPI (Advanced Configuration and Power
Interface) to technologia znana głównie z
komputerów klasy PC (pierwotnie wywodzi się z
APM, stworzonego przez Intel/Microsoft). Coraz
częściej jest implementowana na platformach ARM
(zwłaszcza AARCH64), głównie ze względu na:
● Dojrzałą specyfikację (rozwijana od 1996)
● Szereg zalet nad FDT, w tym możliwość
definiowania metod w kodzie ASL (który jest
następnie interpretowany przez OS np. jako
handlery przerwań, )
● Chęć ujednolicenia rozwiązań stosowanych w
centrach danych (gdzie stopniowo są także
wprowadzane platformy ARM)
Rolą firmware jest przygotowanie i opublikowanie
tablic ACPI w pamięci, za ich interpretację
odpowiedzialny jest OS.
40. Plan prezentacji
● UEFI - wprowadzenie
● EDK2 Build System - jak zbudować swój firmware?
● UEFI Driver model
● Aplikacje w UEFI
● Interakcje UEFI/OS
● Co z tego wyszło?
42. Wsparcie platformowe dla rodziny Armada 7k/8k
● Od 0 do pełnej zgodności z SBBR
● Wyzwania platformowe (sieć, SD/MMC i wiele innych)
● Własne generyczne rozwiązania wokół stosów I2C i SPI
● Aplikacje shellowe
● Kod produkcyjny i prawie w całości już w edk2-platforms
● Duża łatwość dodawania nowych platform
● Działają najnowsze distro (Centos, RHEL, Fedora, SLES)