2 Punkte von GN⁺ 2025-10-26 | 1 Kommentare | Auf WhatsApp teilen
  • Eine technische Erklärung, die den Ablauf vom Drücken des Einschaltknopfs bis zur Ausführung des Linux-Kernels Schritt für Schritt beschreibt
  • Behandelt konkret, wie die CPU im Real Mode startet und in den Protected Mode sowie den Long Mode wechselt
  • Beschreibt detailliert die Rolle und Funktionsweise der einzelnen Schritte, darunter BIOS/UEFI-Firmware, Bootloader (GRUB) sowie Kernel-Dekomprimierung und Adress-Relokation
  • Erläutert die zentralen Konzepte für die Kernel-Initialisierung wie Memory Mapping, Interrupts, Seitentabellen und kASLR anhand knapper Beispiele
  • Vermittelt durch das Verständnis der internen Mechanismen des Linux-Bootvorgangs Einblicke in Systemarchitektur, Sicherheit und Performance-Optimierung

Teil 1 — Vom Einschaltknopf bis zur ersten Ausführung des Kernels

  • Wenn der Einschaltknopf gedrückt wird, wird die CPU in den Real Mode zurückgesetzt und führt die ersten Instruktionen aus

    • Der Real Mode ist ein einfaches Adressschema aus der 8086-Ära, bei dem die physische Adresse aus Segment und Offset berechnet wird
    • Beispiel: physical_address = (segment << 4) + offset
    • Nach dem Reset springt die CPU zur Adresse 0xFFFFFFF0 (Reset-Vektor) und übergibt die Kontrolle an die Firmware
  • Register sind ultraschnelle Speicherplätze innerhalb der CPU, darunter CS (Code Segment), IP (Instruction Pointer) usw.

    • CS gibt die Position des aktuellen Codes an, IP zeigt auf die nächste auszuführende Instruktion

BIOS und UEFI

  • BIOS ist die ältere Firmware, die nach dem POST (Power-On Self Test) die Boot-Reihenfolge prüft und nach einem bootfähigen Datenträger sucht
    • Ein bootfähiger Datenträger ist dadurch markiert, dass die ersten 512 Byte des Sektors mit 0x55AA enden
    • Das BIOS kopiert diesen Sektor an die Adresse 0x7C00 und springt dorthin zur Ausführung
  • UEFI ist die moderne Alternative, die Dateisysteme direkt versteht und größere Boot-Programme laden kann
    • Anders als beim BIOS gibt es keine Beschränkung auf den „ersten Sektor“, und dem Betriebssystem werden umfangreichere Systeminformationen übergeben

Bootloader

  • Der Bootloader ist das Programm, das den Kernel in den Speicher lädt und für die Ausführung vorbereitet
    • Typischerweise wird GRUB verwendet, das Konfigurationsdateien liest und den Kernel sowie die initiale RAM-Disk (initrd) in den Speicher lädt
    • Die Kernel-Datei besteht aus einem kleinen Setup-Programm für den Real Mode und dem komprimierten Kernel-Hauptteil
    • GRUB schreibt Informationen wie Kernel-Position, Kommandozeile und initrd-Position in die Struktur setup header und springt dann in den Kernel-Setup-Code

Setup-Programm (Setup Code)

  • Es sorgt vor der Kernel-Ausführung für einen vorhersagbaren Arbeitsbereich
    • Segmentregister (CS, DS, SS) werden ausgerichtet und das Direction Flag wird gelöscht, damit Speicherkopien konsistent funktionieren
    • Es wird ein Stack angelegt, um temporäre Daten bei Funktionsaufrufen zu speichern
    • Der BSS-Bereich (der Bereich globaler Variablen, die mit dem Anfangswert 0 starten müssen) wird auf 0 initialisiert
  • Wenn die Option earlyprintk gesetzt ist, kann ein serieller Port konfiguriert werden, um frühe Debug-Meldungen auszugeben
  • Von der Firmware wird eine RAM-Map (e820) angefordert, um nutzbare und reservierte Speicherbereiche zu erfassen
  • Nach Abschluss aller Vorbereitungen wird die erste C-Funktion main aufgerufen, danach beginnt die Phase des Moduswechsels

