VESA, VBE und x86emu erklärt

Also, was ist VESA und was sind VBE? Oder besser gesagt, wieso funktioniert xf86-video-vesa auf jeder Grafikkarte und wie arbeitet die VESA-Konsole und wozu brauchen wir den x86emu?

Eigentlich ist es ganz einfach. Irgendwann in grauer Vorzeit waren Grafikkarten vergleichsweise primitive Hardware, die keinerlei weiteren Treiber oder so benötigte. Wie die meiste Hardware unter DOS. Dann bekamen sie eines Tages die Möglichkeit weitere Farbtiefen und Auflösungen darzustellen, als im damals von IBM definierten VGA-Standard vorgesehen war. Nun stand man vor der Aufgabe einen Weg zu finden, mit dem man diese erweiterten Auflösungen, Farbtiefen und noch einige andere Sachen schalten kann. Einen Treiber gab es eben nicht nicht, mal ganz davon abgesehen, dass DOS eh keine definierten Schnittstellen für sowas hätte. Also liefen Grafikkarten-, Monitor- und Softwarehersteller zu ihrem Branchenverband „Video Electronics Standards Association“ - kurz VESA - und sagten ihm, dass er doch bitte eine standardisierte Lösung finden solle. Die VESA kennt praktisch jeder, denn sie machen noch viele andere Standardisierungen. Z.B. die Seitenverhältnisse des Bildes, Auflösungen, Bildwiederholraten, die berüchtigten VESA-Bildschirmhalterungen, den Displayport, etc. Die VESA dachte sich dann die „VESA BIOS Extensions“ (VBE) aus. Wie der Name sagt sind die Funktionen auf dem Grafikkarten-BIOS, die sich in das System-BIOS einklinken und von da aus der DOS-Software zur Verfügung stehen.

Kurz Exkurs für die jüngeren Semester zum Thema DOS: DOS war ein sehr primitives System, technisch gesehen nicht mal ein Betriebssystem, stattdessen ein Wrapper. Es kannte keine Hardware und keine echte API für Programme. Simpel gesagt programmierte unter DOS jedes Programm den Rechner komplett selbst, deshalb gab so Dinge wie virtuellen Speicher oder Multitasking nicht. Wenn ein Programm abschmierte, stürzte der Rechner ab. Um das Programmieren einfacher zu machen, hatte IBM für seinen IBM-PC das BIOS (Basic Input Output System, eigentlich BIOS == Griechisch für „Leben“) erfunden. Es stellt eine gewisse Funktionalität über BIOS-IRQ zur Verfügung. Ein IRQ ist ein „Interrupt Request“, eine Unterbrechungsaufforderung oder kurz eben Interrupt. Kommt ein solcher rein, unterbricht der Computer simpel gesagt sofort das, was er gerade macht und verarbeitet diese Anfrage. Das ist in echt viel komplexer und über IRQ sind Bücher geschrieben wurden, hier reicht aber die einfache Darstellung. Der bekannteste BIOS-Interrupt war 10h, er steuerte die Textkonsole. Um z.B. ein „!“ auszugeben:

mov ah, 0x0a
mov al, '!'
int 0x10

Das ! ins Register schreiben, 10h aufrufen. Die CPU / das BIOS leitet das ! an die Grafikkarte weiter, sie schreibt es an der Position des Cursors auf den Bildschirm. Problem: Dies kann nur Text darstellen. Grafiken gehen damit nicht. VBE macht nun nichts anderes, als eine Reihe weiterer IRQ zu definieren. Aber anstatt ein Zeichen auszugeben, schaltet dann z.B. die Auflösung um.

Nun gibt es Framebuffer. Dies sind Speicherbereiche, in die Bitmap-Daten gelegt werden. Die Grafikkarte zieht diese automatisch ein und gibt sie aus. Die Größe des Framebuffers ist nun davon abhängig, wie groß die Ausgabe ist. Ein Bild von 1280×1024 bei 32 Bit hat also 1310720 Pixel. Jedes belegt 32 Bit. Das Bild und damit der Framebuffer ist also 41943040 Bit oder 5120 Kilobyte groß. Ältere Semester erinnern sich daran, dass Grafikkarten gar keine 1280×1024 bei 32Bit darstellen konnten. Sie hätten 5120 Kilobyte RAM haben müssen, der war teuer, daher hatten die meisten Karten diese Mengen nicht, konnten keinen so großen Framebuffer zur Verfügung stellen und unterstützen die Auflösung nicht. Bei meiner ersten S3 Trio Virge war z.B. bei 1024×786 bei 16Bit Schluss.

