Viele Menschen interessieren sich dafür, wie der Computer startet. Hier beginnt der Zauber, der so lange anhält, wie das Gerät eingeschaltet ist. In diesem Artikel geben wir einen Überblick über den Boot- Prozess, einschließlich seiner verschiedenen Phasen, der beteiligten Schlüsselkomponenten und der Herausforderungen, denen sich der Bootvorgang stellt.
Während unser Hauptaugenmerk auf der x86-Architektur liegt (die am weitesten verbreitete), weisen andere Architekturen viele Ähnlichkeiten in ihrem Startvorgang auf. Ich hoffe, dass dieser Artikel eine wertvolle Ressource für alle ist, die ihr Wissen auf diesem Gebiet vertiefen möchten. Auf geht's!
Ein integrierter Schaltkreis (Chip), der sich auf der Hauptplatine befindet und den Firmware-Code speichert, der für das Booten des Computers verantwortlich ist, wird BOOT ROM genannt. Dieser Name ist nicht standardisiert, daher nennen andere Entwickler ihn oft FLASH ROM , BIOS FLASH , BOOT FLASH , SPI FLASH usw. (diese Namen werden ihnen aufgrund der Technologie-, Schnittstellen- und Zwecknamen gegeben). Keine Sorge, diese Begriffe sind austauschbar. Der Firmware-Code im BOOT-ROM wird zuerst ausgeführt, wenn der Computer eingeschaltet wird. Es führt grundlegende Tests durch, initialisiert die Hardware und lädt dann den Betriebssystem-Loader von einem bootfähigen Gerät, wie einer Festplatte oder einem USB-Laufwerk, in den Speicher. Dieser Chip besteht aus nichtflüchtigem Speicher (NVM) .
Nichtflüchtiger Speicher ist eine Art Computerspeicher, der seinen Inhalt auch dann behält, wenn der Strom ausgeschaltet ist . Dadurch ist dieser Speichertyp ideal für die Speicherung wichtiger Daten, die auch dann erhalten bleiben müssen, wenn der Computer ausgeschaltet ist. Darüber hinaus wird sich die Diskussion nur auf den Speicher konzentrieren, der den Firmware-Code enthält. Wir werden nicht über Speicher wie Festplatten (HDD), Solid State Drives (SSD), Disketten usw. sprechen.
Grundsätzlich können wir diese Art von Gedächtnis in die folgenden Gruppen einteilen.
Elektrisch löschbar programmierbar (EEPROM): Kann mithilfe elektrischer Signale mehrfach umprogrammiert werden.
NOR-Flash-Speicher : Architektonisch in Blöcken angeordnet, wobei Daten auf Blockebene gelöscht werden und auf Byteebene gelesen oder geschrieben werden können. Auf den NOR-Speicher kann über eine Standardschnittstelle wie Byteparallel, I2C oder SPI direkt zugegriffen werden.
In der Branche gibt es eine Konvention, den Begriff EEPROM für byteweise löschbare Speicher im Vergleich zu blockweise löschbaren Flash- Speichern zu verwenden.
Beim programmierbaren Speicher gilt eine Regel: Vor dem Schreiben löschen . In einem solchen Speicher ist das Schreiben neuer Daten komplizierter, da die Daten als Ladung auf einem Floating Gate gespeichert werden (der Grund dafür liegt größtenteils in der Physik der Speicherzellen). Die Ladungsmenge am Gate bestimmt, ob die Zelle „0“ oder „1“ speichert.
Wenn Sie einen Flash-Speicherchip löschen, setzen Sie alle darauf gespeicherten Datenbits auf einen bekannten (Standard-)Zustand, normalerweise eine logische „1“. Damit kann man sozusagen ganz von vorn anfangen und neue Daten auf den Chip programmieren, ohne dass noch Reste der alten Daten darauf gespeichert sind. Wenn neue Daten auf den Chip geschrieben werden, wird der Zustand einzelner Bits von „1“ auf „0“ geändert, um die neuen Daten darzustellen.
Wenn Sie einfach neue Daten auf den Chip schreiben, ohne sie vorher zu löschen, würden die neuen Daten mit den alten Daten kombiniert werden, was zu unvorhersehbaren Ergebnissen führen würde. Stellen Sie sich beispielsweise einen Flash-Speicherchip vor, der über 8 Bit Speicher verfügt und den Wert „0110 0010“ speichert. Wenn Sie neue Daten „1100 1001“ auf den Chip schreiben, ohne sie vorher zu löschen, wäre der resultierende Zustand des Chips „0100 0000“, was möglicherweise nicht Ihren Absichten entspricht.
Die größte Verwirrung hängt mit dem Wort ROM zusammen, das für Read Only Memory steht. Der Begriff „Nur-Lese-Speicher“ wurde in der Vergangenheit für Speicher verwendet, der dauerhaft ist und vom Benutzer nicht geändert werden kann. Mit fortschreitender Technologie hat sich jedoch die Definition von ROM geändert und wird heute oft als Bezeichnung für Speicher verwendet, der werkseitig vorprogrammiert ist und vom Endbenutzer nicht einfach geändert werden kann. Wenn der Benutzer jedoch über die gewünschten Fähigkeiten und spezielle Ausrüstung verfügt (z. B. einen Programmierer), kann er den Chip neu programmieren. Der Name ROM ist, auch wenn sich die Definition geändert hat, als historischer Hinweis auf den ursprünglichen Zweck des Speichers geblieben.
Durch die Anwendung eines Schreibschutzes können einige Arten von umprogrammierbaren ROMs vorübergehend zu Nur-Lese-Speichern werden.
Dies sind NICHT ALLE existierenden Arten von nichtflüchtigen Speichern, sondern die meisten der beliebtesten, von denen Sie vielleicht nur zufällig hören. Heutzutage werden diese Chips auf den meisten Motherboards mithilfe der NOR-Flash-Technologie hergestellt.
Execute in Place (XIP) ist eine Methode, die es dem Prozessor ermöglicht, Code direkt aus dem Flash-Speicher auszuführen, ohne ihn zuerst in den flüchtigen Speicher (z. B. RAM ) zu kopieren. Dies wird erreicht, indem der Flash-Speicher dem Adressraum des Prozessors zugeordnet wird, sodass die Codeausführung direkt vom Flash aus durchgeführt werden kann. So kann das System so schnell wie möglich mit der Ausführung von Code beginnen, ohne zunächst auf die Initialisierung des RAM warten zu müssen.
Warten Sie ... die CPU kann über das SPI/Parallel/etc-Protokoll mit dem BOOT-ROM kommunizieren? Natürlich nicht, es geht nur darum, Anweisungen aus dem Systemspeicher abzurufen, Anfragen an diesen Speicherbereich werden an das Intel Direct Media Interface (DMI ) oder AMD Infinity Fabric (IF) / Unified Media Interface (UMI) (Vorgänger) umgeleitet. Es ist die Verbindung zwischen der CPU und dem Chipsatz auf dem Motherboard. Zu diesem Zeitpunkt erfolgt die Decodierung der Adresse über Decoder im Chipsatz und die Daten vom Chip werden an den Prozessor zurückgegeben.
Wenn der Chip aus NOR-Flash-Speicher besteht, der Direktzugriffslesevorgänge, aber keine Direktzugriffsschreibvorgänge unterstützt, trat ein Problem auf. Sofern kein beschreibbarer Speicher verfügbar ist, müssen alle Berechnungen innerhalb der Prozessorregister durchgeführt werden. Zu diesem Zeitpunkt kann der Code nur in Assemblersprache geschrieben werden und dient dazu, die Umgebung für eine Hochsprache (normalerweise für die Sprache C ) einzurichten. Der Grund dafür ist, dass die Speicherinitialisierung so komplex geworden ist, dass es schwierig wäre, rein in Assembler zu schreiben. Da solche Sprachen mindestens einen Heap und einen Stack erfordern, benötigen wir beschreibbaren Speicher. Bei einigen Prozessoren ist SRAM in den Chip selbst integriert, aber ein modernerer Ansatz besteht darin, den integrierten Cache-Speicher als RAM (CAR) zu verwenden.
Der CPU-Cache ist ein Hochgeschwindigkeitsspeicher, der eine Kopie häufig verwendeter Daten und Anweisungen aus dem Hauptspeicher speichert. Ein Cache befindet sich näher am Prozessor und ist in mehrere Ebenen (L1, L2, L3, ...) unterteilt, wobei jede Ebene größer und langsamer als die vorherige ist.
Befinden sich die Daten im Cache, kann die CPU die angeforderten Daten aus dem Cache abrufen (dies wird als Cache-Treffer bezeichnet). Wenn der CPU-Cache die erforderlichen Daten nicht finden kann, führt dies zu einem Cache-Miss . Dies kann entweder darauf zurückzuführen sein, dass die Daten nie im Cache gespeichert wurden, oder weil die Daten zuvor gespeichert wurden, aber aus dem Cache entfernt wurden. Auf jeden Fall muss der Prozessor bis zum Hauptspeicher vordringen, um auf die Daten zuzugreifen und sie in den Cache zu kopieren.
Beim Cache-Räumen werden Daten aus dem Cache entfernt, um Speicherplatz für neue Daten freizugeben. Die Löschung von Daten kann entweder durch das Caching-System (normalerweise, wenn ein Cache voll ist und neue Daten gespeichert werden müssen oder wenn die Gültigkeitsdauer der Daten abgelaufen ist) oder durch eine explizite Anfrage eingeleitet werden.
Wenn wir jedoch den CPU- Cache als RAM verwenden möchten, müssen wir den Cache für den Betrieb im Non-Eviction-Modus , auch No-Fill-Modus genannt, einrichten. Diese Technik verhindert eine Räumung aufgrund eines Cache-Fehlers . Stattdessen wird der Cache wie ein regulärer SRAM behandelt und alle Zugriffe (Lesen/Schreiben) treffen den Cache und nicht den Hauptspeicher. Der Modus kann über herstellerspezifische CPU-Anweisungen aktiviert werden.
Tatsächlich enthält das BOOT-ROM mehrere Arten von Firmware. Sobald eine Menge Firmware im BOOT-ROM gespeichert ist, muss sie irgendwie organisiert werden, um sie unterscheiden zu können. Lassen Sie uns herausfinden, wie es gemacht wird.
Ursprünglich führt der Chipsatz eine direkte Zuordnung des gesamten BOOT-ROM-Inhalts zum Speicher durch (von 4 GB auf 4 GB – 16 MB). Wenn das BOOT-ROM weniger als 16 MB beträgt, werden die Inhalte normalerweise wiederholt zugeordnet. Die CPU und die Firmware können ohne Einschränkungen auf den Flash lesen/schreiben.
Der Non-Descriptor-Modus wird bei neuen Chipsätzen nicht mehr unterstützt.
Schließlich führt Intel im ICH8 ein spezielles Layout für das BOOT-ROM ein. Der Blitz ist in folgende Bereiche unterteilt:
Flash Descriptor (FD) – diese Datenstruktur muss sich am Anfang des Geräts mit einem Offset 0x10
befinden. Es besteht aus elf Abschnitten, wie in der folgenden Abbildung dargestellt:
Die Deskriptor-MAP enthält Zeiger auf die anderen Regionen und auch auf deren Größe.
Der Abschnitt „Komponente“ enthält Informationen zu den Flash(s) im System (Anzahl der Komponenten, deren Dichte, ungültige Anweisungen usw.).
Der Abschnitt „Master“ definiert die Lese-/Schreibberechtigungen für Regionen. Was das Lesen/Schreiben betrifft, müssen die Berechtigungen auf „Nur Lesen“ eingestellt sein. Die in diesem Bereich gespeicherten Informationen können nur während des Herstellungsprozesses geschrieben werden.
Der Flash Descriptor und Intel ME sind die einzigen erforderlichen Regionen.
Die FIT ist eine Datenstruktur innerhalb der BIOS-Region und enthält verschiedene Einträge, die die Plattformkonfiguration beschreiben. Jeder Eintrag in der Tabelle ist 16 Byte groß. Der erste wird als FIT-Header bezeichnet, der andere als FIT-Eintrag . Es wird durch einen FIT-Zeiger an einer physischen Adresse 0xFFFFFFC0
(4 GB – 0x40) lokalisiert.
Diese Komponenten müssen verarbeitet werden, bevor der erste CPU-Befehl vom Reset-Vektor ausgeführt wird. Zu den Einträgen gehören CPU-Mikrocode-Updates, Start-ACM, Plattform-Boot-/TPM-/BIOS-/TXT-Richtlinien und andere Dinge. Aber zumindest sollte die FIT FIT-Header- und Microcode-Update- Einträge enthalten. Daher besteht die übliche Verwendung von FIT darin, den Mikrocode zu aktualisieren, bevor der Rücksetzvektor ausgeführt wird.
So sieht die Speicherzuordnung aus:
Leider gibt es viel weniger Informationen, ich konnte keine durchgesickerte AMD-Chipsatzdokumentation mit Details zu deren Layout finden. Ich kann es Ihnen also nicht besser sagen, als es in der Coreboot-Dokumentation steht . Es basiert auf der AMD- Dokumentation, die nur unter NDA verfügbar ist.
Tatsächlich reicht es aus zu wissen, dass das AMD-Analogon des Flash-Deskriptors die eingebettete Firmware-Struktur ist und Zeiger auf die PSP-Verzeichnistabelle , die BIOS-Verzeichnistabelle und andere Firmware enthält.
Wenn Sie sehen wollten, wie genau moderner Speicher und CPU initialisiert werden, dann muss ich Sie verärgern. Intel und AMD haben es nicht eilig, den Silicon Initialization Code für die Community freizugeben. Soweit solche Informationen nicht öffentlich verfügbar sind, bieten sie eine binäre Verteilung des notwendigen Silizium-Initialisierungscodes an. Dies ist als Bibliothek für Firmware-Entwickler zu betrachten und enthält Binärcode zum Initialisieren des Speichercontrollers, des Chipsatzes, der CPU und anderer verschiedener Teile des Systems.
Diese Binärdatei kann in 4 Komponenten aufgeteilt werden:
Hier ist ein von Intel veröffentlichtes Repository mit Intel FSP-Binärdateien , das Sie auf GitHub finden können. Die FSP-Spezifikation v2.1 kann von der Intel-Website bezogen werden.
AGESA für Produkte vor Familie 17h wird als v5 oder Arch2008 bezeichnet. Zu diesem Zeitpunkt war AGESA Open-Source und der Code war im Coreboot-Repository verfügbar (er wurde nach Version 4.18 veraltet). Die Spezifikation für Arch2008 finden Sie auf der AMD-Website.
Mit der Einführung der Produkte der Familie 17h (Zen-Mikroarchitektur) hat AMD keinen AGESA-Quellcode veröffentlicht, sondern nur vorgefertigte Binärlösungen. Ein solcher Nachfolger heißt AGESA v9 und unterstützt Family 17h und höher.
Es sind keine detaillierten Informationen verfügbar, sondern nur Neuigkeiten .
Ein integraler Bestandteil des modernen x86-Boot-Prozesses, ohne den die x86-Kerne niemals aktiviert würden. Daher ist es unmöglich, sie vollständig zu deaktivieren . Diese Technologien sind für die Initialisierung der Hardware, die Überprüfung der Systemintegrität, die Energieverwaltung und den Start der CPU verantwortlich. Die Firmware für diese Subsysteme wird geladen und ausgeführt , bevor der Hauptprozessor mit der Ausführung seiner eigenen Firmware beginnt. Ein Code auf solchen Systemen läuft unabhängig von den CPU-Kernen der Plattform.
Solange viele Hardware-Unternehmen das Prinzip der Sicherheit durch Obskurität verinnerlicht haben, ist weder der Quellcode noch die Dokumentation für diese Subsysteme verfügbar. Glücklicherweise wissen wir, wie sich dies auf den Startvorgang auswirkt – siehe Hardware-Stromversorgungssequenzen .
Wir gehen nicht näher darauf ein, da es im Internet bereits umfangreiche Artikel von Forschern aus aller Welt gibt. Aber ich werde Ihnen nur kurz beschreiben, was es ist.
Intel ME ist ein separater i486/80486- Mikroprozessor, der seit 2008 in den Intel-Chipsatz (PCH) integriert ist. Er verfügt über einen eigenen RAM, ein integriertes ROM und Busbrücken zu allen Bussen innerhalb des Chipsatzes (dadurch kann er auf das Netzwerk zugreifen). und sogar der Haupt-RAM der CPU) und so weiter. Führt ein benutzerdefiniertes Betriebssystem basierend auf MINIX aus.
AMD PSP ist ein ARM- Kern, der auf der Trustzone-Erweiterung basiert und als Coprozessor in den CPU-Chip eingefügt wird. Dieser Chip ist seit 2013 in die meisten AMD-Plattformen integriert. Läuft auf einem undokumentierten und proprietären Betriebssystem.
Dieser Prozess, auch Power On Sequence oder Power Sequencing genannt, stellt eine Reihe abgeleiteter Spannungspegel und/oder Stromversorgungsschienen in einer bestimmten Reihenfolge bereit, die auf der Plattform benötigt wird. Einfacher ausgedrückt: Es schaltet eine Reihe von Plattformkomponenten in einer bestimmten Reihenfolge ein. Der Prozess variiert je nach System- oder Plattformdesign, aber normalerweise umfasst ein Standard-PC die folgenden Schritte:
AMD-basierte Systeme (für Family 17h und höher)
PSP führt das On -Chip-BOOT-ROM aus.
PSP findet die eingebettete Firmware-Tabelle im Off -Chip-BOOT-ROM und führt die PSP-Firmware aus.
PSP analysiert die PSP-Verzeichnistabelle, um ABL-Stufen zu finden, und führt sie aus.
ABL-Stufen initialisieren den Hauptspeicher, suchen das BIOS-Image im BOOT-ROM und laden es in den DRAM (dekomprimieren, wenn das Image komprimiert ist).
Diese Plattform hat keinen Grund, CAR zu verwenden, da DRAM bereits verfügbar ist und PSP das Firmware-Image darauf lädt.
Nachdem die CPU zum ersten Mal eingeschaltet wurde, arbeitet sie im Real-Modus . Die meisten Register verfügen über klar definierte Werte , einschließlich des Instruction Pointer (IP), des Code Segments (CS) und des Descriptor Cache , einer Kopie jedes Segmentdeskriptors innerhalb des Prozessors, um einen schnellen Zugriff auf den Segmentspeicher zu ermöglichen.
Der Segmentdeskriptor ist ein Eintrag in der Global Descriptor Table (GDT) und enthält die Basisadresse, das Segmentlimit und Zugriffsinformationen (dieser Teil wird ignoriert, da der Realmodus keine Zugriffskontrolle wie der geschützte Modus hat). Anstatt bei jedem Speicherzugriff auf den GDT (der sich im Speicher befindet) zuzugreifen, werden die Informationen in einem Deskriptor-Cache gespeichert.
Allerdings ist der GDT im Real-Modus nicht beteiligt, sodass der Prozessor intern Einträge generiert. Das CS-Auswahlregister, das für den Zugriff auf den Segmentdeskriptor verwendet wird, wird mit 0xF000
geladen. Die CS-Basisadresse wird auf 0xFFFF_0000
initialisiert. IP wird auf 0xFFF0
initialisiert.
Daher beginnt der Prozessor, Anweisungen aus dem Speicher abzurufen , der sich an der physischen Adresse 0xFFFF_FFF0
( 0xFFFF_0000
+ 0x0000_FFF0
) befindet. Der erste Befehl, der an dieser Adresse ausgeführt wird, wird als Reset-Vektor bezeichnet.
HINWEIS: Mit diesem Trick erhalten Sie Zugriff auf den oberen Adressraum. Sie können jedoch nicht auf den Code unterhalb der Adresse 0xFFFF_0000
zugreifen. Die CS-Basisadresse bleibt auf diesem Anfangswert, bis das CS-Auswahlregister von der Firmware geladen wird. Dies kann durch einen Weitsprung erfolgen.
An diesem Punkt ist die beste Entscheidung, in den geschützten Modus mit 4 GB Adressierbarkeit zu wechseln. Wenn die Firmware dies nicht tut, muss der Chipsatz in der Lage sein, einen Speicherbereich unter 1 MB in einen entsprechenden Bereich knapp unter 4 GB umzuwandeln, damit der Real-Modus funktioniert. Bestimmte Chipsätze verfügen nicht über dieses Aliasing und erfordern möglicherweise einen Wechsel in einen anderen Betriebsmodus, bevor der erste Weitsprung ausgeführt wird.
Ich empfehle Ihnen, sich das folgende Video zur Einschaltsequenz anzusehen, in dem der Vorgang am Beispiel des ASUS P9X79-Motherboards erläutert wird. Obwohl es in russischer Sprache ist, können Sie alles verstehen, wenn Sie die automatisch generierten englischen Untertitel einschalten.
Dieser Artikel enthält viele theoretische Informationen zur Funktionsweise des Bootens. Um diesen Prozess wirklich zu verstehen, müssen wir uns jedoch den Quellcode und die Architektur vorhandener Firmware genauer ansehen.
Im nächsten Artikel werden wir tiefer auf BIOS , UEFI und Coreboot eingehen, um sie im Detail zu untersuchen.