Interrupts

  • Interrupts sind ein Mechanismus, bei dem die CPU ihre aktuelle Arbeit kurz unterbricht, um dringende Ereignisse zu verarbeiten
    • Typische Beispiele sind Hardware-Ereignisse wie Tastatureingaben oder Timer
    • Maskierbare Interrupts können vorübergehend blockiert werden, NMI (Non-Maskable Interrupt) wird immer verarbeitet
    • Während des Moduswechsels werden sie vorübergehend blockiert, um unerwartete Interrupts zu vermeiden

Teil 2 — Vom Real Mode zu 32 Bit und dann zu 64 Bit

  • Modernes Linux läuft im Long Mode der x86_64-Architektur
    • Dafür ist ein schrittweiser Übergang nötig: Real Mode → Protected Mode → Long Mode

Protected Mode

  • Dies ist ein 32-Bit-Modus, der eingeführt wurde, um die Grenzen der 1980er Jahre zu überwinden, und er besitzt zwei zentrale Strukturen
    • GDT (Global Descriptor Table): definiert Startadresse, Größe und Rechte von Segmenten
      • Linux verwendet das Flat Model, das den gesamten 32-Bit-Adressraum zu einem zusammenhängenden Bereich vereinfacht
    • IDT (Interrupt Descriptor Table): speichert die Adressen der Handler, die bei Interrupts aufgerufen werden
      • Während des Bootvorgangs wird nur eine minimale IDT geladen, die vollständige IDT wird nach der Kernel-Initialisierung eingerichtet

Ablauf des Moduswechsels

  • Der Setup-Code führt zunächst das Deaktivieren von Interrupts, das Stoppen des PIC-Chips, das Aktivieren der A20-Leitung und die Initialisierung des mathematischen Koprozessors aus
    • Die A20-Leitung ist ein historischer Mechanismus zur Behebung des 1-MB-Adress-Wrapping-Problems
  • Danach werden eine minimale GDT und IDT geladen, anschließend wird das PE-Bit im Register CR0 gesetzt und ein Far Jump ausgeführt
    • Damit erfolgt der Eintritt in den Protected Mode, und Segment- sowie Stack-Pointer werden an das neue Adressschema angepasst

Kontrollregister

  • CR0: aktiviert den Protected Mode
  • CR3: speichert die oberste Adresse der Seitentabellen
  • CR4: aktiviert Erweiterungen wie PAE

Vorbereitung auf den Long Mode

  • Für den Wechsel in den 64-Bit-Modus sind zwei Bedingungen erforderlich
    • Paging muss aktiviert sein: Es übernimmt die Zuordnung zwischen virtuellen und physischen Adressen
    • Das LME-Bit (Long Mode Enable) im EFER-Register muss gesetzt werden
  • Seitentabellen mappen Seiten in 4-KB-Einheiten; während des frühen Bootvorgangs wird dies zunächst einfach über eine Identity Map in 2-MB-Einheiten aufgebaut

Aktivierung von Paging

  • Die Funktion PAE wird in CR4 aktiviert, und es wird eine minimale Seitentabelle erstellt, die den niedrigen Adressbereich in 2-MB-Einheiten abdeckt
  • Die Adresse der obersten Tabelle wird in CR3 geschrieben, danach wird Paging aktiviert
  • Anschließend wird das LME-Bit in EFER gesetzt und in 64-Bit-Code gesprungen, womit der Eintritt in den Long Mode erfolgt
  • Mit auf 64 Bit erweiterten Adressen und Registern ist die Ausführung des Kernels vorbereitet

Teil 3 — Kernel-Dekomprimierung, Adressanpassung und Selbstverschiebung

  • Die CPU befindet sich nun im 64-Bit-Modus, und im Speicher liegt ein komprimiertes Kernel-Image
    • Ein kleiner 64-Bit-Stub übernimmt das Entpacken des Kernels und die Adressanpassung

