Skip to content

Latest commit

 

History

History
455 lines (357 loc) · 24 KB

File metadata and controls

455 lines (357 loc) · 24 KB

Schreiben von Easyboot-kompatiblen Kerneln

Easyboot unterstützt verschiedene Kernel mit Plugins. Wenn jedoch kein passendes Plugin gefunden wird, greift es auf ELF64- oder PE32+-Binärdateien mit einer vereinfachten Variante des Multiboot2-Protokolls zurück (keine Notwendigkeit, etwas einzubetten).

Dies ist genau das gleiche Protokoll, das Simpleboot verwendet. Alle Beispielkernel in diesem Repo müssen auch mit Easyboot funktionieren.

Sie können den ursprünglichen multiboot2.h-Header im GRUB-Repo oder die C/C++-Header-Datei easyboot.h verwenden, um einfacher darauf zuzugreifen Verwenden Sie Typedefs. Das Low-Level-Binärformat ist dasselbe. Sie können auch alle vorhandenen Multiboot2-Bibliotheken verwenden, auch mit Nicht-C-Sprachen, wie Rust -Bibliothek zum Beispiel (Hinweis: Ich bin in keiner Weise mit diesen Entwicklern verbunden, ich habe nur nach „Rust Multiboot2“ gesucht und das war die erste Ergebnis).

[[TOC]]

Startvorgang

Bootstrapping des Loaders

Auf BIOS-Maschinen wird der allererste Sektor der Festplatte von der Firmware auf 0:0x7C00 geladen und ihm wird die Kontrolle übergeben. In diesem Sektor verfügt Easyboot über boot_x86.asm, das intelligent genug ist, um den 2. Stage-Loader zu finden und zu laden und auch den Langmodus dafür einzurichten.

Auf UEFI-Maschinen wird dieselbe Datei der zweiten Stufe mit dem Namen EFI/BOOT/BOOTX64.EFI direkt von der Firmware geladen. Die Quelle für diesen Loader finden Sie in loader_x86.c. Das ist es, Easyboot ist weder GRUB noch Syslinux, die beide Dutzende und Aberdutzende Systemdateien auf der Festplatte erfordern. Hier werden keine weiteren Dateien benötigt, nur diese (Plugins sind optional, keine erforderlich, um Multiboot2-Kompatibilität bereitzustellen).

Auf Raspberry Pi heißt der Loader KERNEL8.IMG, kompiliert aus loader_rpi.c.

Der Lader

Dieser Loader wurde sehr sorgfältig geschrieben, um auf mehreren Konfigurationen zu funktionieren. Es lädt die GUID-Partitionierungstabelle von der Festplatte und sucht nach einer „EFI-Systempartition“. Wenn es gefunden wird, sucht es auf dieser Boot-Partition nach der Konfigurationsdatei easyboot/menu.cfg. Nachdem die Boot-Option ausgewählt und der Dateiname des Kernels bekannt ist, findet und lädt der Loader ihn.

Es erkennt dann automatisch das Format des Kernels und ist intelligent genug, um die Abschnitts- und Segmentinformationen darüber zu interpretieren, wo was geladen werden soll (es führt bei Bedarf eine Speicherzuordnung bei Bedarf durch). Anschließend richtet es je nach erkanntem Boot-Protokoll (Multiboot2 / Linux / usw. geschützter oder langer Modus, ABI-Argumente usw.) eine geeignete Umgebung ein. Nachdem der Maschinenzustand stabil und klar definiert ist, springt der Loader als allerletzten Schritt zum Einstiegspunkt Ihres Kernels.

Maschinenzustand

Es gilt alles, was in der Multiboot2-Spezifikation (auf Englisch) über den Maschinenstatus geschrieben steht, mit Ausnahme der Allzweckregister. Easyboot übergibt gemäß der SysV-ABI und der Microsoft-Fastcall-ABI zwei Argumente an den Einstiegspunkt Ihres Kernels. Der erste Parameter ist die Magie, der zweite ist a physische Speicheradresse, die auf eine Multiboot-Informations-Tagliste verweist (im Folgenden als MBI abgekürzt, siehe unten).

