uEFI: Graphics Output Protocol (GOP)

Im klassischen PC BIOS aus den alten 16-Bit Zeiten hatten wir den Interrupt 10h (INT 0x10) um den Grafikmodus zu ändern.

Mit uEFI wurde diese antiquierte 16-Bit Technik modernisiert und somit steht mit dem Graphics Output Protocol (GOP) eine C-API der Firmware bereit, um Pixelgrafiken auf den Monitor zu bekommen.


In den glorreichen Zeiten, in denen “die coolen Jungs” ihr eigenes OS bauen wollten, starteten viele mit dem 512 Bytes großen Bootsektor-Code, wechselten per int 10h in den Grafikmodus und zeichneten ein paar verwegene
“You are hacked” Zeichen auf den Schirm.

Das ganze auf eine Diskette gespielt und ins Laufwerk gelegt, ließ Papa am Abend erblassen, wenn er seine Excel-Zeitlisten in Windows 95 befüllen wollte.

Nun sterben langsam auch die letzten Firmware-Varianten aus, die noch ein BIOS CSM (Compatibility Support Module) enthalten.
Die Zukunft heißt (seit 10 bis 15 Jahren): uEFI.

Das GOP Protokoll

Über die GOP GUID (9042a9de-23dc-4a38-96fb7aded080516a) erlangt man von BootServices->LocateProtocol einen Pointer zum EFI_GRAPHICS_OUTPUT_PROTOCOL Interface.

Dieses stellt die Methoden QueryMode(), SetMode() und Blt() bereit, sowie einen Pointer namens Mode zu den Daten des aktuellen Modus.

Mode->MaxMode gibt die Anzahl der verfügbaren Grafik-Modi zurück und nun kann man per Schleife von 0 bis MaxMode zählen und diesen Parameter als ID an QueryMode() übergeben um Infos zum dahinter liegenden Grafikmodus zu erhalten.
Das wären:

  • Pixel-Höhe und -Breite des Grafikmodus
  • Art des Pixelformats
    • RGBX: 32 bit Wert mit dem Inhalt rot, grün, blau + unbenutztes Füllbyte
    • BGRX: 32 bit Wert mit dem Inahtl blau, grün, rot + unbenutztes Füllbyte
    • BitMask: In einer zusätzlichen Struktur wird beschrieben, welche Bits in einem 32-bit Pixel den Farbkanälen rot, grün und blau zugeordnet sind.

Üblicherweise startet die Auflistung beim alten VGA-Standard 640 x 480 und wird dann zunehmend größer.

Mit der Funktion SetMode() kann dann in den Grafikmodus wechseln, wenn man die gewünschte Index-ID einsetzt.

Am interessantesten ist dann die Funktion Blt(), die Pixelpufferinhalte in die Video-Hardware übertragen kann. Das funktioniert sogar in beide Richtungen, man kann also Pixel aus dem eigenen Buffer in die Anzeige transferieren oder die angezeigten Pixel in den eigenen Puffer kopieren lassen.

Man kann also ein Breite * Höhe großes Feld von uint32_t Werten anlegen und dann die Pixel je nach Modus setzen und das gesamte Frame per Blt() anzeigen lassen.

Fazit

Das tolle an UEFI ist, dass die C-API bereits mitgeliefert wird und somit kann man mit wenigen Zeilen einen Bootloader mit grafischen Menü zaubern.
Früher hätte man im BIOS dann per Assembler auf die Hardware-Addressen zugreifen müssen und eben genau dafür schrieben sich viele Entwickler ihre eigene Blt() Funktion.
Schön zu sehen, dass das nun obsolet und die neue Methode standardisiert ist.

Nun existiert im GATE Framework auch eine Framebuffer-Implementierung, die direkt unter EFI ausführbar ist und Grafiken auf den Monitor zeichnen kann.

Und erneut bin ich erstaunt, wie einfach es ist, den PC “ohne Betriebssystem” zu betreiben.