Frühes Aufräumen und Einrichten von Sicherheitsmechanismen

  • Der Stub berechnet seine tatsächliche Ausführungsposition und verschiebt sich bei Überlappungen per Self-Relocation an eine sichere Stelle
  • Er initialisiert seinen BSS-Bereich und lädt eine einfache IDT (einschließlich Handlern für Page Faults und NMI)
    • Tritt ein Page Fault auf, wird die fehlende Zuordnung sofort ergänzt, um die Ausführung wiederherzustellen
  • Für benötigte Bereiche wie Kernel, Boot-Parameter und Kommandozeilenpuffer wird ein Identity Mapping erzeugt

Kernel-Dekomprimierung

  • Die Funktion extract_kernel wird ausgeführt und entpackt den Kernel
    • Unterstützt werden verschiedene Kompressionsalgorithmen wie gzip, xz, zstd und lzo
    • Nach dem Entpacken wird der ELF-Header gelesen, um Code- und Datenabschnitte an die korrekten Adressen zu kopieren
  • Wenn sich die Build-Adresse des Kernels von der tatsächlich geladenen Adresse unterscheidet, wird eine Relokation durchgeführt
    • Dabei werden Instruktionen oder Pointer mit eingebetteten Adressen an die tatsächliche Speicherposition angepasst
  • Sind alle Vorbereitungen abgeschlossen, erfolgt der Sprung in die Funktion start_kernel, womit die eigentliche Kernel-Initialisierung beginnt

Selbstverschiebung des Kernels (kASLR)

  • kASLR (Kernel Address Space Layout Randomization) randomisiert die physischen und virtuellen Adressen des Kernels und erhöht damit die Schwierigkeit von Angriffen
    • Beim Booten werden zwei Basiswerte zufällig gewählt
      • Physische Basis: die RAM-Adresse, an der sich der Kernel tatsächlich befindet
      • Virtuelle Basis: die Startadresse des virtuellen Adressraums, den der Kernel verwendet
  • Ablauf der Auswahl
    • Es wird eine Liste der zu schützenden Bereiche erstellt, darunter Bootloader, initrd und Kommandozeilenpuffer
    • Die Speicherkarte der Firmware wird nach ausreichend großen freien Bereichen durchsucht
    • Mithilfe von Entropie, etwa aus Hardware-Zufallsinstruktionen, wird ein zufälliger Slot ausgewählt
  • Falls kein geeigneter Bereich gefunden wird, wird auf die Standardadresse zurückgefallen; mit der Option nokaslr wird die Randomisierung deaktiviert

Begriffe im Überblick

  • Hexadecimal (Hexadezimal): mit dem Präfix 0x gekennzeichnet; praktisch für Hardware-Bitstrukturen und Alignment
  • Register: temporärer Speicher innerhalb der CPU (CS, DS, SS, IP, SP usw.)
  • Segment/Offset: Adressberechnung im Real Mode (segment * 16 + offset)
  • BIOS/UEFI: Firmware für Systeminitialisierung und das Laden des Boot-Programms
  • Bootloader (GRUB): lädt den Kernel und übergibt Systeminformationen
  • Stack/BSS: temporärer Funktionsspeicher bzw. Bereich globaler Variablen, die mit 0 initialisiert sind
  • Interrupt/NMI: Mechanismus zur Verarbeitung von Hardware- und Software-Ereignissen
  • GDT/IDT: Tabellen zur Definition von Segmenten und Interrupts
  • A20-Leitung: Schalter zur Vermeidung des 1-MB-Adress-Wrappings
  • Protected Mode/Long Mode: 32-Bit- und 64-Bit-Ausführungsmodi
  • Paging/Seitentabellen: Zuordnung zwischen virtuellen und physischen Adressen