Wir verletzen auch ein wenig das Multiboot2-Protokoll, um Kernel der höheren Hälfte zu verarbeiten. Multiboot2 schreibt vor, dass dem Speicher eine Identitätszuordnung zugewiesen werden muss. Nun, unter Easyboot trifft dies nur teilweise zu: Wir garantieren nur, dass der gesamte physische RAM sicher wie erwartet identitätszugeordnet ist; Einige darüber liegende Regionen (abhängig von den Programm-Headern des Kernels) sind jedoch möglicherweise noch verfügbar. Dies beeinträchtigt nicht normale Multiboot2-kompatible Kernel, die nicht auf Speicher außerhalb des verfügbaren physischen RAM zugreifen sollen.

Ihr Kernel wird sowohl auf BIOS- und UEFI-Systemen als auch auf RPi genau gleich geladen, Firmware-Unterschiede sind nur „Jemand Else's Problem“. Das Einzige, was Ihr Kernel sehen wird, ist, ob der MBI das EFI-Systemtabellen-Tag enthält oder nicht. Um Ihnen das Leben zu vereinfachen, generiert Easyboot auch kein EFI-Speicherzuordnungs-Tag (Typ 17), sondern stellt nur bereit das Tag Speicherzuordnungs (Typ 6) wahllos auf allen Plattformen (auch auf UEFI-Systemen, dort wird die Speicherzuordnung einfach für Sie konvertiert, Ihr Kernel muss sich also nur mit einer Art von Speicherlisten-Tags befassen). Auch alte, veraltete Tags werden von diesem Bootmanager weggelassen und nie generiert.

Der Kernel läuft auf Supervisor-Ebene (Ring 0 auf x86, EL1 auf ARM), möglicherweise auf allen CPU-Kernen parallel.

GDT nicht angegeben, aber gültig. Der Stapel ist in den ersten 640 KB eingerichtet und wächst nach unten (aber Sie sollten dies so schnell wie möglich auf den Stapel ändern, den Sie für angemessen halten). Wenn SMP aktiviert ist, haben alle Kerne ihre eigenen Stapel und die Kern-ID befindet sich oben auf dem Stapel (aber Sie können die Kern-ID auch auf die übliche plattformspezifische Weise abrufen, indem Sie cpuid / mpidr / usw. verwenden).

Sie sollten IDT als nicht spezifiziert betrachten; IRQs, NMI und Software-Interrupts deaktiviert. Dummy-Ausnahmehandler werden so eingerichtet, dass sie einen minimalen Dump anzeigen und die Maschine anhalten. Sie sollten sich nur darauf verlassen, dass sie melden, wenn Ihr Kernel kaputt geht, bevor Sie Ihren eigenen IDT und Handler einrichten konnten, vorzugsweise so schnell wie möglich. Auf ARM ist vbar_el1 so eingerichtet, dass es dieselben Dummy-Ausnahmehandler aufruft (obwohl sie natürlich unterschiedliche Register ausgeben).

Framebuffer ist ebenfalls standardmäßig festgelegt. Sie können die Auflösung in der Konfiguration ändern, aber wenn sie nicht angegeben wird, ist der Framebuffer weiterhin konfiguriert.

Es ist wichtig, niemals von Ihrem Kernel zurückzukehren. Es steht Ihnen frei, jeden Teil des Loaders im Speicher zu überschreiben (sobald Sie mit den MBI-Tags fertig sind), sodass Sie einfach nirgendwohin zurückkehren können. „Der Mohr hat seine Schuldigkeit getan, der Mohr kann gehen.“

An Ihren Kernel übergebene Boot-Informationen (MBI)

Es ist zunächst nicht offensichtlich, aber die Multiboot2-Spezifikation definiert tatsächlich zwei völlig unabhängige Sätze von Tags:

  • Der erste Satz soll in einen Multiboot2-kompatiblen Kernel eingebunden sein und wird als Multiboot2-Header des Betriebssystem-Images bezeichnet (Abschnitt 3.1.2) und wird daher vom Kernel bereitgestellt. Easyboot kümmert sich nicht um diese Tags und analysiert Ihren Kernel auch nicht danach. Sie benötigen einfach keine speziellen magischen Daten, die in Ihre Kerneldatei eingebettet sind, da Easyboot, ELF- und PE-Header ausreichen.

  • Der zweite Satz wird beim Booten dynamisch an den Kernel übergeben, Easyboot verwendet nur diese Tags. Es generiert jedoch nicht alles, was Multiboot2 angibt (es lässt einfach die alten, veralteten oder Legacy-Angaben weg). Diese Tags werden MBI-Tags genannt, siehe Boot-Informationen (Abschnitt 3.6).

