Inhaltsverzeichnis

Firmware selber bauen

Bild: Freifunk München Logo

Vorwort

Auf dieser Seite geht es darum, wie man selber die Freifunk-Firmware kompilieren und Firmware-Images erzeugen kann. Als normaler Freifunk-Nutzer oder Knotenbetreiber gibt es keinen Grund das zu tun, man kann einfach die bereitgestellte Firmware benutzen. Aber wenn man helfen will Fehler in der Firmware zu beheben, neue Geräte zu unterstützen oder sich dafür interessiert, wie das eigentlich alles funktioniert, dann ist man hier richtig.

Benötigt wird ein ausreichend schneller Rechner (wenigstens Intel i5 oder Ryzen 5 Prozessor) mit einem aktuellen Linux entweder nativ oder als virtuelle Maschine und 20 GB Platz auf der Festplatte, dann kann es losgehen. Je tiefer man einsteigen will, umso mehr Kenntnisse braucht man in Linux, Shell, C, Lua, sowie allgmein Netzwerktechnik und Netzwerkprotokollen.

Schnelleinstieg

Das hier sind ohne viel Erklärung die Schritte aufgelistet um einmal die Quelltexte herunterzuladen und ein Firmware-Image zu erzeugen. Weiter unten wird dann genauer erklärt wie alles aufgebaut ist und zusammen spielt. So wie es hier steht ist es getestet auf Ubuntu 20.04 Desktop, sollte aber genauso auf anderen Linux-Distributionen funktionieren.

Git installieren:

sudo apt-get update
sudo apt-get install -y git

Git-Repository klonen:

git clone https://github.com/freifunkMUC/site-ffm

Ins site-ffm Verzeichnis wechseln

cd site-ffm

Dependencies installieren:

./scripts/install_build_dependencies.sh

Firmware-Build starten für die Plattform „x86-64“

make GLUON_TARGETS="x86-64"

Jetzt heisst es etwas Geduld aufbringen. Je nachdem wie schnell die Internet-Verbindung und der Rechner ist, dauert das Ganze etwa zwei Stunden, bis ein Firmware-Image herausfällt. Man findet es dann im Unterverzeichnis „output“.

Überblick

Natürlich kann die Freifunk-Community in München nicht selber eigene Software für so viele verschiedene Routermodelle schreiben, sondern greift auf bestehende Opensource-Projekte zurück, die entsprechend den Anforderungen konfiguriert, kombiniert und angepasst werden, um zu einer Firmware zu kommen, die unseren Bedürfnissen entpricht.

Die Grundlage der Firmware ist OpenWrt, eine Linux-Distribution um die Standardfirmware von Endkunden-Routern zu ersetzen. Diese wird von Gluon erweitert und konfiguriert, so dass sie nicht mehr als normaler Heimnetzrouter funktioniert, sondern als Freifunk-Mesh-Router. Freifunk München wiederum sucht aus, für welche Router Firmware gebaut werden soll, welche Funktionen von Gluon aktiviert sind und hat zusätzliche Pakete geschrieben, um neue Funktionen hinzufügen.

OpenWrt

OpenWrt Dokumentation OpenWrt Source Code

OpenWrt stellt alternative Router-Firmware für eine große Zahl von Endkunden-Routern (z.B. von D-Link, Netgear, TP-Link, AVM, Unifi) basierend auf Linux zur Verfügung. Dabei ist der Funktionsumfang von OpenWrt in der Regel größer als der der Originalfirmware und es gibt Updates für Modelle, die beim Hersteller schon aus der Wartung sind.

Liste unterstützter Geräte der aktuellen Version 21.02

Da es sich um eine Linux-Distribution handelt ist eine große Menge Software-Pakete verfügbar, der auf der Geräten installiert werden kann. Es gibt einen Paketmanager namens „opkg“ mit dem Software aus dem Repository installiert werden kann.

OpenWrt Pakete

Der OpenWrt-Build ist umfangreich und komplex, aufgrund der Unterstützung vieler verschiedener Hardware-Plattformen. Da der Build in der Regel auf einem x86-64-System läuft, muss zunächst für jede Plattform eine entsprechende Cross-Compile-Toolchain aufgebaut werden, mit der dann der Linux-Kernel, das Userland und schliesslich die OpenWrt-Pakete für die jeweilige Plattform gebaut werden können.