1 Kommentare

 
GN⁺ 2025-10-26
Hacker-News-Kommentare
  • Wirklich ein guter Artikel. Ich habe vor ein paar Monaten ebenfalls über den Linux-Bootprozess geschrieben, mit etwas stärkerem Fokus auf die Disk-I/O-Seite (was sich auf der Festplatte befindet und wie es geladen wird) Meinen Artikel gibt es unter Booting x86-64
  • Im Seitenquelltext gab es diesen Code
    
      uwu
    
    
    Das hat bei mir ein gewisses „Was ist das denn?“ ausgelöst
    • Das ist noch eine Funktion in Arbeit
  • UEFI ist eine von der Firmware implementierte Schnittstelle. Es ist also nicht die Firmware selbst, sondern eine standardisierte Schnittstelle, um mit der Firmware zu kommunizieren Die Formulierung „UEFI startet die Maschine“ ist terminologisch leicht ungenau. Tatsächlich startet die Firmware die Maschine, und wir kommunizieren über UEFI mit der Firmware Der Artikel lässt viele interessante Aspekte moderner Firmware aus. Wenn man zum Beispiel ExitBootServices() aufruft, befindet man sich bereits im Long Mode. Man muss also nicht extra den Übergang durch Real/Protected Mode durchlaufen
    • Ich würde gern wissen, wo es Material gibt, das darauf näher eingeht
  • Ich habe mich gefragt, ob der Power-Button wirklich direkt die CPU einschaltet. Vielleicht ist es eher so, dass die Intel Management Engine (oder das entsprechende AMD-Pendant) ständig aktiv ist, das Signal des Power-Buttons entgegennimmt und dann die CPU startet
    • Ich denke, diese Rolle übernimmt der Embedded Controller (EC). Das ist der Teil, der aktiv wird, bevor der Bootloader die CPU hochfährt Bei Chromebooks ist dieser Teil zusammen mit dem coreboot-Bootloader als Open Source veröffentlicht Die zugehörige Dokumentation findet sich im Chromium EC Zephyr README
  • Ich suche nach einer ausführlicheren Version dieses Themas. Ich möchte nicht gleich komplette Mikroprozessor-Datenblätter lesen, aber Material, das auch die Phase vor UEFI/BIOS etwas tiefer behandelt, wäre interessant
  • Der Artikel ist interessant, aber gleichzeitig habe ich mich gefragt, warum er sogar noch Hexadezimalzahlen (HEX) erklären muss. Wer so einen Artikel liest, sollte das doch eigentlich wissen Eine weitere Sache, die mich interessiert: Wie genau wird in dem Moment, in dem man den physischen Power-Button drückt, die Verbindung zum Reset Vector hergestellt? Das ist so ein Bereich der Hardware- und Elektronikmagie
    • HN wird nicht nur von IT-Profis gelesen. Es kann gut sein, dass jemand den Linux-Bootprozess verstehen will, aber das Konzept von Hexadezimalzahlen nicht kennt oder vergessen hat
  • Das Thema ist interessant, wirkte aber zu sehr auf Anfänger ausgerichtet
    • Bei Erklärungen wie „Wenn die Stromversorgung stabil ist, wird die CPU in den Real Mode zurückgesetzt“ habe ich mich gefragt, ob meine Großmutter wirklich so versiert ist, dass sie so etwas versteht
    • An der Uni habe ich Zielgruppenanalyse (audience analysis) gelernt: Wichtig ist zu entscheiden, welches Vorwissen man voraussetzt und welche Begriffe oder Abkürzungen man ausschreiben sollte. In technischem Schreiben ist das fast eine Kunstform
  • Auf dem Handy war der Text schwer zu lesen. Die Schriftfarbe war viel zu blass
    • Auch in Desktop-Browsern war das Styling nicht besonders gut. Mit dem Lesemodus von Firefox oder Firefox Mobile lässt es sich deutlich angenehmer lesen
    • Das wirkte ein bisschen wie ein selbstabwertendes Design
  • GRUB wurde zwar erwähnt, aber nicht im Detail behandelt Dazu ist Pixelbeats Dokument zur Festplattenstruktur hilfreich
  • Beim Lesen dieses Artikels musste ich an ein früheres technisches Bewerbungsgespräch bei Facebook denken. Das war um 2010 herum ein Telefoninterview für eine Position als Production Engineer, und ich wurde gefragt: „Erklären Sie den Bootprozess eines Linux-Servers“ Abgesehen vom Hinweis, tiefer ins Detail zu gehen, bekam ich keinerlei Hilfe. Am Ende bin ich nicht nach Dublin gezogen, und nun ja, wegen surveillance capitalism und so waren die Trauben wohl noch nicht ganz reif