HINWEIS: Die Multiboot2-Spezifikation für MBI-Tags ist verdammt fehlerhaft. Unten finden Sie eine korrigierte Version, die mit der Header-Datei multiboot2.h übereinstimmt, die Sie im Quell-Repository von GRUB finden.

Der erste Parameter Ihres Kernels ist der magische 0x36d76289 (in rax, rcx und rdi). Sie können die MBI-Tags mithilfe des zweiten Parameters finden (in rbx, rdx und rsi). Auf der ARM-Plattform befindet sich Magic in x0 und die Adresse in x1. Auf RISC-V und MIPS werden jeweils a0 und a1 verwendet. Wenn dieser Loader auf eine andere Architektur portiert wird, müssen immer die durch SysV ABI für Funktionsargumente angegebenen Register verwendet werden. Wenn es andere gemeinsame ABIs auf der Plattform gibt, die die SysV-ABI nicht beeinträchtigen, sollten die Werte auch in den Registern dieser ABIs (oder oben im Stapel) dupliziert werden.

Überschriften

Die übergebene Adresse ist immer 8 Bytes lang ausgerichtet und beginnt mit einem MBI-Header:

        +-------------------+
u32     | total_size        |
u32     | reserved          |
        +-------------------+

Darauf folgt eine Reihe von ebenfalls 8 Byte großen ausgerichteten Tags. Jedes Tag beginnt mit den folgenden Tag-Header-Feldern:

        +-------------------+
u32     | type              |
u32     | size              |
        +-------------------+

type enthält eine Kennung des Inhalts des restlichen Tags. size enthält die Größe des Tags einschließlich der Header-Felder, jedoch ohne Auffüllung. Tags folgen aufeinander und werden bei Bedarf aufgefüllt, damit jedes Tag an einer 8-Byte-ausgerichteten Adresse beginnt.

Abschlusszeichen

        +-------------------+
u32     | type = 0          |
u32     | size = 8          |
        +-------------------+

Tags werden durch ein Tag vom Typ 0 und der Größe 8 abgeschlossen.

Boot-Befehlszeile

        +-------------------+
u32     | type = 1          |
u32     | size              |
u8[n]   | string            |
        +-------------------+

string enthält die in der „kernel“-Zeile von menuentry angegebene Befehlszeile (ohne Pfad und Dateinamen des Kernels). Die Befehlszeile ist eine normale, nullterminierte UTF-8-Zeichenfolge im C-Stil.

Bootloader-Name

        +----------------------+
u32     | type = 2             |
u32     | size = 17            |
u8[n]   | string "Easyboot"    |
        +----------------------+

string enthält den Namen eines Bootloaders, der den Kernel bootet. Der Name ist eine normale nullterminierte UTF-8-Zeichenfolge im C-Stil.

Moduls

        +-------------------+
u32     | type = 3          |
u32     | size              |
u32     | mod_start         |
u32     | mod_end           |
u8[n]   | string            |
        +-------------------+

Dieses Tag zeigt dem Kernel an, welches Bootmodul zusammen mit dem Kernel-Image geladen wurde und wo es zu finden ist. mod_start und mod_end enthalten die physischen Start- und Endadressen des Bootmoduls selbst. Sie erhalten nie einen mit gzip komprimierten Puffer, da Easyboot diese transparent für Sie dekomprimiert (und wenn Sie ein Plugin bereitstellen, funktioniert es auch mit anderen als mit gzip komprimierten Daten). Das Feld string stellt eine beliebige Zeichenfolge bereit, die diesem bestimmten Bootmodul zugeordnet werden soll; Es handelt sich um eine normale nullterminierte UTF-8-Zeichenfolge im C-Stil. Wird in der „Module“-Zeile von menuentry angegeben und seine genaue Verwendung ist betriebssystemspezifisch. Im Gegensatz zum Boot-Befehlszeilen-Tag enthalten die Modul-Tags auch den Pfad und den Dateinamen des Moduls.

Pro Modul erscheint ein Tag. Dieser Tag-Typ kann mehrmals vorkommen. Wenn eine erste Ramdisk zusammen mit Ihrem Kernel geladen wurde, wird diese als erstes Modul angezeigt.

