Ein wichtiger Grund für das Erstellen angepasster und eigener Firmware Images ist der in vielen Geräeten mit 4MB knapp bemessene Flash Speicher. Die aktuellen Snapshots (trunk genannt) sind minimal. Sie haben keine Weboberfläche installiert. Eine Nachinstallation benötigt viel mehr von dem knappen Speicher, da die Dateien dort im Gegensatz zur Firmware, nicht komprimiert gespeichert werden.
Bei Geräten mit einem freien USB-Anschluss kann mit einem kleinen USB-Stick ein grösseres (root-)Dateisystem "darüber gelegt" werden. Wie man das macht, steht hier beschrieben: OpenWrt: Alternative Routersoftware
Für die digitalen Spiegelreflexkameras von Nikon und Canon gibt es eine leistungsstarke und preisgünstige Lösung für die Fernsteuerung per Smartphone oder Tablet: DslrDashboard auf TL-MR30. In diesem Artikel wird der dafür notwendige 'ddserver' als Paket in die Firmware integriert. Im verlinkten sind die fertigen Firmware Images zum Herunterladen angehängt.
In diesem Artikel werden zwei Methoden kurz anhand eines konkreten Beispieles beschrieben. Die erste und einfachere beschreibt, wie man aus den vorkompilierten Quellen eine angepasste Firmware erstellt. Die zweite Methode, die aufwändiger ist, kompiliert aus den Quellen den Linux Kernel und die Pakete selber. Diese wird benötigt, wenn externe Pakete für die aktuelle Firmware kompiliert und erstellt werden sollen. Anders ausgedrückt: Image Builder (erstellt aus fertigen Paketen das Firmware Image, OpenWrt buildroot erstellt die Firmware aus den Quelldateien.
Referenz: http://wiki.openwrt.org/doc/howto/obtain.firmware.generate
Quellen: http://downloads.openwrt.org/snapshots/trunk/ar71xx/
Im Heimverzeichnis wird ein Verzeichnis openwrt erstellt, in das das aktuelle ImageBuilder-Archiv herunter geladen wird. Als User, nicht als root (bei 'w get' muss das Leerzeichen entfernt werden wird ausgeführt:
cd ~; mkdir openwrt; cd openwrt w get http://downloads.openwrt.org/snapshots/trunk/ar71xx/OpenWrt-ImageBuilder-ar71xx_generic-for-linux-x86_64.tar.bz2 tar xvf OpenWrt-ImageBuilder-ar71xx_generic-for-linux-x86_64.tar.bz2 cd OpenWrt-ImageBuilder-ar71xx_generic-for-linux-x86_64/
Ein minimales Image, wie die Trunk-Version, erstellt man mit:
make image PROFILE=TLMR3040
Das ergibt:
ls -laR bin bin/ar71xx: total 29776 drwxrwxr-x. 2 jh jh 4096 21. Mär 12:55 . drwxrwxr-x. 3 jh jh 4096 21. Mär 12:51 .. -rw-rw-r--. 1 jh jh 1012 21. Mär 12:55 md5sums -rw-rw-r--. 1 jh jh 1966080 21. Mär 12:55 openwrt-ar71xx-generic-root.squashfs -rw-r--r--. 1 jh jh 1835012 21. Mär 12:55 openwrt-ar71xx-generic-root.squashfs-64k -rw-rw-r--. 1 jh jh 3932160 21. Mär 12:55 openwrt-ar71xx-generic-tl-mr3040-v1-squashfs-factory.bin -rw-rw-r--. 1 jh jh 2949124 21. Mär 12:55 openwrt-ar71xx-generic-tl-mr3040-v1-squashfs-sysupgrade.bin -rw-rw-r--. 1 jh jh 3932160 21. Mär 12:55 openwrt-ar71xx-generic-tl-mr3040-v2-squashfs-factory.bin -rw-rw-r--. 1 jh jh 2949124 21. Mär 12:55 openwrt-ar71xx-generic-tl-mr3040-v2-squashfs-sysupgrade.bin -rw-rw-r--. 1 jh jh 1490733 21. Mär 12:55 openwrt-ar71xx-generic-uImage-gzip.bin -rw-rw-r--. 1 jh jh 1079009 21. Mär 12:55 openwrt-ar71xx-generic-uImage-lzma.bin -rwxr-xr-x. 1 jh jh 3243348 21. Mär 12:55 openwrt-ar71xx-generic-vmlinux.bin -rwxr-xr-x. 1 jh jh 3309852 21. Mär 12:55 openwrt-ar71xx-generic-vmlinux.elf -rw-rw-r--. 1 jh jh 1507328 21. Mär 12:55 openwrt-ar71xx-generic-vmlinux.gz -rw-rw-r--. 1 jh jh 1114112 21. Mär 12:55 openwrt-ar71xx-generic-vmlinux.lzma -rwxr-xr-x. 1 jh jh 1150973 21. Mär 12:55 openwrt-ar71xx-generic-vmlinux-lzma.elf
Das Image …sysupgrade.bin ist dasjenige, das man verwendet, wenn OpenWrt bereits auf dem Router installiert ist.
Zum Vergleich das vorher herunter geladene trunk-Image. (Ein cmp ist nicht möglich.) Die beiden Versionen sind aufs Byte genau gleich gross.
-rw-r--r--. 1 jh jh 3932160 21. Mär 00:41 openwrt-ar71xx-generic-tl-mr3040-v2-squashfs-factory.bin
Diese Pakete sind in der trunk Version installiert:
echo $(opkg list_installed | awk '{ print $1 }')
base-files busybox dnsmasq dropbear firewall fstools hostapd-common ip6tables
iptables iw iwinfo jshn kernel kmod-ath kmod-ath9k kmod-ath9k-common kmod-cfg80211
kmod-crypto-aes kmod-crypto-arc4 kmod-crypto-core kmod-gpio-button-hotplug
kmod-ip6tables kmod-ipt-conntrack kmod-ipt-core kmod-ipt-nat kmod-ipt-nathelper
kmod-ipv6 kmod-leds-gpio kmod-ledtrig-default-on kmod-ledtrig-netdev kmod-ledtrig-timer
kmod-ledtrig-usbdev kmod-lib-crc-ccitt kmod-mac80211 kmod-nls-base kmod-ppp kmod-pppoe
kmod-pppox kmod-slhc kmod-usb-core kmod-usb-ohci kmod-usb2 libblobmsg-json libc libgcc
libip4tc libip6tc libiwinfo libjson-c libjson-script libnl-tiny libubox libubus libuci
libxtables mtd netifd odhcp6c odhcpd opkg ppp ppp-mod-pppoe procd swconfig uboot-envtools
ubox ubus ubusd uci wpad-mini
make image PROFILE=TLMR3040 PACKAGES='kmod-usb-storage kmod-scsi-core kmod-fs-vfat \ kmod-nls-iso8859-1 kmod-nls-iso8859-15 kmod-nls-cp437 kmod-nls-cp850 block-mount \ -ppp -ppp-mod-pppoe -kmod-ppp -kmod-pppoe -kmod-pppox -ppp \ -odhcp6c -odhcpd -kmod-ipv6 -ip6tables'
Das ist ungefähr der maximalen Speicherplatz, den man überhaupt einsparen kann:
df -h / Filesystem Size Used Available Use% Mounted on rootfs 1.2M 220.0K 996.0K 18% /
Luci nachträglich installiert in der Minimalversion benötigt 670K Platz auf dem root-fs
df -h / Filesystem Size Used Available Use% Mounted on rootfs 1.2M 888.0K 328.0K 73% /
Für die "Einbettung" im squash-fs, dem Flash-Image braucht es diese Pakete für eine vollständige Luci Installation:
luci-lib-sys liblua libuci-lua lua libubus-lua luci-lib-core luci-lib-nixio luci-sgi-cgi luci-lib-web luci-proto-core luci-i18n-english luci-mod-admin-core libiwinfo-lua luci-theme-base luci-theme-bootstrap luci-app-firewall luci-lib-ipkg luci-proto-ppp luci-mod-admin-full uhttpd uhttpd-mod-ubus luci
Das ergibt folgenden Befehl:
make image PROFILE=TLMR3040 PACKAGES='luci-lib-sys liblua libuci-lua lua libubus-lua luci-lib-core \ luci-lib-nixio luci-sgi-cgi luci-lib-web luci-proto-core luci-i18n-english luci-mod-admin-core libiwinfo-lua \ luci-theme-base luci-theme-bootstrap luci-theme-openwrt luci-app-firewall luci-lib-ipkg luci-proto-ppp \ luci-mod-admin-full uhttpd uhttpd-mod-ubus luci'
Nun ist luci im Image, installiert wird nun … sysupgrade.bin.
Tipp: Am einfachsten geht das, in dem man in der trunk Version luci installiert und dann via Webinterface das Update macht. Die Einstellungen bleiben erhalten.
PPP brauchen wir nicht, das spart einige Dutzend KB.
make image PROFILE=TLMR3040 PACKAGES='luci-lib-sys liblua libuci-lua lua \ libubus-lua luci-lib-core luci-lib-nixio luci-sgi-cgi luci-lib-web \ luci-proto-core luci-i18n-english luci-mod-admin-core libiwinfo-lua \ luci-theme-base luci-theme-bootstrap luci-theme-openwrt luci-app-firewall \ luci-lib-ipkg luci-proto-ppp luci-mod-admin-full uhttpd uhttpd-mod-ubus luci \ kmod-usb-storage kmod-scsi-core kmod-fs-vfat block-mount \ kmod-nls-iso8859-1 kmod-nls-cp437 kmod-nls-cp850 \ -ppp -ppp-mod-pppoe -kmod-ppp -kmod-pppoe -kmod-pppox -ppp'
Mit PPP (das man nur dann braucht, wenn man selber die Verbindung mit dem ISP herstellen will, manchmal für einzelne recht nützlich, aber hier nicht):
df -h / Filesystem Size Used Available Use% Mounted on rootfs 576.0K 220.0K 356.0K 38% /
Ohne PPP, ein rechter Gewinn:
df -h / Filesystem Size Used Available Use% Mounted on rootfs 704.0K 220.0K 484.0K 31% /
Brauchen wir IPv6? Nein, es geht noch ohne. ;-] Nun sind schon über 600K frei. Diese Pakete mit Minuszeichen versehen in obiger Befehlszeile: -odhcp6c -odhcpd -kmod-ipv6 -ip6tables
df -h / Filesystem Size Used Available Use% Mounted on rootfs 832.0K 224.0K 608.0K 27% /
Den Hardware-Schalter aktiviert man mit dem kernel-Modul: kmod-button-hotplug
Den Schalter kann man so benutzen: https://forum.openwrt.org/viewtopic.php?pid=189097#p189097 Ein angepassetes Script folgt hier irgendwann.
Die aktuelle Trunk-Version (ohne Weboberfläche) liess 816KB frei. Installiert man Luci und die USB-Pakete nach, verbleiben einem nur noch unter 100KB. Die angepasste Firmware lässt 608KB frei. Genug Platz für die Installation weiterer Pakete.
Referenz: http://wiki.openwrt.org/doc/howto/buildroot.exigence und http://wiki.openwrt.org/doc/devel/packages
Um ddserver (Kamera Fernsteuerung) als Paket für die aktuelle Trunk-Version zu erstellen, muss build-root installiert werden. Auf dem lokalen PC installiert man als root:
yum install git-core gcc-c++ ncurses zlib ncurses-devel zlib-devel subversion
Vollständig für Fedora 19 aus obigem Link ('w get' unten wie immer hier zusammenfügen):
yum install -y subversion binutils bzip2 gcc gcc-c++ gawk gettext flex \ ncurses-devel zlib-devel make patch unzip perl-ExtUtils-MakeMaker \ glibc glibc-devel glibc-static quilt ncurses-lib sed sdcc intltool \ sharutils bison w get
Dann folgt man der Anleitung http://wiki.openwrt.org/doc/howto/buildroot.exigence 1:1. Darum hier nicht mehr dazu.
(Das Verzeichnis ist package und nicht packages, wie im obigen Link angegeben)
Dieses Kapitel zeigt in Kürze, wie man ein Paket aus seine Quellen generiert. Im Prinzip wird hier zugleich die aktuelle trunk-Version erstellt. Aber eben nur diese. Es fehlen schlussendlich nicht nur einige nicht aktivierte Pakete und Kernelmodule, sondern alle Zusatzpakete. Darum verschmelzen wir die beiden Ansätze, die zu einem Flash-Image führen. 'Image Builder' liefert die vorkompilierten Pakete und fertigt die Flash-Images. 'Root Builder' stellt die Infrastruktur zum eigenen Erstellen von Paketen aus dem Quelltext dar. Mehr dazu unten.
Man holt sich die Quellen mit git.
git clone git://github.com/hubaiz/DslrDashboardServer package/DslrDashboardServer make menuconfig
Unter Multimedia DDServer anwählen, als Modul (M), nicht in den Kernel integrieren (*).
make
Das 'make' dauert seine Zeit, erst müssen alle Tools herunter geladen werden. Man könnte das Paket auch direkt kompilieren, jedoch müssen dann noch einige Einstellungeng gemacht werden. Darum gleich alles. (Man könnte sich wie beim Image Builder eine massgeschneiderte Image Firmware erstellen lassen). Nach langer Zeit, einigen Stunden auf dem etwas älteren Laptop, befindet sich das Paket dann in:
./openwrt/bin/ar71xx/packages/ddserver_0.2-11_ar71xx.ipk
und kann nun wie gewohnt installiert werden.
Immer noch auf dem lokalen PC kopiert man das Packet mittels scp auf den Router:
cd ./openwrt/bin/ar71xx/packages/ scp ddserver_0.2-11_ar71xx.ipk root@192.168.0.230:/tmp
Darauf hin einloggen im Router (ssh root@192.168.0.230 )
cd /tmp opkg update && opkg install ddserver_0.2-11_ar71xx.ipk
df -h / Filesystem Size Used Available Use% Mounted on rootfs 832.0K 580.0K 252.0K 70% /
Die Abhängigkeiten werden aufgelöst: libusb libpthread librt libstdcpp. Die letzteren Pakete kann man gleich beim Build Image angeben, libusb wird nachinstalliert.
df -h / Filesystem Size Used Available Use% Mounted on rootfs 640.0K 256.0K 384.0K 40% /
Die Quellen müssen nicht bei jedem Update der trunk-Version neu übertragen werden. Man wechselt ins Repository (Depot) und zieht sich die Updates. Für diesen Artikel gilt:
cd ~/openwrt/openwrt git pull (git merge origin)
Ein einfache Lösung, um schnell an fertige Firmware Images zu kommen, ist die "Symbiose" dieser beiden Methoden. Dazu wird das fertige Paket aus dem Buildroot-Verzeichnis in das richtige Verzeichnis des Image Builders kopiert. Dann fährt man wie oben fort. Auf dem lokalen PC:
cd ~/openwrt cp ./openwrt/bin/ar71xx/packages/ddserver_0.2-11_ar71xx.ipk \ OpenWrt-ImageBuilder-ar71xx_generic-for-linux-x86_64/packages/
Und schlussendlich ddserver bereits im squash-fs integriert. Zusätzliche Pakete im ddserver image zum erweiterten trunk image: hotplug2, kmod-usb-ohci, libusb-1.0, openssh-keygen, openssh-server (werden wohl nicht benötigt), uclibc, zlib (werden mit installiert).
Auf dem lokalen PC:
cd OpenWrt-ImageBuilder-ar71xx_generic-for-linux-x86_64 make image PROFILE=TLMR3040 PACKAGES='luci-lib-sys liblua libuci-lua lua libubus-lua \ luci-lib-core luci-lib-nixio luci-sgi-cgi luci-lib-web luci-proto-core luci-i18n-english \ luci-mod-admin-core libiwinfo-lua luci-theme-base luci-theme-openwrt luci-app-firewall \ luci-lib-ipkg luci-mod-admin-full uhttpd uhttpd-mod-ubus luci kmod-usb-storage \ kmod-scsi-core kmod-fs-vfat kmod-nls-iso8859-1 kmod-nls-cp437 kmod-nls-cp850 \ block-mount -ppp -ppp-mod-pppoe -kmod-ppp -kmod-pppoe -kmod-pppox -ppp \ -odhcp6c -odhcpd -kmod-ipv6 -ip6tables libpthread librt libstdcpp ddserver'
Das Image installieren. Nun zeigt sich:
df -h / Filesystem Size Used Available Use% Mounted on rootfs 640.0K 224.0K 416.0K 35% /
make image PROFILE=TLWDR4300 PACKAGES='luci-lib-sys liblua libuci-lua lua \
libubus-lua luci-lib-core luci-lib-nixio luci-sgi-cgi luci-lib-web \
luci-proto-core luci-i18n-english luci-mod-admin-core libiwinfo-lua \
luci-theme-base luci-theme-bootstrap luci-theme-openwrt luci-app-firewall \
luci-lib-ipkg luci-proto-ppp luci-mod-admin-full uhttpd uhttpd-mod-ubus luci \
kmod-usb-storage kmod-scsi-core kmod-fs-vfat block-mount kmod-fs-ext4 \
kmod-nls-iso8859-1 kmod-nls-cp437 kmod-nls-cp850 kmod-nls-iso8859-15 \
luci-app-qos luci-i18n-german luci-app-firewall luci-app-upnp luci-app-hd-idle \
e2fsprogs kmod-usb-storage-extras kmod-usb-ohci e2fsprogs'
make image PROFILE=TLMR3040 PACKAGES='luci-lib-sys liblua libuci-lua lua libubus-lua \
luci-lib-core luci-lib-nixio luci-sgi-cgi luci-lib-web luci-proto-core luci-i18n-english \
luci-mod-admin-core libiwinfo-lua luci-theme-base luci-theme-openwrt luci-app-firewall \
luci-lib-ipkg luci-mod-admin-full uhttpd uhttpd-mod-ubus luci kmod-usb-storage \
kmod-scsi-core kmod-fs-vfat kmod-nls-iso8859-1 kmod-nls-cp437 kmod-nls-cp850 \
block-mount -ppp -ppp-mod-pppoe -kmod-ppp -kmod-pppoe -kmod-pppox -ppp \
-odhcp6c -odhcpd -kmod-ipv6 -ip6tables libpthread librt libstdcpp ddserver kmod-button-hotplug'
make image PROFILE=TLWR841 PACKAGES='luci-lib-sys liblua libuci-lua lua \
libubus-lua luci-lib-core luci-lib-nixio luci-sgi-cgi luci-lib-web \
luci-proto-core luci-i18n-english luci-mod-admin-core libiwinfo-lua \
luci-theme-base luci-theme-bootstrap luci-theme-openwrt luci-app-firewall \
luci-lib-ipkg luci-proto-ppp luci-mod-admin-full uhttpd uhttpd-mod-ubus luci \
luci-app-qos luci-i18n-german luci-app-firewall'