Gluon

Gluon Dokumentation Gluon Source Code

Gluon wird von vielen Freifunk-Communities genutzt. Es bietet genug Funktionalität in der Grundausstattung, um von kleinen Communities ohne viel Anpassung eingesetzt werden zu können, aber auch genug Flexibilität um eigene Komponenten einzubinden (wie zum Beispiel die Verwendung des Wireguard-Tunnels beim Freifunk München). Gluon unterstützt nur eine Teilmenge der Routermodelle, die für den Einsatz im Freifunk zweckmässig sind und getestet wurden.

Unterstützte Geräte v2021.1.1

Der Gluon-Build funktioniert so, dass zunächst die Git-Repositories von OpenWrt und der zusätzlichen Gluon-spezifischen Pakete geladen werden. Dann werden Patches auf diese Projekte angewendet, um Fehler zu beheben, die im Upstream noch nicht gefixed sind, oder zusätzliche Features zu implementieren, die nicht über Pakete abgebildet werden können. Der OpenWrt-Build wird so konfiguriert, dass zum Beispiel das OpenWrt-UI LuCi weggelassen und durch das Gluon-UI ersetzt wird. Dann wird der OpenWrt-Build gestartet, um die Images zu bauen.

FFMUC

FFMUC Firmware Git Repository

Gluon sieht vor, dass die Konfiguration für einen bestimmten Freifunk-Standort in einem Ordner namens „site“ im Gluon-Build-Ordner angelegt wird. Da drin werden bestimmte Dateien, wie die „site.conf“ und „site.mk“, erwartet. In dieser Konfiguration sind zum Beispiel die Gateways eingetragen und für welche Geräte überhaupt Firmware gebaut werden soll.

Gluon site Dokumentation

Der FFMUC-Firmware-Build funktioniert nun wiederum so, dass erstmal das Gluon-Repository in den Ordner „gluon-build“ geladen wird. Dann wird ein Symlink gemacht von „site-ffm“ auf „site“ im „gluon-build“ Ordner, um die Konfiguration dort bereitzustellen. Auch wir bringen Patches mit, die auf Gluon angewendet werden, als auch eigene Pakete, die entsprechend der Datei „modules“ geladen und eingebunden werden.

FFMUC Pakete FFMUC Community Pakete

Dann starten wir den Gluon-Build um die für Freifunk München angepassten Firmware-Images zu bauen.

Branches & Tags

Es gibt im GitHub-Repository diverse Branches. Eine Übersicht und die Unterschiede der Branches sind im Artikel Branches & Tags beschrieben. Wenn man das erste Mal einen anderen Remote-Branch auschecken will, so muss man ihn explizit mit angeben:

git checkout -b stable origin/stable

Wenn man zwischen den Branches `stable` und `next` wechselt, so sollte man vorher „make clean“ machen, damit es nicht zu Komplikationen kommt.

Für jeden Release gibt es einen Tag im Git-Repository. Um einen bestimmten Stand nochmal zu bauen, muss man also einen Checkout auf den gewünschten Tag machen, das geht so:

git checkout -b release tags/v2022.10.5

Liste der Tags im GitHub

Build Parameter & Umgebungsvariablen

GLUON_TARGETS

Hier kann man ein oder mehrere Targets angeben, für die Images gebaut werden sollen. Zum Testen empfiehlt sich eine VM zu benutzen, in der man x86-64 Images laufen lassen kann. Wenn man Firmware für ein bestimmtes Gerät bauen will, so muss man erst herausfinden, in welchem Target es enthalten ist. Hier lohnt sich ein Blick auf der Liste der unterstützten Geräte von OpenWrt oder Gluon.

make GLUON_TARGETS="x86-64 ipq40xx-generic" 

JOBS

Man kann definieren, wieviele Build-Jobs parallel laufen sollen. Automatisch macht er so viele, wie Cores im Computer zur Verfügung stehen. Wenn man nach einem Build-Problem sucht, sollte man das auf „1“ setzen, damit das Build-Log lesbarer wird.

make GLUON_TARGETS="x86-64" JOBS="1" V=s 

GLUON_DEVICES

