====== Flashing La Fonera ======
In questa pagina trovate i miei appunti generici per aggiornare le immagini flash (il firmware) e in particolare per installare OpenWrt. Altri documenti migliori di questo:
* Wiki ufficiale di OpenWrt: **[[http://wiki.openwrt.org/toh/fon/fonera]]**
* Istruzioni per compilare OpenWrt: **[[http://wiki.ninux.org/moin.cgi/OpenWRTCompile|OpenWRTCompile]]**
===== La Fonera bricked =====
Si è deciso di installare OpenWrt perché la Fonera si è danneggiata e non si avvia più (in gergo: //bricked//). Il danno è accaduto installando e poi rimuovendo un pacchetto con **ipkg** (per la precisione il pacchetto **gpsd**): si è avuto un segmentation fault e da quel momento la Fonera non si è più riavviata. Dalla console seriale il boot si blocca con questi messaggi:
mini_fo_lookup: ERROR, meta data corruption detected.
mini_fo_d_delete: negative dentry passed.
mini_fo_d_release: no private data.
===== Tipi di filesystem =====
^ squashfs | Squashfs is a readonly filesystem, OpenWrt boots from this one. |
^ jffs2 | For writable support, OpenWrt creates a jffs2 partition and on bootup swaps to the jffs2 root. |
Un **filesystem di tipo JFFS2** generalmente viene montato da un device MTD, per montarlo da un file immagine si può usare questa procedura (Linux kernel 2.6):
# Associate a loop device with the regular file:
modprobe loop; sleep 1
losetup /dev/loop0 /path/mtdblock2.jffs2
# Load the MTD support and the emulation using a block device:
modprobe mtdblock
modprobe block2mtd block2mtd=/dev/loop0,256; sleep 1
# Load the filesystem support and mount it:
modprobe jffs2
mount -t jffs2 /dev/mtdblock0 /mnt
FIXME **I was unable to mount** the jffs image (rootfs1) downloaded from the Fonera, may be for an endianess problem? Check the **''jffs2dump''** command with a syntax like this:
jffs2dump -l -c -e
Magic bitmask is backwards at offset 0x00560000. Wrong endian filesystem?
The following code will undo the previous setup:
umount /mnt
modprobe -r jffs2
modprobe -r block2mtd
modprobe -r mtdblock
losetup --detach /dev/loop0
modprobe -r loop
===== Backup delle immagini flash =====
Se la Fonera non è //bricked// ed è accessibile via ssh, possiamo fare una copia delle immagini flash esistenti:
root@OpenWrt:~# cat /proc/mtd
dev: size erasesize name
mtd0: 00030000 00010000 "RedBoot"
mtd1: 006f0000 00010000 "rootfs"
mtd2: 00570000 00010000 "rootfs1"
mtd3: 00010000 00010000 "config"
mtd4: 000b0000 00010000 "vmlinux.bin.l7"
mtd5: 0000f000 00010000 "FIS directory"
mtd6: 00001000 00010000 "RedBoot config"
mtd7: 00010000 00010000 "board_config"
Questo il contenuto di ciascuna immagine:
^ RedBoot | mtd0 | |
^ rootfs | mtd1 | Root filesystem di tipo squashfs (read-only, per failsafe boot?) (versione 0.7.1-1) |
^ rootfs1 | mtd2 | Immagine principale del root filesystem, tipo jffs2 (versione 0.7.1-3) |
^ config | mtd3 | |
^ vmlinux.bin.l7 | mtd4 | Immagine del kernel Linux |
^ FIS directory | mtd5 | |
^ RedBoot config | mtd6 | Configurazione del boot manager RedBoot |
^ board_config | mtd7 | |
Non si capisce bene il significato di **''rootfs''** e **''rootfs1''**. Dal prompt ''RedBoot'' è visibile solo un blocco di nome ''rootfs'', che è quello che viene sovrascritto con l'immagine ufficiale squashfs durante l'operazione di flash.
Con questo comando lanciato dal PC possiamo salvare sul PC stesso un file con l'immagine che contiene il kernel:
ssh root@169.254.255.1 'dd if=/dev/mtdblock/4' > mtdblock4
FIXME L'immagine del **rootfs1** (mtd2) ottenuta in questo modo **non è adatta ad essere flashata** come descritto in seguito! Con il seguente metodo si ottiene un file di 5.5M (di tipo //data//), mentre l'immagine rootfs distribuita da Fon è un file di 1.5M (di tipo //Squashfs filesystem//).
===== Flash di un'immagine ufficiale Fon =====
Questa procedura è stata sperimentata flashando un'immagine **rootfs** originale Fon (versione **{{.:fonera:fonera_0.7.1.3.fon.gz|fonera_0.7.1.3.fon}}**), per recuperare una Fonera //bricked//. Abbiamo flashato due file sulla Fonera: **rootfs.squashfs** e **kernel.lzma**
Il flashing è stato fatto operando dal prompt di **''RedBoot''**. In teoria dovrebbe essere possibile riscrivere la flash anche da riga di comando utilizzando il comando ''write'' di **''mtd''**, ma noi non ci siamo riusciti! Abbiamo riscritto sia l'mtd device ''rootfs'' che ''rootfs1'': al reboot successivo abbiamo ritrovato la Fonera con il vecchio rootfs.
Iniziamo con **rootfs.squashfs**, si tratta di un //Squashfs filesystem//. Avviare La Fonera controllandola via seriale, interrompere la sequenza ed entrare al prompt RedBoot:
+PHY ID is 0022:5521
Ethernet eth0: MAC address 00:18:84:1e:61:98
IP: 169.254.255.1/255.255.0.0, Gateway: 0.0.0.0
Default server: 169.254.255.46
RedBoot(tm) bootstrap and debug environment [ROMRAM]
Non-certified release, version v1.3.0 - built 16:57:58, Aug 7 2006
Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
Board: ap51
RAM: 0x80000000-0x81000000, [0x80040450-0x80fe1000] available
FLASH: 0xa8000000 - 0xa87f0000, 128 blocks of 0x00010000 bytes each.
== Executing boot script in 10.000 seconds - enter ^C to abort
^C
RedBoot>
Controlliamo le immagini presenti nella memoria flash (Fonera originale, versione 0.7.1-3):
RedBoot> fis list
Name FLASH addr Mem addr Length Entry point
RedBoot 0xA8000000 0xA8000000 0x00030000 0x00000000
rootfs 0xA8030000 0xA8030000 0x00700000 0x00000000
vmlinux.bin.l7 0xA8730000 0x80041000 0x000B0000 0x80041000
FIS directory 0xA87E0000 0xA87E0000 0x0000F000 0x00000000
RedBoot config 0xA87EF000 0xA87EF000 0x00001000 0x00000000
Se RedBoot non avesse già assegnato un indirizzo IP alla Ethernet lo si fa adesso, qui lo facciamo solo a scopo didattico, perché l'indirizzo è stato già assegnato come si vede dall'output sopra. Si carica quindi in RAM l'immagine del nuovo **rootfs** tramite protocollo **tftp** (bisogna configurare un PC con tftpd e condividere il file immagine):
RedBoot> ip_address -l 169.254.255.1/16 -h 169.254.255.46
IP: 169.254.255.1/255.255.0.0, Gateway: 0.0.0.0
Default server: 169.254.255.46
RedBoot> load -r -b %{FREEMEMLO} -m tftp -h 169.254.255.46 rootfs.squashfs
Raw file loaded 0x80040800-0x801c07ff, assumed entry at 0x80040800
I parametri specificati al comando ''load'' sono:
^ -r | Indica che il file è //raw data//. |
^ -b | Indirizzo in RAM a cui caricare il file. Si usa un alias che rappresenta l'inizio della RAM libera. |
Quindi si crea l'immagine nella memoria flash:
RedBoot> fis create rootfs -e 0
An image named 'rootfs' exists - continue (y/n)? y
... Erase from 0xa8030000-0xa8730000: ..........................................
... Program from 0x80040800-0x801c0800 at 0xa8030000: ........................
... Erase from 0xa87e0000-0xa87f0000: .
... Program from 0x80ff0000-0x81000000 at 0xa87e0000: .
**Non abbiamo specificato** né l'indirizzo di origine della **memoria RAM** (parametro **-b**) né l'indirizzo destinazione **nella memoria flash** (parametro **-f**) dei dati da scrivere. Come valori predefiniti sono stati presi rispettivamente l'indirizzo dell'ultimo file caricato (0x80040800) e l'indirizzo dell'immagine //rootfs// esistente (0xA8030000). È stato dato il parametro **-e 0**, perché per l'immagine rootfs non ha senso specificare un entry point. Vedere eventualmente la **[[http://ecos.sourceware.org/ecos/docs-latest/redboot/redboot-guide.html| documentazione di RedBoot]]**.
Controlliamo nuovamente le immagini esistenti:
RedBoot> fis list
Name FLASH addr Mem addr Length Entry point
RedBoot 0xA8000000 0xA8000000 0x00030000 0x00000000
rootfs 0xA8030000 0x80040800 0x00700000 0x00000000
vmlinux.bin.l7 0xA8730000 0x80041000 0x000B0000 0x80041000
FIS directory 0xA87E0000 0xA87E0000 0x0000F000 0x00000000
RedBoot config 0xA87EF000 0xA87EF000 0x00001000 0x00000000
Si esegue operazione analoga per caricare l'immagine del kernel **kernel.lzma**:
RedBoot> load -r -v -b 0x80041000 -m tftp -h 169.254.255.46 kernel.lzma
Raw file loaded 0x80041000-0x800c0fff, assumed entry at 0x80041000
RedBoot> fis create -r 0x80041000 -e 0x80041000 vmlinux.bin.l7
An image named 'vmlinux.bin.l7' exists - continue (y/n)? y
... Erase from 0xa8730000-0xa87e0000: ...........
... Program from 0x80041000-0x800c1000 at 0xa8730000: ........
... Erase from 0xa87e0000-0xa87f0000: .
... Program from 0x80ff0000-0x81000000 at 0xa87e0000: .
In questo caso si è indicato il base address per il caricamento in ram (**-b**). Nel creare la nuova immagine si è indicato l'indirizzo di rilocazione (**-r**) e l'entry point (**-e**) rispettando lo schema originale.
Per riavviare:
RedBoot> reset
====== OpenWrt ======
Sulla Fonera si possono installare due versioni di OpenWrt: **Kamikaze** e **Backfire**, occorre il build per Atheros:
* [[http://downloads.openwrt.org/kamikaze/8.09.2/atheros/]]
* [[http://downloads.openwrt.org/backfire/10.03.1/atheros/]]
===== Compilazione =====
**ATTENZIONE:** Operazione da fare solo in casi particolari, la distribuzione binaria precompilata va più che bene.
==== OpenWrt Download ====
In una directory dedicata, si scarica da SVN il trunk di OpenWrt e tutti i pacchetti extra disponibili:
svn co https://svn.openwrt.org/openwrt/trunk/
svn co https://svn.openwrt.org/openwrt/packages
La compilazione di OpenWrt cerca i pacchetti nella directory **trunk/package**, quindi si creano dei link simbolici alle directory dei pacchetti extra:
cd trunk/package
ln -sv ../../packages/*/* .
cd ../..
==== OpenWrt Configure ====
cd trunk
make menuconfig
Target System (Atheros [2.6]) --->
Base System --->
<*> busybox
Configuration --->
Networking Utilities --->
[*] arp
[*] ether-wake
[*] hostname
Network --->
<*> vtun
<*> wget
<*> wol
<*> wpa-supplicant
<*> wpa-cli
...
...
La configurazione viene salvata nel file **.config**.
==== OpenWrt Compile ====
cd trunk
make
Al termine della compilazione le immagini e i pacchetti *.ipk si trovano nella directory **trunk/bin**.
L'immagine del root filesystem viene create in alcune varianti:
^ squashfs | The firmwares with //squashfs// in the filename use a combination of a readonly squashfs partition and a writable jffs2 partition. This gives you a /rom with all the files that shipped with the firmware and a writable root containing symlinks to /rom. This is considered the standard install. |
^ jffs2 | The firmwares with //jffs2// in the name are jffs2 only; all of the files are fully writable. |
^ 64k, 128k, ... | Most 4M flash chips use a block size of 64k while most 8M chips tend to use a 128k block size. The jffs2 partition needs to be formatted for the correct block size. |
===== Flash dell'immagine OpenWrt Backfire =====
Qui le istruzioni ufficiali: [[http://wiki.openwrt.org/toh/fon/fonera]].
Scaricati i file **openwrt-atheros-vmlinux.lzma** e **openwrt-atheros-root.squashfs** dal [[http://downloads.openwrt.org/backfire/10.03.1/atheros/|repository]] e resi disponibili sul server **tftp** all'indirizzo IP **169.254.255.46**.
Avviata La Fonera e raggiunto il prompt RedBoot dalla console seriale, con **''fis list''** si possono vedere le immagini caricate in flash:
RedBoot> fis list
Name FLASH addr Mem addr Length Entry point
RedBoot 0xA8000000 0xA8000000 0x00030000 0x00000000
rootfs 0xA8030000 0xA8030000 0x00700000 0x00000000
vmlinux.bin.l7 0xA8730000 0x80041000 0x000B0000 0x80041000
FIS directory 0xA87E0000 0xA87E0000 0x0000F000 0x00000000
RedBoot config 0xA87EF000 0xA87EF000 0x00001000 0x00000000
Si carica in RAM l'immagine del kernel via tftp, quindi si copia in flash memory specificando a che indirizzo dovrà essere caricata in RAM (**-r**) e specificando anche l'entry point (**-e**) a cui iniziare l'esecuzione (si mantengono gli stessi valori del kernel Fon):
RedBoot> ip_address -h 169.254.255.46 -l 169.254.255.1/24
IP: 169.254.255.1/255.255.255.0, Gateway: 0.0.0.0
Default server: 169.254.255.46
RedBoot> load -r -b %{FREEMEMLO} openwrt-atheros-vmlinux.lzma
Using default protocol (TFTP)
Raw file loaded 0x80040800-0x801207ff, assumed entry at 0x80040800
RedBoot> fis init
About to initialize [format] FLASH image system - continue (y/n)? y
*** Initialize FLASH Image System
... Erase from 0xa87e0000-0xa87f0000: .
... Program from 0x80ff0000-0x81000000 at 0xa87e0000: .
RedBoot> fis create -e 0x80041000 -r 0x80041000 vmlinux.bin.l7
... Erase from 0xa8030000-0xa8110000: ..............
... Program from 0x80040800-0x80120800 at 0xa8030000: ..............
... Erase from 0xa87e0000-0xa87f0000: .
... Program from 0x80ff0000-0x81000000 at 0xa87e0000: .
Si carica in RAM via ftp l'immagine del root filesystem (nella posizione più bassa della RAM, variabile FREEMEMLO) e si copia in flash alla prima posizione libera:
RedBoot> load -r -b %{FREEMEMLO} openwrt-atheros-root.squashfs
Using default protocol (TFTP)
Raw file loaded 0x80040800-0x802207ff, assumed entry at 0x80040800
RedBoot> fis create rootfs
... Erase from 0xa8110000-0xa82f0000: ..............................
... Program from 0x80040800-0x80220800 at 0xa8110000: ..............................
... Erase from 0xa87e0000-0xa87f0000: .
... Program from 0x80ff0000-0x81000000 at 0xa87e0000: .
Si verifica la configurazione di boot, per sicurezza la si riscrive:
RedBoot> fconfig -l -n
boot_script: true
boot_script_data:
.. fis load -l vmlinux.bin.l7
.. exec
boot_script_timeout: 1
bootp: false
bootp_my_gateway_ip: 0.0.0.0
bootp_my_ip: 0.0.0.0
bootp_my_ip_mask: 255.255.255.255
bootp_server_ip: 0.0.0.0
console_baud_rate: 9600
gdb_port: 9000
info_console_force: false
net_debug: false
RedBoot> fconfig boot_script_data
boot_script_data:
.. fis load -l vmlinux.bin.l7
.. exec
Enter script, terminate with empty line
>> fis load -l vmlinux.bin.l7
>> exec
>>
Update RedBoot non-volatile configuration - continue (y/n)? y
... Erase from 0xa87e0000-0xa87f0000: .
... Program from 0x80ff0000-0x81000000 at 0xa87e0000: .
Infine si riavvia:
RedBoot> reset
OpenWrt Backfire installa l'**interfaccia web LuCI** e un telenet con accesso root senza password, l'indirizzo di rete predefinito è 192.168.1.1. Una volta impostata una password per l'utente root il telenet viene disabilitato e al suo posto viene abilitato l'ssh.
====== Configurare OpenWrt ======
===== /etc/config/network =====
Configurazione Ethernet via DHCP:
config interface wan
option ifname eth0.1
option proto dhcp
option hostname MyRouter
Configurazione Ethernet statica:
config interface lan
option ifname eth0.0
option proto static
option ipaddr 192.168.1.2
option netmask 255.255.255.0
option gateway 192.168.1.1
option dns 192.168.1.1
Dopo aver modificato la configurazione dovrebbe bastare dare il comando:
/sbin/ifup lan
===== /etc/config/wireless =====
Per attivare l'interfaccia wireless bisogna mettere nel file di configurazione due sezioni. Una sezione **wifi-device** con la configurazione della radio, il cui risultato è l'attivazione dell'interfaccia **wifi0**. Una seconda sezione di nome **wifi-iface** con la configurazione dell'interfaccia di rete vera e propria (quella effettivamente usata con il TCP/IP ecc.), il cui risultato è l'attivazione dell'interfaccia **ath0**:
config wifi-device wifi0
option type atheros
option channel 5
# option diversity 1
# option txantenna 0
# option rxantenna 0
# option distance 2000
# disable radio to prevent an open ap after reflashing:
option disabled 0
config wifi-iface
option device wifi0
option network lan
# Mode is "ap" (master access point), "sta" (station, managed client):
option mode sta
option ssid OpenWrt
option hidden 0
# option txpower 15
# option bgscan enable
option encryption none
Un esempio per associarsi come client ad un access point con crittografia **wep**:
config wifi-iface
option device wifi0
option network wan
option mode sta
option ssid MyEssid
option encryption wep
option key 's:supersecret01'
Per creare una nuova interfaccia wireless **ath1** (ovviamente basata sullo stesso hardware **wifi0**) si aggiunge un'altra sezione **config wifi-iface**. Non è possibile avere due interfacce contemporaneamente in modalità managed.
Un altro comando per creare interfacce wlan:
wlanconfig ath1 create wlandev wifi0 wlanmode monitor
Per applicare la nuova configurazione wireless:
/sbin/wifi down
/sbin/wifi up
===== /etc/init.d/ =====
Per avviare e formare i servizi ci sono gli script in **''/etc/init.d/''**. Oltre ai classici **start** e **stop** dovrebbero essere supportate anche le opzioni **enable** e **disable** per abilitare o meno l'avvio automatico del servizio al bootstrap.
Attivare un servizio al bootstrap generalmente significa creare l'opportuno link simbolico in **''/etc/rc.d/''**.
===== /etc/config/firewall e /etc/firewall.user =====
Nel file **''/etc/config/firewall''** si scrive la configurazione con una sintassi semplificata, ad esempio:
accept:proto=tcp dport=22
Altre istruzioni **iptables** vanno invece in **''/etc/firewall.user''**. Rispetto ad una configurazione vanilla si può approfittare di alcune catene predefinite:
* input_rule
* input_wan
* output_rule
* forwarding_rule
* forwarding_wan
* NEW
* prerouting_rule
* prerouting_wan
* postrouting_rule
Come configurazione predefinita vengono accettate tutte le connessioni **RELATED**, **ESTABLISHED** e il traffico **icmp**. Vedere per maggiori dettagli **''/etc/init.d/firewall''**.
## Allow full forwarding
iptables -A forwarding_rule -i eth0 -o ath0 -j ACCEPT
## Allow masquerading
iptables -t nat -A postrouting_rule -s 192.168.1.0/24 -o ath0 -j MASQUERADE