Eine bootfähige Zeitkapsel – das historische NixOS-Image unter der Lupe
Im zweiten Teil dieser Serie ging es vor allem um den Linux-Kernel. Ich hatte verschiedene Kernelgenerationen auf der Novena untersucht, Startprobleme verfolgt und schließlich mit Linux 6.18.49 einen Stand erreicht, bei dem nicht nur NixOS startete, sondern auch das interne Display funktionierte. Das war ein großer Schritt für ein Gerät, dessen ursprüngliche Software aus einer ganz anderen Zeit stammte.
Am Ende des zweiten Teils stand deshalb die Frage, ob das historische NixOS-Image mehr sein konnte als nur ein funktionierender Systemstand: Könnte es als Grundlage für ein neues, nachvollziehbar gebautes Novena-System dienen?
Eine SD-Karte, die startet, ist zunächst einmal ein Ergebnis. Sie sagt noch wenig darüber aus, welche Dateien aus welchen Quellen stammen, wie der Bootloader erzeugt wurde oder welche Einstellungen nötig waren. Im ungünstigsten Fall funktioniert sie nur deshalb, weil an irgendeiner Stelle eine alte Binärdatei mitkopiert wurde, deren Herkunft niemand mehr genau kennt.
Ich wollte nicht auf Dauer von einem solchen Fundstück abhängig sein. Gleichzeitig wäre es unklug gewesen, einen bekannten funktionierenden Stand beiseitezulegen. Unter den vorhandenen Systemen gab es nämlich ein älteres NixOS-Image, das die Novena bereits erfolgreich bis zur Anmeldung gebracht hatte. Es war keine Bauanleitung. Aber es war ein Ausgangspunkt, an dem sich neue Versuche messen ließen.
Also begann ich nicht mit der nächsten Änderung am Kernel, sondern mit einer Bestandsaufnahme. Was war auf diesem Image eigentlich enthalten? Und was davon brauchte die Novena, bevor Linux überhaupt die erste Meldung ausgeben konnte?
Die Karte als Ausgangspunkt
Am 3. September 2026 hielt ich die Untersuchung des historischen NixOS-Images in der Projektdokumentation fest. Die ersten Ergebnisse wirkten zunächst wenig spektakulär. Es gab eine FAT-Partition mit dem Label FIRMWARE und eine ext4-Partition namens NIXOS_SD.
Diese Trennung ergab Sinn. Die FAT-Partition stellte Dateien bereit, die der Bootloader laden konnte. Auf der zweiten Partition lag das eigentliche NixOS-System mit seinem Dateibaum und den im Nix-Store abgelegten Bestandteilen. Man konnte sich den Aufbau vereinfacht wie zwei aufeinanderfolgende Aufgaben vorstellen: Zuerst muss der Rechner Linux in Gang setzen. Danach muss Linux das System finden, das es ausführen soll.
Für die Analyse war es hilfreich, diese Aufgaben nicht miteinander zu vermischen. Wenn der Kernel gar nicht geladen wird, hilft es wenig, das Root-Dateisystem zu verändern. Wenn der Kernel läuft, aber seine Root-Partition nicht findet, liegt das Problem möglicherweise viel später im Startablauf. Genau solche Unterschiede waren bereits bei den früheren Kernelversuchen wichtig gewesen.
Auf der Firmware-Partition des historischen Images waren sechs Dateien dokumentiert:
boot.cmd
boot.scr
initrd.uimg
novena.dtb
u-boot-dtb.img
zImage
Die Liste ist kurz genug, um zunächst übersichtlich zu wirken. Hinter den Dateinamen verbergen sich aber sehr unterschiedliche Aufgaben.
zImage ist der komprimierte Linux-Kernel für die ARM‑Architektur. Die Datei novena.dtb enthält einen kompilierten Device Tree, also die Beschreibung wesentlicher Hardwareeigenschaften, die der Kernel für dieses Board benötigt. initrd.uimg stellt die frühe RAM-Umgebung bereit, die beim Übergang zum eigentlichen System eine Rolle spielt. Die beiden Dateien boot.cmd und boot.scr gehören zusammen: Das eine ist ein lesbares Bootskript, das andere seine für U-Boot vorbereitete Form.
Dann war da noch u-boot-dtb.img. Schon der Name deutete auf den Bootloader hin. Aber eine Datei auf einer Partition zu finden und zu wissen, dass sie beim Einschalten tatsächlich von dort geladen wird, sind zwei verschiedene Dinge. Diesen Unterschied musste ich im weiteren Verlauf immer wieder beachten.
An dieser Stelle hätte man versucht sein können, die sichtbaren Dateien auf eine neue FAT-Partition zu kopieren, das Root-Dateisystem daneben anzulegen und den ersten Bootversuch zu starten. Die Karte sah schließlich vollständig aus. Genau diese Vorstellung führte jedoch zur nächsten Untersuchung: Eine SD-Karte besteht nicht nur aus dem, was ein Dateimanager anzeigt.
Auch die Partitionsbezeichnungen waren wichtig, aber sie waren kein Selbstzweck. FIRMWARE und NIXOS_SD halfen dabei, die Bestandteile des Images zuzuordnen. Entscheidend war am Ende, dass die Bootbefehle, die Kernelparameter und die tatsächlich vorhandenen Dateisysteme zueinander passten. Ein richtig benanntes Dateisystem nützt wenig, wenn der Kernel an der falschen Stelle danach sucht.
Ich hatte damit einen ersten Überblick, aber noch keine Erklärung für den vollständigen Startweg. Um die zu finden, musste ich den Blick von den Partitionen lösen und das Medium als Ganzes betrachten.
Was vor der ersten Partition lag
Bei der Untersuchung des historischen Images fanden sich auch im Bereich vor der ersten Partition Bootloader-Daten. Sie gehörten weder zum FAT-Dateisystem noch zum ext4-Root-Dateisystem. In einer gewöhnlichen Dateiliste wären sie deshalb nicht aufgetaucht.
Das war ein entscheidender Fund. Wer nur die Dateien zweier Partitionen kopiert, übernimmt nicht automatisch die Daten in den davorliegenden Sektoren. Eine neue SD-Karte kann dann auf den ersten Blick genauso aussehen wie die funktionierende Referenz und trotzdem schon vor dem Start von Linux scheitern.
Warum ist dieser Bereich bei der Novena so wichtig? Das Board verwendet einen i.MX6-Prozessor. Nach dem Einschalten steht noch kein Linux zur Verfügung, das bequem Dateien lesen oder Treiber laden könnte. Der Prozessor beginnt mit einem sehr frühen Startmechanismus. Von dort aus muss die weitere Software in einer Reihenfolge geladen werden, die zur Hardware und zum gewählten Bootmedium passt.
Eine zentrale Rolle spielt der Secondary Program Loader, kurz SPL. Er übernimmt frühe Aufgaben, zu denen je nach Konfiguration auch die Vorbereitung des Arbeitsspeichers gehört. Erst wenn diese Voraussetzungen geschaffen sind, kann das eigentliche U-Boot seine Arbeit aufnehmen. U-Boot lädt anschließend die Komponenten, die Linux benötigt, und übergibt die Kontrolle an den Kernel.
Diese Reihenfolge klingt selbstverständlich, solange alles funktioniert. Sobald der Start aber vor der ersten Kernelmeldung stehen bleibt, wird sie zur eigentlichen Diagnosefrage: Hat der Prozessor den frühen Bootcode gefunden? Ist der SPL gestartet? Konnte er die nächste Stufe laden? Hat U-Boot den Kernel überhaupt erreicht?
Bei der historischen NixOS-Referenz wurde eine SPL-Kennung U-Boot SPL 2020.07 festgestellt. Auch die Datei u-boot-dtb.img identifizierte sich als U-Boot 2020.07 für die Novena. Das lieferte eine wichtige Zuordnung zu einer konkreten Bootloader-Generation. Es bewies aber nicht allein, dass jede gefundene Datei bei jedem Start von genau dieser Position geladen wurde. Die tatsächliche Bootreihenfolge muss durch den jeweiligen Bootpfad und seine Beobachtungen belegt werden.
Die Referenz war damit mehr als eine Sammlung historischer Binärdateien. Sie zeigte, welche Generation der frühen Software in einem funktionierenden Novena-Aufbau vorkam. Für spätere Versuche war das ein wertvoller Vergleich, ohne dass ich U-Boot 2020.07 deshalb zum endgültigen Entwicklungsziel erklären musste.
Auch das Bootskript gab einen konkreten Einblick. Für das historische Image waren folgende Befehle dokumentiert:
fatload mmc 1:1 0x12000000 zImage
fatload mmc 1:1 0x13000000 initrd.uimg
fatload mmc 1:1 0x11ff0000 novena.dtb
bootz 0x12000000 0x13000000 0x11ff0000
Die ersten drei Zeilen laden Kernel, initrd und Device Tree von der FAT-Partition an bestimmte Adressen im Arbeitsspeicher. Die letzte Zeile startet den Kernel mit diesen Bestandteilen. Das Kommando bootz ist dabei kein allgemeines Synonym für „Computer einschalten“, sondern der konkrete U-Boot-Befehl zum Start eines ARM-Linux-zImage.
Die Zahlen in den Befehlen sind nicht bloße Dekoration. Sie beschreiben, wo die geladenen Daten im Speicher liegen sollen. Ändert man die Ladeadressen, muss weiterhin sichergestellt sein, dass die Komponenten nicht unerwünscht miteinander oder mit anderen benötigten Speicherbereichen kollidieren. Ebenso muss die Reihenfolge stimmen: Ein Startkommando hilft nicht, wenn eine der Dateien zuvor nicht erfolgreich geladen wurde.
Zum vollständigen historischen Bootpfad gehörte außerdem eine Kernel-Kommandozeile. Sie verwies auf einen konkreten NixOS-Systemstand im Nix-Store und auf dessen Initialisierungsprogramm. Das machte einen weiteren Zusammenhang sichtbar: Der Kernel war nicht unabhängig von dem System, das er starten sollte. Die Bootparameter verbanden die frühe Bootumgebung mit einer ganz bestimmten NixOS-Installation.
Spätestens jetzt wurde mir klar, warum die Untersuchung der Karte so wichtig war. Ein bootfähiges Image ist nicht einfach eine FAT-Partition, ein Linux-Kernel und irgendein Root-Dateisystem. Es ist eine Kette von Übergaben, bei der jede Stufe die nächste finden und korrekt vorbereiten muss.
Das erklärte auch, weshalb manche früheren Fehlermeldungen so aufschlussreich gewesen waren. Ein Kernel, der bereits eine Meldung über ein nicht gefundenes Root-Dateisystem ausgibt, hat einen ganz anderen Punkt erreicht als ein System, bei dem nicht einmal der SPL sichtbar wird. Ein Bootfehler ist also nicht nur ein Misserfolg. Er verrät, wie weit die Kette bereits funktioniert.
Vom Fundstück zum eigenen Build
Nach dieser Untersuchung war mein Ziel genauer gefasst. Ich wollte die historische Karte nicht einfach vervielfältigen. Ich wollte verstehen, welche Bestandteile notwendig waren, woher sie kamen und wie sich daraus ein eigenes NixOS-Image erzeugen ließ.
Dafür stand mir die Foobox zur Verfügung, mein Entwicklungsrechner mit x86_64-Prozessor. Die Novena selbst verwendet dagegen ARMv7. Der Rechner, auf dem die Software gebaut wird, und der Rechner, auf dem sie später laufen soll, sprechen also nicht dieselbe Prozessorarchitektur. Das ist bei der Entwicklung für eingebettete Systeme üblich, macht aber die Unterscheidung zwischen Build-Erfolg und Hardware-Erfolg besonders wichtig.
NixOS bot dafür einen interessanten Ansatz. Anstatt das Zielsystem ausschließlich durch manuelle Installationsschritte zusammenzustellen, konnte ich Konfiguration und Bauvorgang als Dateien festhalten. Vorhandene Novena-spezifische Linux- und NixOS-Projekte lieferten dabei wichtige Anhaltspunkte. Die Arbeit bestand nicht darin, ein beliebiges ARM-Image zu erzeugen, sondern die Besonderheiten dieses Boards mit einem aktuellen Systemstand zusammenzubringen.
Für das neue Image musste mehr zusammenpassen als nur der Linux-Kernel. Die Architektur des Benutzerraums musste stimmen. Der Device Tree musste zur Novena passen. Die frühe RAM-Umgebung musste den Übergang zum Root-Dateisystem ermöglichen. Die Firmware-Partition brauchte die Dateien, die das verwendete U-Boot erwartete. Und der Datenträger musste so aufgebaut sein, dass die frühe Bootstufe ihren Platz fand.
Das historische Image war bei all diesen Fragen ein Vergleichsmaßstab. Es war aber keine Garantie dafür, dass sich seine Bestandteile unverändert in einen modernen Build übertragen ließen. Gerade bei Kernel und Device Tree musste ich unterscheiden, was zum historischen Stand gehörte und was für Linux 6.18.49 angepasst werden musste.
In den Tagen nach der Bestandsaufnahme entstand ein neuer NixOS-Buildpfad. Der verwendete Kernel war Linux 6.18.49. Die Projektaufzeichnungen nennen für diese Entwicklungsphase unter anderem Anpassungen am IT6251-Displaypfad und am internen Panel. Diese Arbeiten gehörten zur Vorbereitung eines Systems, das nicht nur irgendwie bis zum Login kommen, sondern die vorhandene Hardware sinnvoll nutzen sollte.
Am 7. September 2026 war der Build erfolgreich abgeschlossen. Die Foobox hatte eine vollständige Image-Datei erzeugt. Sie war exakt 2.581.291.008 Byte groß. Auch die SHA-256-Prüfsumme wurde festgehalten:
5e65bfa6b7c599bdf507c2f1957c99136255e74eff01dec0dfb0bf8fb31ab94b
Solche Angaben wirken in einer Erzählung vielleicht etwas trocken. Für die Entwicklung waren sie aber entscheidend. Mit der Prüfsumme ließ sich ein bestimmtes Artefakt wiedererkennen. Ein Dateiname allein hätte dafür nicht genügt: Er kann mehrfach vergeben werden, und sein Inhalt kann sich ändern. Die Prüfsumme half, zwischen „einem Image mit diesem Namen“ und „genau diesem gebauten Image“ zu unterscheiden.
Trotzdem war das zunächst nur ein Erfolg auf der Foobox. Ein Build mit Exit-Code null sagt aus, dass der Bauvorgang abgeschlossen wurde. Er sagt nicht, dass der i.MX6 den Bootloader findet, dass U-Boot die Dateien korrekt lädt oder Linux anschließend die Root-Partition einbinden kann.
Für das Testmedium waren eine FAT-Partition FIRMWARE mit 128 MiB und eine ext4-Partition NIXOS_SD dokumentiert. Die Partitionierung entsprach damit dem grundsätzlichen Aufbau, den ich an der historischen Referenz untersucht hatte. Auf der Novena würde das externe Medium unter anderen Gerätenamen erscheinen als am Entwicklungsrechner. Auch das musste man im Blick behalten: Ein Gerätename wie /dev/sda beschreibt zunächst die momentane Sicht des jeweiligen Linux-Systems und ist keine dauerhafte Identität einer SD-Karte.
Beim Schreiben eines Images ist dieser Unterschied besonders wichtig. Eine Verwechslung des Zielgeräts kann andere Datenträger überschreiben. Deshalb gehörten die Kontrolle des Testmediums, die Sicherung bekannter funktionierender Stände und die Zuordnung der Artefakte zum eigentlichen Entwicklungsprozess. Sie waren nicht bloß nachträgliche Verwaltungsarbeit.
Auch die Aufzeichnungen selbst hatten Grenzen. Nicht jeder frühe Zwischenversuch lässt sich heute eindeutig einer bestimmten Karte und einer bestimmten Image-Datei zuordnen. Ich möchte daraus keine glatte Geschichte machen, in der angeblich jeder Versuch unmittelbar auf dem vorherigen aufbaute. Die dokumentierten Meilensteine lassen sich benennen; dazwischen muss man dort vorsichtig bleiben, wo die Belege nicht ausreichen.
Ein besonders wichtiger Punkt ist allerdings ausdrücklich gesichert: Die spätere Golden-Build-Dokumentation ordnet das am 7. September erzeugte Image dem erfolgreichen Hardwaretest vom 12. September zu. Dieser Zusammenhang ist damit mehr als eine bloße Vermutung. Zugleich bleibt die genaue Herkunft einzelner gesicherter Device-Tree-Zwischenstände eine eigene Frage, die sich nicht allein aus dem Image-Dateinamen beantworten lässt.
Damit war der Weg frei für den entscheidenden Vergleich zwischen dem, was auf dem Entwicklungsrechner fertig geworden war, und dem, was die Novena tatsächlich ausführte.
Warum die Zeitkapsel wichtig blieb
Am 12. September 2026 kam der entscheidende Nachweis auf der echten Hardware. Das NixOS-System mit Linux 6.18.49 startete vollständig. Der Bootpfad erreichte nicht nur den Kernel, sondern auch die frühen NixOS-Startphasen, das Root-Dateisystem und schließlich die reguläre Anmeldung.
Besonders wichtig war für mich das interne Display. Es genügte nicht, dass die serielle Konsole einen erfolgreichen Start meldete. Die Novena besitzt ein eigenes Display, dessen Ansteuerung mit dem modernen Kernel zusätzliche Arbeit erfordert hatte. Im Hardwareprotokoll waren die Linux-seitige Versorgung und Erkennung des IT6251, die Initialisierung und das DisplayPort-Link-Training dokumentiert. Am Ende stand eine stabile Ausgabe mit 1920 × 1080 Bildpunkten.
Damit waren mehrere bis dahin getrennte Fragen auf einmal beantwortet. Der Kernel konnte auf der realen Novena laufen. NixOS konnte seine Startphasen durchlaufen. Das Root-Dateisystem war erreichbar. Und der Displaypfad funktionierte zumindest in diesem dokumentierten Teststand bis zur sichtbaren Ausgabe.
Das war ein echter Erfolg, aber kein Freibrief für die gesamte Hardware. Ein erfolgreicher Displaytest sagt noch nichts Abschließendes über Audio, alle Eingabegeräte oder das Verhalten bei vielen aufeinanderfolgenden Kaltstarts aus. Auch aus einem einzelnen erfolgreichen Boot folgt nicht automatisch, dass jeder spätere Build denselben Zustand erreicht. Für solche Aussagen braucht es jeweils eigene Prüfungen.
Gerade deshalb war es sinnvoll, den funktionierenden Stand als Referenz zu sichern. Die Projektunterlagen beschreiben einen Golden Build und trennen dabei zwischen der gesicherten Image-Datei, dem zugehörigen Dokumentations- und Git-Stand sowie einzelnen Device-Tree-Artefakten. Diese Unterscheidung ist wichtig: Ein gesicherter Git-Commit beweist nicht automatisch, dass jede danebenliegende Binärdatei exakt aus diesem Commit gebaut wurde.
Für mich war das eine Fortsetzung derselben Erkenntnis, die bereits bei der historischen SD-Karte begonnen hatte. Nur weil ein System funktioniert, ist seine Herkunft noch nicht vollständig erklärt. Und nur weil eine Konfiguration sauber versioniert ist, muss nicht jedes bereits vorhandene Binärartefakt aus genau diesem Quellenstand stammen.
Die historische NixOS-Karte hatte gezeigt, wie ein funktionierender Startweg aussehen konnte. Der eigene Build und der Hardwaretest vom September zeigten, dass sich mit aktuellen Komponenten wieder ein funktionierendes System erreichen ließ. Dazwischen lag aber eine Menge Arbeit, die sich nicht auf das Kopieren einiger Dateien reduzieren ließ.
Mit universellem Novena-SD-Image meinte ich deshalb nie ein Image für beliebige ARM-Rechner. Gemeint war ein nachvollziehbar erzeugtes System für die Novena, bei dem die benötigten Komponenten zusammenpassen und dessen Entstehung nicht an einer einzigen zufällig erhaltenen historischen SD-Karte hängt.
Dazu gehörte auch, nicht jede historische Eigenheit sofort durch eine vermeintlich modernere Standardlösung zu ersetzen. Eine Besonderheit kann ein unnötiger Altbestand sein. Sie kann aber genauso gut eine Voraussetzung dafür sein, dass genau diese Hardware startet. Den Unterschied findet man nicht durch Raten heraus, sondern durch Quellen, Vergleiche und überprüfbare Tests.
Am Anfang hatte ich gefragt, ob eine funktionierende SD-Karte als Bauanleitung dienen kann. Die Antwort war inzwischen klarer: nicht unmittelbar. Eine fertige Karte verrät nicht von selbst, wie sie entstanden ist. Aber sie kann eine hervorragende technische Referenz sein, wenn man auch die unsichtbaren Bereiche untersucht und zwischen beobachteten Eigenschaften und vermuteten Abläufen unterscheidet.
Der Erfolg vom 12. September war deshalb kein Schlusspunkt, sondern ein neuer Ausgangspunkt. Linux und NixOS liefen auf der Novena, das interne Display funktionierte. Was weiterhin genauer verstanden und aus eigenen Quellen aufgebaut werden sollte, war der früheste Teil der Startkette: der Weg vom Einschalten über SPL und U-Boot bis zur Übergabe an Linux.
Dort lagen die nächsten Fragen. Wie wird der Arbeitsspeicher vorbereitet? Woher weiß der Prozessor, welchen Bootcode er laden soll? Welche Bestandteile stammen aus historischen Novena-Anpassungen, und welche lassen sich mit einem neueren U-Boot ersetzen?
Wie baut man einen eigenen, nachvollziehbaren Bootpfad, der nicht nur auf der Foobox entsteht, sondern auf der realen Novena zuverlässig bis zum Kernel führt?
Hinweis zur Entstehung dieses Artikels: Bei der technischen Arbeit nutze ich ChatGPT zur Analyse von Quellcode und Bootlogs, zur Strukturierung von Untersuchungen und zur Dokumentation. ChatGPT unterstützt mich außerdem beim Gliedern und Formulieren dieser Artikelserie. Die Arbeiten an der realen Novena und die beschriebenen Hardwaretests führe ich selbst durch. Technische Aussagen gleiche ich, soweit möglich, mit den Projektaufzeichnungen und Originalquellen ab.
Quellen und weiterführende Links
- Novena-Projektseite: https://www.kosagi.com/w/index.php?title=Novena_Main_Page
- Novena-spezifischer Linux-Kernel: https://github.com/novena-next/linux
- Novena-NixOS-Projekt: https://github.com/novena-next/nixos-novena
- U-Boot-Dokumentation zu: https://docs.u-boot.org/en/v2022.07/usage/cmd/bootz.html
- Linux-Kernel-Dokumentation zu initrd: https://docs.kernel.org/admin-guide/initrd.html
- Eigene Projektaufzeichnungen:
KERNEL-TEST-HISTORY.md,TEST-LOG.md,IMAGE-LAYOUT.md,GOLDEN-BUILD.mdund die dokumentierten Image-Builds und Hardwaretests vom 3. bis 12. September 2026. Die separat untersuchten historischen Novena-USB-Medien sind nicht mit dem NixOS-Referenzimage gleichzusetzen.
Quellen:
**Quellen und weiterführende Informationen**
- Novena-Projekt und technische Dokumentation (Kosagi): https://www.kosagi.com/w/index.php?title=Novena_Main_Page
- Novena-spezifischer Linux-Kernel: https://github.com/novena-next/linux
- NixOS für die Novena: https://github.com/novena-next/nixos-novena
- U-Boot-Dokumentation (`bootz`): https://docs.u-boot.org/en/v2022.07/usage/cmd/bootz.html
- Linux-Kernel-Dokumentation (`initrd`): https://docs.kernel.org/admin-guide/initrd.html
**Eigene Quellen:** Projektdokumentation und technische Versuchsprotokolle zur Novena, insbesondere `KERNEL-TEST-HISTORY.md`, `TEST-LOG.md`, `IMAGE-LAYOUT.md` und `GOLDEN-BUILD.md`, einschließlich der dokumentierten Build- und Hardwaretests vom 3. bis 12. September 2026.
**KI-Unterstützung:** ChatGPT wurde zur Auswertung technischer Informationen, zur Strukturierung der Dokumentation und zur sprachlichen Ausarbeitung des Artikels eingesetzt. Die praktischen Arbeiten und Hardwaretests wurden vom Autor selbst durchgeführt.