Erlaubt es Images nur für einzelne Geräte zu bauen. Den genauen Device-Namen findet man in der entsprechenden targets-Datei, als den ersten Parameter vom device()-Aufruf.

Gluon targets

Im unten stehenden Beispiel baut man nur das Image für den TP-Link WR841 v13, es können auch mehrere Devices und mehrere Targets angegeben werden.

make GLUON_TARGETS="ramips-mt76x8" GLUON_DEVICES="tp-link-tl-wr841n-v13"

WEITERE

Gluon bietet eine Menge Umgebungsvariablen an, mit denen man den Build weiter konfigurieren kann, die vollständige Liste findet sich in der Gluon-Dokumentation:

Dokumentation Gluon Make Variablen

Wenn man noch mehr Einfluss auf den Build nehmen will, so kann man den Gluon-Build direkt starten. Zuerst lässt man dafür „gluon-prepare“ laufen, um das Git-Repository zu klonen und die Patches einzuspielen. Im Gluon-Verzeichnis kann man dann alle Gluon-Build-Parameter verwenden.

make gluon-prepare
cd gluon-build
make GLUON_RELEASE="v2020.3.3.7-mybuild" GLUON_BRANCH="stable" GLUON_TARGET="x86-64" download all

GitHub Build

Weil der komplette Build von allen Firmware-Images sehr viel Zeit in Anspruch nimmt, werden die Builds der Freifunk-Images auf der GitHub-Infrastruktur gemacht. Die Konfiguration hierfür findet sich in

.github/workflows/firmware.yml

GitHub Action Syntax

Wenn man neue Geräte zum Build hinzufügen will, so sind diese neben dem Makefile hier zusätzlich einzutragen, damit sie auch im Release-Build gebaut werden.

Der GitHub-Build wird ausgelöst, wenn man einen neuen Tag auf das GitHub-Repository pushed. Das funktioniert auch, wenn es nicht das FFMUC-Repository selber ist, sondern ein eigener Fork davon. Wenn man nur mal etwas ausprobieren will, sollte man natürlich die Targets im firmware.yml entsprechend reduzieren und nicht immer für alle Plattformen bauen lassen.

git tag -a v2020.3.3.7 -m "Release v2020.3.3.7"
git push origin v2020.3.3.7

Neue Geräte

Die Motivation selber ein Firmware-Image zu bauen liegt oft darin, dass man ein Gerät hat, für das FFMUC keine Firmware anbietet. Da gibt es unterschiedliche Schwierigkeitsgrade, je nachdem wie weit der Support für diese Geräte in den zugrunde liegenden Frameworks schon vorhanden ist.

Kein OpenWrt Support

Als erstes ist zu prüfen, ob OpenWrt das Gerät schon unterstützt. Sollte dies nicht der Fall sein, sieht es schlecht aus. Ein neues Gerät in OpenWrt zu supporten ist aufwendig und verlangt tiefgehendes Wissen über den verwendeten SoC, den Boot-Prozess, weitere Hardware die darin verbaut ist. Hier heisst es warten, ob/wann eine Unterstützung in OpenWrt kommt. Leider gibt es viele beliebte FritzBox Geräte, für die es absehbar keine Unterstütung geben wird (z.B. 7390, 7490).

Kein Gluon Support

Wenn OpenWrt-Support vorhanden ist, aber kein Gluon-Support, dann sieht es schon etwas besser aus. Entweder ist das Gerät noch nicht vollständig unterstützt und deswegen absichtlich weggelassen oder es ist so exotisch, dass noch keiner danach verlangt hat. Man kann erstmal schauen, ob es vielleicht im „next“ Branch schon enthalten ist, also für das kommende Release geplant ist. Man kann auch händisch die entsprechende Targets-Datei in Gluon dafür ergänzen bzw. anlegen und hat eine reelle Chance, dass ein funktionierendes Image herauskommt.

master-Branch Targets next-Branch Targets

Kein FFMUC Support

Das sollte eigentlich gar nicht passieren - die Liste der FFMUC-Geräte ist generiert aus Gluon, mittels contrib/genpkglist.py . Sollte ein Gerät bei uns fehlen, so muss man das nachgenerieren und in die site.mk kopieren, dann ist die Liste wieder aktuell:

genpkglist.py FFMUC site.mk