Es gibt einen Sonderfall: Wenn es sich bei der Datei um eine DSDT-ACPI-Tabelle, einen FDT-Blob (dtb) oder GUDT-Blob handelt, wird sie nicht als Modul angezeigt, sondern ACPI altes RSDP (Typ 14) oder ACPI neues RSDP (Typ 15) wird gepatcht und ihre DSDT durch den Inhalt dieser Datei ersetzt.

Speicherzuordnungs

Dieses Tag stellt eine Speicherzuordnung bereit.

        +-------------------+
u32     | type = 6          |
u32     | size              |
u32     | entry_size = 24   |
u32     | entry_version = 0 |
varies  | entries           |
        +-------------------+

size enthält die Größe aller Einträge einschließlich dieses Feldes selbst. entry_size ist immer 24. entry_version ist auf 0 gesetzt. Jeder Eintrag hat folgenden Aufbau:

        +-------------------+
u64     | base_addr         |
u64     | length            |
u32     | type              |
u32     | reserved          |
        +-------------------+

base_addr ist die physische Startadresse. length ist die Größe des Speicherbereichs in Bytes. type ist die Art des dargestellten Adressbereichs, wobei der Wert „1“ den verfügbaren RAM angibt, der Wert „3“ den nutzbaren Speicher mit ACPI-Informationen angibt und der Wert „4“ den reservierten Speicher angibt, der im Ruhezustand erhalten bleiben muss. Der Wert „5“ zeigt einen Speicher an, der durch defekte RAM-Module belegt ist, alle anderen Werte weisen derzeit auf einen reservierten Bereich hin. reserved wird beim BIOS-Booten auf „0“ gesetzt.

Wenn der MBI auf einem UEFI-Computer generiert wird, werden verschiedene EFI-Speicherzuordnungseinträge als Typ „1“ (verfügbarer RAM) oder „2“ (reservierter RAM) gespeichert, und falls Sie ihn benötigen, wird der ursprüngliche EFI-Speichertyp darin abgelegt Feld reserved.

Die bereitgestellte Karte listet garantiert den gesamten Standard-RAM auf, der für die normale Verwendung verfügbar sein sollte, und sie ist immer nach aufsteigender „base_addr“ sortiert. Dieser verfügbare RAM-Typ umfasst jedoch die von Kernel, MBI, Segmenten und Modulen belegten Bereiche. Der Kernel muss darauf achten, diese Regionen nicht zu überschreiben (Easyboot könnte diese Regionen leicht ausschließen, aber das würde die Multiboot2-Kompatibilität beeinträchtigen).

Bildschirminformationen

        +----------------------------------+
u32     | type = 8                         |
u32     | size = 38                        |
u64     | framebuffer_addr                 |
u32     | framebuffer_pitch                |
u32     | framebuffer_width                |
u32     | framebuffer_height               |
u8      | framebuffer_bpp                  |
u8      | framebuffer_type = 1             |
u16     | reserved                         |
u8      | framebuffer_red_field_position   |
u8      | framebuffer_red_mask_size        |
u8      | framebuffer_green_field_position |
u8      | framebuffer_green_mask_size      |
u8      | framebuffer_blue_field_position  |
u8      | framebuffer_blue_mask_size       |
        +----------------------------------+

Das Feld framebuffer_addr enthält die physische Adresse des Framebuffers. Das Feld framebuffer_pitch enthält die Länge einer Zeile in Bytes. Die Felder framebuffer_width und framebuffer_height enthalten Framebuffer-Abmessungen in Pixel. Das Feld framebuffer_bpp enthält die Anzahl der Bits pro Pixel. framebuffer_type ist immer auf 1 gesetzt und reserved enthält in der aktuellen Version der Spezifikation immer 0 und muss vom Betriebssystem-Image ignoriert werden. Die übrigen Felder beschreiben das gepackte Pixelformat, die Position und Größe der Kanäle in Bits. Sie können den Ausdruck ((~(0xffffffff << size)) << position) & 0xffffffff verwenden, um eine UEFI-GOP-ähnliche Kanalmaske zu erhalten.

EFI 64-Bit-Systemtabellenzeiger

Dieses Tag existiert nur, wenn Easyboot auf einem UEFI-Computer ausgeführt wird. Auf einem BIOS-Computer wurde dieses Tag nie generiert.

        +-------------------+
u32     | type = 12         |
u32     | size = 16         |
u64     | pointer           |
        +-------------------+

Dieses Tag enthält einen Zeiger auf die EFI-Systemtabelle.

EFI 64-Bit-Bild-Handle-Zeiger