Fassen wir zusammen: Es gibt zwei Arten Daten auf den Monitor zu bekommen. Die Textkonsole - in DOS über INT 10h, heute meist anders implementiert. Sie kann maximal 256 Zeichen darstellen, also Zeichensätze wie ANSI, ASCII oder ISO. Ihre Auflösung ist sehr begrenzt. Dies ist die Textkonsole, die DOS hat und die alle BSDs und Linux in Standardeinstellung nutzen. Sie ist für LCD-Monitore durch die geringe Auflösung ungeeignet und sie kann kein Unicode, da Unicode mehr als 256 Zeichen braucht. Daneben gibt es den Framebuffer. Eine Anwendung setzt ein Bild mittels der CPU zu einer Bitmap zusammen, schreibt dieses in den Framebuffer, die Grafikkarte stellt es da. Früher gern für Spiele unter DOS genutzt. Die VESA-Konsole macht nichts anderes. Sie schaltet mittels VBE-Interrupt die Grafikkarte in eine hohe Auflösung, setzt das Bild aus Text und Hintergrund auf der CPU zusammen und schreibt es in den Framebuffer. Vorteile sind hohe Auflösungen, es ist alles darstellbar (Grafiken, unbegrenzt viele unterschiedliche Zeichen), Nachteil ist die hohe CPU-Last und das es eher langsam ist.

Mit VBE kann man tolle Dinge machen. Ein gutes Beispiel ist xf86-video-vesa, also X.orgs VESA-Grafiktreiber. Er schaltet mittels VBE die Auflösung, arbeitet dann einzig auf dem Framebuffer. Da jede Grafikkarte VBE unterstützt, arbeitet er auch mit jeder zusammen. Zwar sind möglichen Auflösungen und die Bildwiederholraten begrenzt, auch läuft alles über die CPU und es ist langsam, aber immer noch besser als nichts.

Nun gibt es aber ein Problem: Die nötigen BIOS-Interrupts sind nur in den drei CPU-Modi „Real Mode“, „Virtual Mode“ und „Protected Mode“ verfügbar. Diese nutzt die i386-CPU und alle kompatiblen, Seitens der Software also FreeBSD/i386, OpenBSD/i386, Linux/i386 und so weiter. Unter AMD64 ist die CPU aber im „Long Mode“, dort sind die BIOS-Interrupts nicht mehr verfügbar. Daher ginge die VESA-Konsole unter FreeBSD/amd64, OpenBSD/amd64 und Linux/amd64 nicht, man kann die VBE nicht nutzen. Auch xf86-video-vesa ginge nicht mehr. Aus diesem Dilemma gibt es zwei Auswege.

Linux nutzt den sauberen Weg, wir wollen ja nicht immer nur über Linux lästern. Beim Systemstart ist die CPU im Real Mode. Linux schaltet erst per VBE die Auflösung hoch, wechselt dann in den Long Mode. Die gesetzt Auflösung bleibt dabei vorhanden. Der Vorteil ist die einfache und sichere Implementierung, das Problem ist halt, dass ein Ändern der Konsolenauflösung unter Linux einen Reboot erfordert.

Der andere Weg ist auf XFree86s Mist gewachsen, genauer für den xf86-video-vesa. Er heißt x86emu. Dies ist ein Programm, was im Long Mode einen Teil des x86-BIOS des IBM PC emuliert. Die Grafikkarte dockt ihre VBE daran wie an ein echtes BIOS an. Über den x86emu können nun die VBE genutzt werden. Das klappt unter AMD64, es klappt theoretisch sogar auf ganz anderen Plattformen wie SPARC oder PowerPC. Scheitert praktisch aber daran, dass dort die Grafikkarten kein VBE können. x86emu wurde dann irgendwann aus XFree86 auf den NetBSD-Kernel portiert. Damit konnte NetBSD auch auf NetBSD/amd64 eine VESA-Konsole zur Verfügung stellen. Dann wurde er von dort auf OpenBSD weiterportiert und nun zuletzt auch auf FreeBSD. FreeBSD 9-CURRENT und 8-STABLE (früher mit Patch http://www.bsdforen.de/showthread.php?p=208806, inzwischen auch ohne) kann daher auch unter AMD64 hohe Auflösungen in der Konsole.

Theoretisch gibt es eine dritte Möglichkeit eine Konsole zu implementieren. Dies ist die Direct Rendering Infrastructure oder kurz DRI. DRI wird im Moment nur von Xorg verwendet, ist aber unabhängig davon. Es funktioniert so, dass ein Treiber oder Grafikbiliothek oben ihre Eingabe in DRI reinwirft. Diese wird in native Befehle der Grafikkarte umgesetzt - das machen die DRI-Backends - und dann durch den Direct Rendering Manager aka DRM im Kernel auf die Grafikkarte geschrieben. Der Vorteil ist, dass die komplette Bildberechnung von der GPU übernommen wird und die CPU entlastet. Es ist weitaus schneller als eine VESA-Konsole. Problematisch ist, dass längst nicht alle Grafikkarten von DRI unterstützt werden.

Quelle: Yamagi / www.bsdforen.de / 18.02.2010