Ich mache mal weiter im Thema ... den aufgebrachten Vorschlag/die Frage, ob es die Möglichkeit bzw. keine Automatisierung für die Installation über die Shell gibt, kann man auf zwei Wegen angehen/beantworten.
Einmal auf dem von Freetz, wobei sich das eben auch immer auf die
/var/install
von AVM stützt und dazu diese Datei aus einem originalen Firmware-Image (was nur per
tar
gepackt wurde und damit nach meiner Ansicht "mit Standard-Tools" zu zerlegen wäre - mithin auch nicht mehr unbedingt als "distribution as a whole" gelten würde) in das eigene, finale Image kopiert.
Auch hier wird es sicherlich keine Urheberrechtskonflikte geben, solange man das jeweils selbst macht (und dann muß man es erst recht nicht an die große Glocke hängen) - aber will man selbst Images zusammenstellen, die irgendwelche Veränderungen an der Box vornehmen (und keine originale AVM-Komponente enthalten, die nicht auch unter GPL-Bedingungen vertrieben werden darf), muß man ohnehin selbst "in die Tasten hauen" und sich ein Skript bauen, was die notwendigen Kommandos enthält, um den Inhalt solcher Images zu installieren. Das wäre die Alternative zur Nutzung des AVM-Skripts.
Das muß ja nicht mal immer ein Kernel und ein Dateisystem sein, was da in solch einem Image enthalten ist ... mit einem selbstsignierten Image kann man auch (vorausgesetzt, der öffentliche Schlüssel ist in der laufenden Firmware bekannt) solche Dinge wieder ausführen, wie sie in den früheren "Pseudo-Updates" erfolgten - ja, beim passenden Aufruf (wenn man sein Image als Update für Zubehör "tarnt", woraufhin die enthaltene
/var/install
anders aufgerufen wird) wird nicht mal die Firmware so weit "heruntergefahren", daß man um einen Neustart nur noch schwer herumkommt - mancher erinnert sich vielleicht noch an alte "Pseudo-Updates" zum Start eines Telnet-Daemons, die dann erst den Rest der Firmware wieder zum Laufen bringen mußten, der beim
prepare_fwupgrade
zuvor gestoppt wurde.
Der Nachteil an der Benutzung des AVM-Skripts ist es außerdem, daß dieses erst mal hingeht und die "Prüfsumme" für die enthaltenen Dateien mit derjenigen, die dort jeweils in den letzten acht Byte enthalten ist (vier Byte als Signatur, vier Byte mit dem Wert), vergleicht - ein etwas "archaisches" Vorgehen bei der Absicherung, daß die zu installierenden Dateien auch in Ordnung sind. Und nebenbei bemerkt auch der Grund, warum man beim Zusammenbau eines "in-memory images" zum Start einer Box aus dem RAM, die letzten acht Byte von Kernel und Dateisystem abschneiden muß, bevor man sie zum finalen Image zusammenfügt.
Aber schon aus der Tatsache, daß diese CRC32-Prüfsummen eben bei der Installation aus dem RAM gar nicht vorhanden sind und die Firmware trotzdem den Inhalt der "Partitionen" aus dem RAM direkt in die jeweiligen Ziele kopiert und da keine weiteren Prüfsummen berechnet und angehangen werden, kann man ja ersehen, daß diese am Ende gar nicht mehr benötigt werden - sie stellen eigentlich nur sicher, daß die jeweilige Datei "bis zum Ende" ausgepackt werden konnte und wenn es dabei tatsächlich Probleme geben sollte, müßte/würde das schon das zum Entpacken verwendete
tar
-Kommando bemerken und entsprechend an seinen Aufrufer melden.
Aber es ist nun mal, wie es ist ... auch Freetz packt letztlich diese AVM-Datei zur Installation nicht weiter an (sie wird nur 1:1 kopiert, von einer Ausnahme abgesehen, die aber in unserem Kontext keine Rolle spielt) und sorgt daher brav dafür, daß die Eingabedateien auch das erwartete Format haben - es berechnet die CRC32-Prüfsummen und hängt sie an die jeweilige Datei an (mit
tichksum
:
https://github.com/Freetz/freetz/tree/master/tools/make/tichksum-host/src).
Das kann man nun so machen, man muß es aber nicht. Daher findet sich bei mir in den vorkompilierten Programmen für alle Lebenslagen auch dieses Tool nicht - abgesehen davon, daß das eben auch mit "Standard-Tools" problemlos funktioniert:
Rich (BBCode):
peh@vidar:~> cd /home/FritzBox/FB7490/firmware/
peh@vidar:/home/FritzBox/FB7490/firmware> mkdir /tmp/demo_cksum
peh@vidar:/home/FritzBox/FB7490/firmware> tar -x -f FRITZ.Box_7490-07.19-79325-LabBETA.image -O ./var/tmp/kernel.image >/tmp/demo_cksum/kernel.bin
peh@vidar:/home/FritzBox/FB7490/firmware> tar -x -f FRITZ.Box_7490-07.19-79325-LabBETA.image -O ./var/tmp/filesystem.image >/tmp/demo_cksum/fs.bin
peh@vidar:/home/FritzBox/FB7490/firmware> cd /tmp/demo_cksum/
peh@vidar:/tmp/demo_cksum> dd if=kernel.bin of=kernel.raw bs=$(( $(stat -c %s kernel.bin) - 8 )) count=1 2>/dev/null
peh@vidar:/tmp/demo_cksum> dd if=fs.bin of=fs.raw bs=$(( $(stat -c %s fs.bin) - 8 )) count=1 2>/dev/null
peh@vidar:/tmp/demo_cksum> ls -l
total 65900
-rw-r--r-- 1 peh users 31047688 Jun 17 20:26 fs.bin
-rw-r--r-- 1 peh users 31047680 Jun 17 20:30 fs.raw
-rw-r--r-- 1 peh users 2687496 Jun 17 20:26 kernel.bin
-rw-r--r-- 1 peh users 2687488 Jun 17 20:30 kernel.raw
peh@vidar:/tmp/demo_cksum> hexdump -C kernel.bin | tail -n 3
*
00290200 23 de 53 c4 96 f7 c9 94 |#.S.....|
00290208
peh@vidar:/tmp/demo_cksum> hexdump -C fs.bin | tail -n 3
*
01d9c000 23 de 53 c4 14 4d d6 fd |#.S..M..|
01d9c008
Die grün markierten Bytes sind die Signatur für diese Art von Prüfsumme nach TI-"Standard" - sie wird immer im "little endian"-Format gespeichert, wo das höchstwertige Byte als letztes im Speicher (oder wo auch immer) steht.
Daher ist das in Wirklichkeit die hexadezimale Konstante 0xC453DE23 (dezimal 3293830691) - an ihr kann man auch automatisch erkennen, ob ein Image nun eine solche Prüfsumme am Ende hat oder nicht. In der
image2ram
(
https://github.com/PeterPawn/YourFritz/blob/master/eva_tools/image2ram) überprüfe ich das z.B., indem ich diese vier Byte (die 8 Byte vor dem Dateiende stehen) mit
base64
in eine Zeichenkette umwandeln lasse, die man dann mit dem "erwarteten Wert"
I95TxA==
für die "Signatur" vergleichen kann.
image2ram
ist auch eher Demo als ein komplettes Skript und dient ja genau dazu, die oben gezeigten Operationen für die
kernel.image
und die
filesystem.image
zu automatisieren - als da wären das Extrahieren aus dem TAR-File von AVM und das Abschneiden der Prüfsumme, aber nur, wenn sie auch wirklich vorhanden ist, auszuführen, wobei für die Ausgabe dann die "blanken" Dateien einfach hintereinander kopiert werden. Das ist also eigentlich die "Umkehroperation" für das Anbringen der TI-Prüfsummen, wobei nur eine einzelne Datei (eben das "in-memory image") ausgegeben wird.
Die oben rot markierten Byte sind dann die eigentliche Prüfsumme - das ist nichts anderes als das Ergebnis der Berechnung eines bekannten CRC32-Polynoms über den gesamten Inhalt der Datei (natürlich ohne die Signatur), wobei auch hier das Ergebnis wieder im LE-Format gespeichert wird. Das Kommando
cksum
verwendet genau dieses Polynom ebenfalls (
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/cksum.html):
Rich (BBCode):
peh@vidar:/tmp/demo_cksum> cksum kernel.raw
2496264086 2687488 kernel.raw
peh@vidar:/tmp/demo_cksum> printf "%#x\n" $(cksum kernel.raw | sed -e "s| .*||")
0x94c9f796
peh@vidar:/tmp/demo_cksum> printf "%#x\n" $(cksum fs.raw | sed -e "s| .*||")
0xfdd64d14
Wie man sieht, stimmen die Werte in Rot mit denen aus der oben gezeigten TI-Prüfsumme des "Originals" überein - die Reihenfolge der Bytes ist nur "gedreht" (weil die Anzeige halt das Byte mit der niedrigsten Wertigkeit als letztes darstellt, wie man das von Zahlen nun mal kennt).
Gesetzt den Fall, man will also mit dem eigenen (Dateisystem-)Image das AVM-Skript zur automatischen Installation verwenden, muß man jetzt irgendwie dafür sorgen, daß sowohl der Kernel als auch das Dateisystem (bei den UBI-Boxen ist das ja einfach nur das SquashFS-Image aus dem
mksquashfs
-Aufruf beim Einpacken) die passende Prüfsumme haben. Beim Kernel wird das (solange es der von AVM ist) meist bereits der Fall sein - man darf nur das
dd
-Kommando aus #5 dann natürlich nicht verwenden, denn das schneidet ja diese Prüfsumme erst ab.
An das eigene SquashFS-Image muß man sie dann eben irgendwie anhängen ... solange man das Programm aus der Freetz-Toolchain nicht für die verwendete Plattform vorliegen hat, muß man sich anders zu helfen wissen - das eigentliche Problem ist es am Ende, die berechnete Prüfsumme irgendwie in die passende binäre Darstellung zu bringen (eben das LE-Format), die man an die Datei anhängen kann.
Dazu bauen wir uns erst mal eine kleine Funktion, die eine gegebene Zahl in das passende Binärformat bringen kann und testen diese gleich mal mit der Signatur und der oben (grün) gezeigten Prüfsumme für den Kernel:
Rich (BBCode):
peh@vidar:/tmp/demo_cksum> le32() { v=$1; i=4; while [ $i -gt 0 ]; do i=$(( i - 1 )); b=$(( ( v >> ( ( 3 - i ) * 8 ) ) & 0xFF )); printf "%b" "$(printf '\\0%03o' "$b")"; done; }
peh@vidar:/tmp/demo_cksum> ( le32 3293830691; le32 2496264086 ) | hexdump -C
00000000 23 de 53 c4 96 f7 c9 94 |#.S.....|
00000008
Das sieht doch schon mal gut aus ... diese 8 Byte sind mit denen aus der "originalen" Signatur identisch und mit der Funktion haben wir jetzt auch die Möglichkeit, jede beliebige Zahl (solange sie in den Wertebereich paßt) in die passende Darstellung zu konvertieren. Daraus kann man natürlich auch gleich ein komplettes Skript bauen oder sich die Zeile als Shell-Funktion in seiner
.profile
speichern oder sie eben auch nur als "Einzeiler" irgendwo ablegen, wo man sie wiederfindet.
Am Ende sähe das z.B. so aus:
Rich (BBCode):
peh@vidar:/tmp/demo_cksum> ticksum() { le32() { v=$1; i=4; while [ $i -gt 0 ]; do i=$(( i - 1 )); b=$(( ( v >> ( ( 3 - i ) * 8 ) ) & 0xFF )); printf "%b" "$(printf '\\0%03o' "$b")"; done; }; cat "$1"; le32 3293830691; le32 $(cksum "$1" | sed -e "s| .*||"); }
peh@vidar:/tmp/demo_cksum> ticksum kernel.raw > kernel.new
peh@vidar:/tmp/demo_cksum> ticksum fs.raw > fs.new
peh@vidar:/tmp/demo_cksum> cmp kernel.bin kernel.new
peh@vidar:/tmp/demo_cksum> cmp fs.bin fs.new
Die Funktion
ticksum
nimmt also jetzt den Dateinamen als Parameter entgegen und gibt auf STDOUT (hier dann umgeleitet in eine Datei) die Datei mit der angehangenen Signatur aus - der Vergleich mit dem
cmp
zeigt, daß die originale Datei von AVM und die mit den "selbstberechneten" Prüfsummen (*.new) identisch sind im Anschluß.
Diese beiden Dateien packt man jetzt in eine Verzeichnisstruktur, die ein Unterverzeichnis
var
und darunter wieder eines mit dem Namen
tmp
enthält. Da man obendrein noch das AVM-Programm zum Überprüfen der Prüfsumme braucht und natürlich auch das AVM-Skript
/var/install
, ist es am einfachsten, man packt gleich das gesamte AVM-Image mittels
tar
aus auf der Box und ersetzt dann nur noch die AVM-Dateien durch die eigenen ... solange man den Kernel nicht ändert, wäre das also nur das eigene Dateisystem-Image.
Rich (BBCode):
~ # wget http://ftp.avm.de/fritzbox/fritzbox-7490/deutschland/fritz.os/FRITZ.Box_7490-07.12.image -O - -q | tar -x -C / -v
./var/
./var/tmp/
./var/tmp/filesystem.image
./var/tmp/kernel.image
./var/content
./var/version
./var/info.txt
./var/regelex
./var/chksum
./var/install
./var/signature
~ # ls -l /var/tmp/*.image /var/install /var/chksum
-r-xr-xr-x 1 root root 283980 Jul 3 2019 /var/chksum
-rwxr-xr-x 1 root root 36448 Jul 8 2019 /var/install
-rw-r--r-- 1 root root 29954056 Jul 8 2019 /var/tmp/filesystem.image
-rw-r--r-- 1 root root 2649096 Jul 8 2019 /var/tmp/kernel.image
~ # cp /var/media/ftp/own_filesystem.sqfs /var/tmp/filesystem.image
Anschließend ruft man
/var/install
auf und betet, daß alles gut gehen möge ... wobei hier auch schon fast nichts mehr schiefgehen kann. Die Fallstricke liegen i.d.R. davor, wenn AVM noch die (kryptographische) Signatur von Images prüft oder wenn es bei einer Box mit wenig RAM-Ausstattung durch den Aufruf von
prepare_fwupgrade
erst mal darum geht, Prozesse zu beenden und Platz im RAM für das Image zu schaffen.
Mittlerweile hat AVM auch einen Mechanismus für ein "SILENT_UPDATE" erfunden, dessen Funktion mir noch nicht ganz klar ist - der kam (in vollem Umfang) erst mit 07.19 (obwohl schon davor ein paar Vorbereitungen zu sehen waren) und ich habe den noch nicht "live" erleben und beobachten können. Zwar gab es wohl zwischendrin auch mal eine Inhouse-Version, die das getestet hat, aber da bin ich nicht so richtig schlau draus geworden ... vor allem nicht daraus, wann da die Gültigkeitsprüfungen genau ablaufen und ob die nun doppelt (einmal beim Download und einmal vor der (verzögerten) Installation) oder nur einmal ausgeführt werden.
Aber zurück zur
/var/install
... bei den meisten Modellen (mit Ausnahme der Puma6-Boxen) schreibt dieses Skript die Firmware gar nicht direkt in die passenden Partitionen - nein, sie prüft erst mal nur alles mögliche (u.a. eben die TI-Prüfsummen) und schreibt die zur eigentlichen Installation erforderlichen Kommandos in die Datei
/var/post_install
, die im Rahmen des (irgendwann später mal erfolgenden) Neustarts der FRITZ!Box dann die tatsächlichen Kopieroperationen ausführt. Man muß also nach dem Aufruf der
/var/install
die Box auch i.d.R. erst einmal neu starten, damit die geänderte Firmware auch tatsächlich installiert(!) wird (und das meint nicht nur, daß sie "benutzt" wird - vorher ist sie noch nicht in der passenden Flash-Partition angekommen).
Das mag ja alles für ein "unbeaufsichtigtes" Update ganz spannend und sinnvoll sein (wobei vieles in meinen Augen auch wieder "historisch gewachsen" ist) - aber es geht auch anders und so macht es halt "modfs" schon seit langem (auch wenn das VR9 ist) und ich habe an dieser Stelle eigentlich nie wirklich Klagen gehört, daß dieser Teil nicht funktioniert hätte. Daher ist dieser Weg (den ich trotzdem noch mal erläutern wollte, weil es eben auch der ist, den Freetz-Images nehmen) in meinen Augen auch viel zu kompliziert ... auch wenn AVM i.d.R. natürlich am besten weiß, wie welche Firmware auf welcher Box installiert wird, gibt es da nicht soo viele unterschiedliche Herangehensweisen bei AVM (zumindest nicht bei aktuellen Boxen) und so kann man das i.d.R. auch noch "von Hand" selbst machen oder sich eben ein passendes Shell-Skript dafür bauen.
===============================================
EDIT: Außerdem hat das Verwenden eines eigenen Skripts am Ende sogar noch einen deutlichen Vorteil ... das AVM-Skript installiert immer beides zusammen, den Kernel und das Dateisystem. Auch bei den Boxen, die den UBI-Layer verwenden, sind aber die Kernel-Partitionen "fest" im Flash verankert und verwenden gerade nicht diesen Layer, der ja die physischen Blöcke (PEB) von den "logischen" (LEB) entkoppelt. Während also beim Schreiben des Dateisystem-Images der UBI-Layer für das "wear leveling" sorgt (das ist das Verteilen von Löschzyklen über alle verfügbaren Blöcke, weil diese nur eine begrenzte Anzahl von Löschoperationen vertragen und besonders stark beanspruchte Blöcke dann sehr schnell den Geist aufgeben würden), gibt es das beim Beschreiben der Kernel-Partitionen nicht und jeder zusätzliche Löschzyklus beansprucht ALLE Blöcke in der betreffenden Partition. Solange man also denselben Kernel verwendet, der bereits (in der richtigen Partition wohlgemerkt, denn es gibt ja zwei) installiert ist, sollte man - wenn man das häufiger macht - ohnehin auf das erneute Schreiben des Kernel-Images verzichten - das spricht zusätzlich gegen die Verwendung des originalen AVM-Skripts und am Ende auch gegen die ständige Installation über den Start aus dem RAM, weil auch dabei immer beide "Teile" des Systems neu geschrieben werden, ungeachtet des bisherigen Inhalts.
===============================================
Geht man an diese Aufgabe mit der Idee heran, daß das Skript so viel "Sicherheit" wie möglich bieten soll, muß man natürlich auch entsprechende Tests in das Skript einbauen, damit der Benutzer so wenig Fehler wie möglich dabei machen kann ... das geht bei der Kontrolle des Formats für das Filesystem-Image los und endet bei der Überprüfung der Größe. Vieles von dem, was dieses Skript leisten sollte, macht aber auch das AVM-Skript für die Installation beim Start aus dem RAM (i.d.R.
E03-flash_update
bei UBI bzw.
/wrapper/sbin/flash_update
bei VR9 - wobei das ggf. ab 07.20 wieder anders aussieht) bereits ... nur daß dieses Skript halt keine Datei mit dem Image nimmt, sondern sich das Image aus der passenden "Partition" im Hauptspeicher (wohin man es ja per EVA geladen hat) erst einmal in eine Datei schreibt und diese dann flasht.
Wer sich dafür interessiert, kann also auch in dieser (Skript-)Datei nachsehen, wie eine solche Installation ablaufen müßte ... man muß dabei ja auch immer davon ausgehen, daß der Vorrat an verfügbaren Kommandos auf der Box (wo das ja dann laufen muß) schon stark eingeschränkt ist, solange man nicht selbst weitere Kommandos (z.B. mit der eigenen BusyBox) hinzugefügt hat.
Ich mache hier erst mal Schluß und widme mich mal dem Erstellen eines passenden Beispiels, das ich dann ins YourFritz-Repo stelle - ich muß ohnehin aufpassen, daß der Beitrag nicht die max. zulässige Zeichenzahl reißt und ich den hinterher erst wieder splitten muß.