Dieses Tag existiert nur, wenn Easyboot auf einem UEFI-Computer ausgeführt wird. Auf einem BIOS-Computer wurde dieses Tag nie generiert.

        +-------------------+
u32     | type = 20         |
u32     | size = 16         |
u64     | pointer           |
        +-------------------+

Dieses Tag enthält einen Zeiger auf das EFI-Bildhandle. Normalerweise ist es das Bootloader-Image-Handle.

SMBIOS-Tabellen

        +-------------------+
u32     | type = 13         |
u32     | size              |
u8      | major             |
u8      | minor             |
u8[6]   | reserved          |
        | smbios tables     |
        +-------------------+

Dieses Tag enthält eine Kopie der SMBIOS-Tabellen sowie deren Version.

Alte ACPI-RSDP

        +-------------------+
u32     | type = 14         |
u32     | size              |
        | copy of RSDPv1    |
        +-------------------+

Dieses Tag enthält eine Kopie von RSDP gemäß der Definition in der ACPI 1.0-Spezifikation. (Mit einer 32-Bit-Adresse.)

Neue ACPI-RSDP

        +-------------------+
u32     | type = 15         |
u32     | size              |
        | copy of RSDPv2    |
        +-------------------+

Dieses Tag enthält eine Kopie von RSDP, wie in der Spezifikation ACPI 2.0 oder höher definiert. (Wahrscheinlich mit einer 64-Bit-Adresse.)

Diese (Typ 14 und 15) verweisen auf eine RSDT- oder XSDT-Tabelle mit einem Zeiger auf eine FACP-Tabelle, die wiederum zwei Zeiger auf eine DSDT-Tabelle enthält, die die Maschine beschreibt. Easyboot fälscht diese Tabellen auf Maschinen, die ACPI ansonsten nicht unterstützen. Auch wenn Sie eine DSDT-Tabelle, einen FDT-Blob (dtb) oder GUDT-Blob als Modul bereitstellen, patcht Easyboot die Zeiger so, dass sie auf diese vom Benutzer bereitgestellte Tabelle verweisen. Um diese Tabellen zu analysieren, können Sie meine abhängigkeitsfreie Einzelheader-Bibliothek hwdet (oder die aufgeblähte Bibliothek apcica und libfdt) verwenden.

Kernelspezifische Tags

Tags mit type größer oder gleich 256 sind nicht Teil der Multiboot2-Spezifikation, werden aber dennoch von Easyboot bereitgestellt. Diese können durch optionale Plugins zur Liste hinzugefügt werden, wenn ein Kernel sie benötigt.

EDID

        +-------------------+
u32     | type = 256        |
u32     | size              |
        | copy of EDID      |
        +-------------------+

Dieses Tag enthält eine Kopie der Liste der unterstützten Monitorauflösungen gemäß der EDID-Spezifikation.

SMP

        +-------------------+
u32     | type = 257        |
u32     | size              |
u32     | numcores          |
u32     | running           |
u32     | bspid             |
        +-------------------+

Dieses Tag existiert, wenn die Anweisung multicore angegeben wurde. numcores enthält die Anzahl der CPU-Kerne im System, running ist die Anzahl der Kerne, die erfolgreich initialisiert wurden und denselben Kernel parallel ausführen. Das bspid enthält die Kennung des BSP-Kerns (lAPIC-ID auf x86), sodass Kernel APs unterscheiden und auf diesen einen anderen Code ausführen können. Alle APs haben ihren eigenen Stapel und oben auf dem Stapel befindet sich die ID des aktuellen Kerns.

Partitionskennungen

        +-------------------+
u32     | type = 258        |
u32     | size = 24 / 40    |
u128    | bootuuid          |
u128    | rootuuid          |
        +-------------------+

Dieses Tag enthält die eindeutigen Kennungsfelder in der GPT der Boot- und Root-Partitionen. Wenn beim Booten keine GUID-Partitionierungstabelle verwendet ist, dann wird bootuuid als 54524150-(Gerätecode)-(Partitionsnummer)-616F6F7400000000 generiert.

Speicherlayout

BIOS-Maschinen

Start Ende Beschreibung
0x0 0x400 Interrupt Vector Table (verwendbar, real-Modus IDT)
0x400 0x4FF BIOS Data Area (verwendbar)
0x4FF 0x500 BIOS-Startlaufwerkscode (höchstwahrscheinlich 0x80, verwendbar)
0x500 0x5A0 Synchronisationsdaten für SMP (verwendbar)
0x5A0 0x1000 Ausnahmehandler-Stack (verwendbar, nachdem Sie Ihr IDT eingerichtet haben)
0x1000 0x8000 Paging-Tabellen (verwendbar, nachdem Sie Ihre Paging-Tabellen eingerichtet haben)
0x8000 0x20000 Loader-Code und Daten (verwendbar, nachdem Sie Ihr IDT eingerichtet haben)
0x20000 0x40000 Konfiguration + Tags (verwendbar nach der MBI-Analyse)
0x40000 0x90000 plugin ids; Von oben nach unten: Kernel-Stack
0x90000 0x9A000 Nur Linux-Kernel: zero page + cmdline
0x9A000 0xA0000 Extended BIOS Data Area (besser nicht anfassen)
0xA0000 0xFFFFF VRAM und BIOS ROM (nicht verwendbar)
0x100000 x Kernel-Segmente, gefolgt von den Modulen, jede Seite ausgerichtet

UEFI-Maschinen

Niemand weiß. UEFI weist den Speicher nach Belieben zu. Erwarten Sie alles und jedes. Alle Bereiche werden in der Speicherzuordnung sicherlich als Typ = 1 (MULTIBOOT_MEMORY_AVAILABLE) und reserved = 2 (EfiLoaderData) aufgeführt, dies ist jedoch nicht exklusiv, auch andere Arten von Speicher könnten so aufgeführt werden (BSS des Boot-Managers zum Beispiel).

Raspberry Pi

Start Ende Beschreibung
0x0 0x500 Von der Firmware reserviert (besser nicht anfassen)
0x500 0x5A0 Synchronisationsdaten für SMP (verwendbar)
0x5A0 0x1000 Ausnahmehandler-Stack (verwendbar, nachdem Sie Ihr VBAR eingerichtet haben)
0x1000 0x9000 Paging-Tabellen (verwendbar, nachdem Sie Ihre Paging-Tabellen eingerichtet haben)
0x9000 0x20000 Loader-Code und Daten (verwendbar, nachdem Sie Ihr IDT eingerichtet haben)
0x20000 0x40000 Konfiguration + Tags (verwendbar nach der MBI-Analyse)
0x40000 0x80000 Firmware bereitgestellt FDT (dtb); Von oben nach unten: Kernel-Stack
0x100000 x Kernel-Segmente, gefolgt von den Modulen, jede Seite ausgerichtet

Die ersten paar Bytes sind für armstub reserviert. Nur der Kern 0 wurde gestartet. Um Anwendungsprozessoren zu starten, schreiben Sie die Adresse einer Funktion auf 0xE0 (Kern 1), 0xE8 (Kern 2), 0xF0 (Kern 3). Diese Adressen befinden sich in diesem Bereich. Dies ist irrelevant, wenn die Direktive multicore verwendet wird, dann führen alle Kerne den Kernel aus.

Obwohl das RPi von Haus aus nicht unterstützt wird, erhalten Sie dennoch ein altes ACPI-RSDP-Tag (Typ 14) mit gefälschten Tabellen. Die APIC-Tabelle wird verwendet, um dem Kernel die Anzahl der verfügbaren CPU-Kerne mitzuteilen. Die Adresse der Startfunktion wird im Feld RSD PTR -> RSDT -> APIC -> cpu[x].apic_id gespeichert (und die Kern-ID in cpu[x].acpi_id, wobei BSP immer cpu[0].acpi_id ist = 0 und cpu[0].apic_id = 0xD8. Achtung, acpi und apic sehen ziemlich ähnlich aus.

Wenn von der Firmware ein gültiger FDT-Blob übergeben wird oder eines der Module eine .dtb-, .gud- oder .aml-Datei ist, wird auch eine FADT-Tabelle (mit magischem FACP) hinzugefügt. In dieser Tabelle zeigt der DSDT-Zeiger (32 Bit, bei Offset 40) auf den bereitgestellten abgeflachten Gerätebaum-Blob.

Obwohl die Firmware keine Speicherzuordnungsfunktion bereitstellt, erhalten Sie dennoch auch ein Speicherzuordnungs-Tag (Typ 6), das den erkannten RAM und die MMIO-Region auflistet. Damit können Sie die Basisadresse des MMIO erkennen, die bei RPi3 und RPi4 unterschiedlich ist.