DSL-302T demystified
Home | DSL-302T | F.A.Q. | News

Disclaimer

Il presente documento ha scopo PURAMENTE INFORMATIVO: l' autore non si assume alcuna responsabilità di eventuali danni diretti o indiretti provocati dall' applicazione delle informazioni ivi contenute e non offre ovviamente alcuna garanzia sulla correttezza delle stesse.
Notare che le operazioni descritte non sono adatte ad essere eseguite dall'utente inesperto e potrebbero rendere inutilizzabile il dispositivo: dunque ne sconsiglio vivamente l'applicazione. Infine, se il "modem" è in comodato d'uso, ci si assicuri di non violare le clausole contrattuali relative alla custodia dello stesso.

W3CHTML 4.01 W3CCSS 2.0

D-Link DSL-302T

by Kirillov

Contenuto:

1. Introduzione
2. Una rapida panoramica del sistema
2.1 L' interfaccia seriale
3. Telnet
3.1 Aggiornare il firmware
3.2 Modificare le variabili d'ambiente
3.3 Controllo dei LEDs
4. ADAM2
4.1 Il bootloader di ADAM2
4.2 Il server FTP di ADAM2
4.3 Aggiornare il firmware con ADAM2
4.4 Ridimensionare le partizioni
4.5 Caricare il firmware del DSL-500T
4.6 Trasferire ed eseguire un applicativo in memoria
5. Conclusioni

1. Introduzione

Ho deciso di buttare giù queste poche righe per i possessori del D-LINK DSL-302T (fornito in comodato d'uso ai clienti Alice-TI) sperando di arginare in tal modo il flood di richieste su forum e newsgroup sulla modifica del firmware di questo interessante dispositivo. La gran parte dei concetti espressi in questi appunti è comunque applicabile a tutti i dispositivi basati su AR7: i D-Link DSL-xxxT, Netgear DG834G, Actiontec GT701, AVM Fritz!Box, ecc. Darò per scontata un' elementare conoscenza dell' ambiente unix.

2. Una rapida panoramica del sistema

Tutto l' hardware ruota intorno al TNETD7300, un integrato della Texas Instruments cuore dell' architettura AR7, specificatamente progettato per i routers DSL, e che integra un processore RISC MIPS 4KEc V4.8 a 150MHz. Il sistema è inoltre dotato di 8MB di SDRAM (ESMT M12L64164A-7T) e 2MB di memoria flash (Intel TE28F160). All' interno è anche presente un connettore a 5 pin: si tratta di un' interfaccia seriale. La memoria flash è suddivisa in 4 "partizioni":

Partiz.ContenutoAllocazioneDimensione
mtd0root - Filesystem compresso (SquashFS)0x900a0000 - 0x901f00001344 kB (21 blocchi)
mtd1kernel - kernel compresso (LZMA)0x90010000 - 0x900a0000576 kB (9 blocchi)
mtd2ADAM2 0x90000000 - 0x9001000064 kB (1 blocco)
mtd3Configurazione (env+config.xml)0x901f0000 - 0x9020000064 kB (1 blocco)

La flash memory viene dunque "vista" dal processore agli indirizzi di memoria suddetti, che appartengono tutti al kseg0 contrassegnato come "cacheable" e accessibile in kernel mode (per maggiori dettagli si rimanda alla documentazione dei processori MIPS). In effetti la flash è costituita da 32 erase blocks da 64 kB ciascuno (vedi oltre).

Il DSL-302T è linux-based (MontaVista Linux version 2.4.17), tuttavia il firmware contiene anche del codice proprietario. La maggior parte dei sorgenti è comunque disponibile sul server ftp della d-link. Il filesystem è compresso e a sola lettura (SquashFS) e per risparmiare ulteriormente risorse tutti i principali comandi sono forniti da BusyBox che li incorpora in un unico file. Sul sito di BusyBox è possibile trovare sintassi e descrizione dell' intero set di comandi (solo una parte dei quali sono implementati sul nostro modem). Durante la fase di boot, viene caricato il demone thttpd che consente la configurazione del dispositivo tramite browser e un demone dhcp. I dati di configurazione sono salvati negli ultimi 54kB del blocco mtd3 sottoforma di uno pseudo-file config.xml e sono gestiti attraverso alcuni moduli applicativi forniti (senza codice sorgente) dalla Texas Instruments:

cm_logic [-h] [-c /path/to/config.xml] [-m /path/to/mtdblockdevice]

È un modulo di fondamentale importanza. Gestisce numerosi aspetti del funzionamento del sistema, in particolare "sincronizza" il contenuto di config.xml con i dati presenti nel blocco mtd3, controllando l'integrità di quest' ultimo.

cm_cli [-t timeout] [-l] [-v]

Core logic Interface. Permette di dialogare con la logica del sistema, il suo stdout è /dev/console, ovvero la console seriale. Ecco un esempio:

   echo "begin;logger:settings/loglevel=debug;end" | cm_cli

In questo modo abbiamo impostato il log al livello "debug". Notare che per modificare delle impostazioni è necessaria la struttura begin...end, che invece non è necessaria nelle interrogazioni:

   echo "logger:status/log" | cm_cli
   echo "security:settings/password" | cm_cli

possiamo leggere i risultati dalla console seriale.

cm_pc

Viene caricato dallo script di avvio, legge il program definition file (/etc/progdef.xml) e si occupa di caricare i moduli fondamentali e attivare determinati servizi al verificarsi di particolari eventi.

webcm

È la CGI di configurazione del dispositivo tramite web-browser.

2.1 L' interfaccia seriale

Sulla scheda del dispositivo è presente un connettore a 5 pin: si tratta di una porta seriale. Come al solito per interfacciarla al PC, sarà necessario traslare i livelli TTL 3,3V per adattarli a quelli tipici della RS-232. Allo scopo esistono componenti specifici come il MAX3232 (o equivalenti): bastano 4 condensatori da 100nF e il gioco è fatto. Per connettersi al dispositivo basta un qualunque emulatore di terminale configurato come 38400,n,8,1.

Interfaccia seriale

Ecco il circuito di interfaccia (clicca per ingrandire):

Clicca qui

3. Telnet

In presenza di un tentativo di connessione sulla porta TCP/23, cm_pc lancia il demone utelnetd. L'account e la password di accesso sono ripettivamente root e admin. Una volta effettuato il login otteniamo il prompt della shell built-in di BusyBox (ash):

$ telnet 192.168.1.1

login: root

Password:


BusyBox v0.61.pre (2004.03.11-17:08+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

#

3.1 Aggiornare il firmware da telnet

È un modo di procedere alquanto "brutale": per aggiornare il firmware sarebbe più indicato utilizzare il server FTP di ADAM2 come spiegato in seguito. Resta comunque un metodo efficace: per prima cosa bisogna procurarsi un firmware adatto, ad esempio quello del DSL-300T, scompattarlo in una directory temporanea e rinominare per comodità i due files come fs e kernel. In secondo luogo bisogna installare sul proprio Pc un server TFTP, che ci consenta di trasferire i due files dal PC al modem: gli utenti windows possono scaricarne uno free qui (ricordate però di selezionare "Transmit and Receive files" in Security, raggiungibile dal menu Files->Configure).

Accediamo ora al nostro dispositivo tramite telnet all' indirizzo 192.168.1.1. Dobbiamo trasferire i due files (fs e kernel) dal PC alla memoria SDRAM del dispositivo: per fare questo ci sposteremo prima in /var.

     # cd /var
     # tftp -g -r fs 192.168.1.x
     # tftp -g -r kernel 192.168.1.x

Ovviamente sostituiremo 192.168.1.x con l'indirizzo del nostro PC...

Nella directory /var dovrebbero comparire i 2 nuovi files: per concludere l'operazione non ci resta che trasferirli dalla SDRAM alla memoria flash:

     # dd if=/var/fs of=/dev/mtdblock/0

Dopo qualche attesa verrà completato il salvataggio dell' immagine del filesystem, per il kernel invece:

     # dd if=/var/kernel of=/dev/mtdblock/1

Ancora una volta, il sistema dovrebbe confermare l'avvenuto trasferimento. Se tutto è andato bene, possiamo spegnere il dispositivo e riaccenderlo dopo qualche secondo: dovrebbe funzionare a tutti gli effetti come un DSL-300T. In generale dopo l'aggiornamento e il successivo reboot conviene tenere premuto il tasto reset per una decina di secondi in modo da portare config.xml alle condizioni di default relative al particolare firmware utilizzato. Se qualcosa dovesse essere andato storto si può sempre utilizzare il server FTP di ADAM2 come spiegato più avanti.

Notare che utilizzando il firmware del DSL-300T la porta usb diviene inutilizzabile.

3.2 Modificare le variabili d'ambiente

Le variabili d'ambiente del sistema sono salvate nei primi 10kB del blocco mtd3. Il loro significato sarà chiaro più avanti. Per adesso limitiamoci a dire che /proc/ticfg/env ci offre una comoda interfaccia verso di esse. Possiamo infatti facilmente modificare, aggiungere o eliminare una variabile con la seguente sintassi:

echo <variabile> [valore] > /proc/ticfg/env

Notare che se <valore> viene omesso, la variabile viene eliminata. Ecco un esempio:

# echo usb_prod 302T_Hacked > /proc/ticfg/env
# cat /proc/ticfg/env | grep usb_prod
usb_prod        302T_Hacked

3.3 Controllo dei LEDs

Il DSL-302T è dotato di 5 LEDs, anche se la scheda ne supporta un numero maggiore. I LEDs controllabili sono identificati da un Module ID. Ogni led può assumere 4 stati (1=idle, 2= training, 3=sync, 4=activity). Ogni stato può assumere 4 modalità (1=off, 2=blinkon, 3=blinkoff, 4=on, 5=flash). Per le modalità "lampeggianti" (2,3,5) è previsto anche un parametro che stabilisce la frequenza di lampeggiamento in ms. Lo script di avvio lancia l' applicazione ledapp che si occupa di impostare le modalità relative ad ogni stato in base alla configurazione salvata in /etc/led.conf.

# cat /proc/led_mod/led
LEDS Registered for use are: 3  4  5  7  8  9  10  11  12  13  14
USER MODULE INFORMATION:
  Module ID = 1
    State = 1 , Led = 4, Mode = OFF
    State = 2 , Led = 4, Mode = FLASH , Time Period(ms) = 200
    State = 3 , Led = 4, Mode = ON
    State = 4 , Led = 4, Mode = BLINK_OFF , Off Time(ms) = 25
  Module ID = 2
    State = 1 , Led = 5, Mode = OFF
    State = 2 , Led = 5, Mode = ON
  Module ID = 3
    State = 1 , Led = 7, Mode = OFF
    State = 2 , Led = 7, Mode = ON
    State = 3 , Led = 7, Mode = BLINK_ON , On Time(ms) = 50
  Module ID = 5
    State = 1 , Led = 7, Mode = OFF
    State = 2 , Led = 7, Mode = ON
    State = 3 , Led = 7, Mode = BLINK_OFF , Off Time(ms) = 50
  Module ID = 6
    State = 1 , Led = 13, Mode = OFF
    State = 2 , Led = 13, Mode = ON
    State = 3 , Led = 13, Mode = BLINK_OFF , Off Time(ms) = 50
  Module ID = 9
    State = 1 , Led = 9, Mode = FLASH , Time Period(ms) = 500
    State = 2 , Led = 9, Mode = OFF
    State = 3 , Led = 9, Mode = BLINK_OFF , Off Time(ms) = 40
    State = 4 , Led = 9, Mode = BLINK_ON , On Time(ms) = 40
    State = 5 , Led = 9, Mode = FLASH , Time Period(ms) = 40

In pratica lo stato dei leds può essere controllato con la seguente sintassi:

echo <Module ID>,<stato> > /proc/led_mod/led 

Un'occhiata a /etc/led.conf chiarirà ogni eventuale dubbio.

4. ADAM2

Si può dire che Adam2 sia il cuore del sistema: si tratta di un particolare monitor del processore sviluppato dalla Telogy Software, che essenzialmente consta di due "moduli": un bootloader e un server FTP per l' aggiornamento del firmware. I parametri di configurazione che riguardano ADAM2 sono salvati nei primi 10 kB del blocco mtd3 sottoforma di variabili d' ambiente. I restanti 54 kB del blocco mtd3 sono riservati a config.xml. Le variabili d'ambiente possono essere lette direttamente dallo pseudo-file /proc/ticfg/env:

    # cat /proc/ticfg/env
    memsize 0x00800000
    flashsize       0x00200000
    modetty0        38400,n,8,1,hw
    modetty1        38400,n,8,1,hw
    bootserport     tty0
    cpufrequency    150000000
    sysfrequency    125000000
    bootloaderVersion       0.22.02
    ProductID       AR7RD
    HWRevision      Unknown
    SerialNumber    none
    my_ipaddress    10.8.8.8
    prompt  Adam2_AR7RD         
    firstfreeaddress        0x9401d888
    req_fullrate_freq       125000000
    maca    x:x:x:x:x:x         
    mtd0    0x900a0000,0x901f0000 
    mtd1    0x90010000,0x900a0000 
    mtd2    0x90000000,0x90010000 
    mtd3    0x901f0000,0x90200000
    autoload        1         
    usb_vid 0x2001
    usb_pid 0x5b00
    usb_man D-Link
    usb_prod        Alice ADSL 302T
    usb_serial      x:x:x:x:x:x
    usb_board_mac   x:x:x:x:x:x
    usb_usbrndis_mac
    usb_rndis_mac   x:x:x:x:x:x

Segue una breve descrizione delle variabili più importanti:

my_ipaddress

Contiene l' indirizzo IP del server FTP di ADAM2. Se questa variabile non è definita il monitor le assegna un valore di default.

prompt

È il prompt del bootloader di ADAM2

cpufrequency, sysfrequency

contengono rispettivamente la frequenza del processore e quella di sistema. Tali parametri possono essere controllati con il comando setmfreq del bootloader.

bootloaderVersion

Versione del monitor. Questa informazione deve essere presente nel pacchetto UDP eventualmente utilizzato per comunicare con ADAM2.

firstfreeaddress

Primo indirizzo disponibile per il trasferimento del kernel in memoria. L'indirizzo presente negli headers dei binari da caricare deve essere compatibile con tale valore.

req_fullrate_freq

Frequenza richiesta (?)

maca

Contiene il MAC address dell' interfaccia di rete. Se questa variabile non è definita il monitor le assegna un valore di default.

mtd0, mtd1, mtd2, mtd3

suddividono la memoria flash in 4 "partizioni", defininendone l' allocazione virtuale e conseguentemente le rispettive dimensioni. Ad esempio il blocco 0 (destinato all' immagine del filesystem) viene "mappato" da 0x900a0000 a 0x901f0000 (si tratta di indirizzi virtuali), occupando così 1344 kB. Analoghe considerazioni valgono per gli altri blocchi. Notare che se mtd0 o mtd1 non sono definite ADAM2 non potrà operare correttamente sulla flash memory.

autoload

Imposta il tempo di attesa allo scadere del quale il bootloader carica ed esegue il kernel. Se la variabile autoload non è impostata il processo di boot viene interrotto.

4.1 Il bootloader di ADAM2

Il bootloader, dopo aver atteso <autoload> secondi, carica l'immagine binaria contenuta all'indirizzo virtuale <mtd1> (ossia il kernel Linux) in un indirizzo di memoria specificato nell' header del file e ne esegue il codice (comando "go"). Dalla console seriale è possibile interrompere il bootstrap: otteniamo così un prompt e abbiamo a disposizione una serie di comandi:

ADAM2 Revision 0.22.02
(C) Copyright 1996-2003 Texas Instruments Inc. All Rights Reserved.
(C) Copyright 2003 Telogy Networks, Inc.
Usage: setmfreq [-d] [-s sys_freq, in MHz] [cpu_freq, in MHz]
Memory optimization Complete!

Adam2_AR7RD >
Press any key to abort OS load, or wait 1 seconds for OS to boot...

Adam2_AR7RD > help
	 Commands		Description
	 --------		-----------
         h/help commands supported
           info Displays board information
          memop Memory Optimization
       setmfreq configures/dumps the system and cpu frequencies
             dm Dump memory at <address>
         setmac Change memory at <address> <value>
          erase Erase Flash except Adam2 Kernel and Env space
       printenv Displays Env. Variables
         setenv Sets Env. variable <var> with a value <val>
       unsetenv Unsets the Env. variable <var>
         fixenv Defragment for Env. space
             go Loads the image starting at address <mtd1>

Adam2_AR7RD > info                  
Monitor Revision              0.22.02
Monitor Compilation time      Feb 10 2004, 12:27:38
Endianness                    Little
External Memory rate          Full, 16 bit wide
CPU Frequency                 150 MHz

Adam2_AR7RD > dm 0x900a0000 0x900a003f

900a0000: 73717368 00000170 0013707a 00137072 - hsqsp...zp..rp..               
900a0010: 00137076 001359d9 001365a7 00000001 - vp...Y...e......               
900a0020: 000f8000 9d010100 a440d258 00000018 - ........X.@.....               
900a0030: 78000000 0b7dbdda 75d75478 07a39aee - ...x..}.xT.u....               

Adam2_AR7RD > setmfreq -d
CPU Freq: 150000000
SYS Freq: 125000000
        
Adam2_AR7RD > go
Launching kernel decompressor.  
Kernel decompressor was successful ... launching kernel.

LINUX started...
Config serial console: ttyS0,38400
CPU revision is: 00018448
Primary instruction cache 16kb, linesize 16 b
Primary data cache 16kb, linesize 16 bytes (4 ways)
Number of TLB entries 16.
Linux version 2.4.17_mvl21-malta-mips_fp_le (jordan@localhost.localdomain) (gcc
version 2.95.3 20010315 (release/MontaVista)) #70 g| 2 26 07:54:07 CST 2004   
Determined physical RAM map:
 memory: 14000000 @ 00000000 (reserved) 
 memory: 00020000 @ 14000000 (ROM data) 
 memory: 007e0000 @ 14020000 (usable)   
On node 0 totalpages: 2048  
zone(0): 2048 pages.
zone(1): 0 pages. 
zone(2): 0 pages. 
Kernel command line:
the pacing pre-scalar has bee   
calculating r4koff... 000b71b0(750000)
CPU frequency 150.00 MHz
Calibrating delay loop... 149.91 BogoMIPS   
Freeing Adam2 reserved memory [0x14001000,0x0001f000]   
Memory: 6504k/8192k available (1315k kernel code, 1688k reserved, 111k data, 48k
 init)  
Dentry-cache hash table entries: 1024 (order: 1, 8192 bytes)  
Inode-cache hash table entries: 512 (order: 0, 4096 bytes)
Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
Buffer-cache hash table entries: 1024 (order: 0, 4096 bytes)  
Page-cache hash table entries: 2048 (order: 1, 8192 bytes)
Checking for 'wait' instruction...  unavailable.  
POSIX conformance testing by UNIFIX 
Linux NET4.0 for Linux 2.4  
Based upon Swansea University Computer Society NET3.039 
Initializing RT netlink socket  
Starting kswapd   
Disabling the Out Of Memory Killer
devfs: v1.7 (20011216) Richard Gooch (rgooch@atnf.csiro.au) 
devfs: boot_options: 0x1
pty: 32 Unix98 ptys configured  
Serial driver version 5.05c (2001-07-08) with no serial options enabled   
ttyS00 at 0xa8610e00 (irq = 15) is a 16550A 
ttyS01 at 0xa8610f00 (irq = 16) is a 16550A 
block: 64 slots per queue, batch=16 
PPP generic driver version 2.4.1
avalanche flash device: 0x400000 at 0x10000000. 
Physically mapped flash: Found 1 x16 devices at 0x200000 in 16-bit mode   
Looking for mtd device :mtd0: 
Found a mtd0 image (0xa0000), with size (0x150000). 
Looking for mtd device :mtd1: 
Found a mtd1 image (0x10000), with size (0x90000).
Looking for mtd device :mtd2: 
Found a mtd2 image (0x0), with size (0x10000).
Looking for mtd device :mtd3: 
Found a mtd3 image (0x1f0000), with size (0x10000). 
Looking for mtd device :mtd4: 
Creating 4 MTD partitions on "Physically mapped flash": 
0x000a0000-0x001f0000 : "mtd0"  
0x00010000-0x000a0000 : "mtd1"  
0x00000000-0x00010000 : "mtd2"  
0x001f0000-0x00200000 : "mtd3"  
NET4: Linux TCP/IP 1.0 for NET4.0 
IP Protocols: ICMP, UDP, TCP, IGMP
IP: routing cache hash table of 512 buckets, 4Kbytes  
TCP: Hash tables configured (established 512 bind 512)
Linux IP multicast router 0.06 plus PIM-SM
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0. 
cramfs: wrong magic   
expected 0x28cd3d45 got 0x67844fb9
Reading magic from address 0x9400fe50   
VFS: Mounted root (squashfs filesystem) readonly.   
Mounted devfs on /dev 
Freeing unused kernel memory: 48k freed 
serial console detected.  Disabling virtual terminals.
console=/dev/tts/0
init started:  BusyBox v0.61.pre (2004.06.18-02:49+0000) multi-call binary  
Starting pid 9, console /dev/tts/0: '/etc/init.d/rcS'   
 Standard Configuration File
proc write:Calling Configurat
Number of State module =  1   
STATE =  1  
STATE =  2  
STATE =  3  
STATE =  4  
module =  2   
STATE =  1  
STATE =  2  
module =  3   
STATE =  1  
STATE =  2  
STATE =  3  
module =  5   
STATE =  1  
STATE =  2  
STATE =  3  
module =  6   
STATE =  1  
STATE =  2  
STATE =  3  
module =  9   
STATE =  1  
STATE =  2  
STATE =  3  
STATE =  4  
STATE =  5  
Elements = 20 
Total Length = 164  
Using /lib/modules/2.4.17_mvl21-malta-mips_fp_le/kernel/drivers/atm/tiatm.o   
registered device TI Avalanche SAR
Initializing DSL interface  
Texas Instruments ATM driver: version:[4.01.00.00 
Using /lib/modules/2.4.17_mvl21-malta-mips_fp_le/kernel/net/bridge/bridge.o   
NET4: Ethernet Bridge 008 for NET4.0  
Waiting for enter to start '/bin/sh' (pid 37, terminal /dev/tts/0)

Please press Enter to activate this console. Sep  8 12:00:05 cm_monitor: Monitor
 Starting 
logic: /proc/led_mod/ar7reset: [0]
Logger: Setting remote_loglevel=notice (5)
Setting loglevel=notice (5)   
===>bridge set ZIPB_MODE active in init 

rfc2684_start(nas0):
ip_tables: (c)2000 Netfilter core team
ip_conntrack version 2.0 (64 buckets, 512 max) - 364 bytes per conntrack
Sep  8 12:00:11 cfgmgr(fdb)> Firewall NAT service started
AutoPVC feature is activated
rfc2684_load(nas0): 8.35
/sbin/ifconfig nas0 hw ether 00:aa:bb:cc:dd:10
tn7atm_ioctl
tn7atm_ioctl
===>bridge ZIPB enable

Sep  8 12:00:11 cfgmgr(bridge)> Bridge Created: br0
device nas0 entered promiscuous mode
br0: port 1(nas0) entering learning state
Sep  8 12:00:12 cfgmgr(bridge)> Bridge Interface Added: nas0
device eth0 entered promiscuous mode
br0: port 2(eth0) entering learning state
Sep  8 12:00:12 cfgmgr(bridge)> Bridge Interface Added: eth0
Sep  8 12:00:15 cfgmgr(sar)> DSL Carrier is down
br0: port 1(nas0) entering forwarding state
br0: topology change detected, propagating
br0: port 2(eth0) entering forwarding state
br0: topology change detected, propagating

4.2 Il server FTP di ADAM2

ADAM2 emula anche un server FTP che risponde all' indirizzo IP definito in my_ipaddress. Esso permette la lettura di due "files", env e config.xml: il primo contiene l'elenco di tutte le variabili di sistema con i rispettivi valori, il secondo è un file di configurazione. Grazie a speciali comandi è inoltre possibile impostare le variabili d' ambiente e soprattutto trasferire files immagine nella flash memory. Normalmente il server è attivo solo per qualche istante prima che il bootloader carichi ed esegua il kernel: bisogna accedervi dunque subito dopo l'accensione. L' accesso è autenticato (USER adam2, PASS adam2).

my_ipaddress può essere anche assegnato arbitrariamente: per farlo bisogna accendere il dispositivo e un istante dopo, prima che il bootloader lanci il kernel, inviare un pacchetto UDP in broadcast alla porta 5035 contenente 16 bytes di dati così organizzati:

char adam2udp_data[] =
  "\0x00\0x00\0x16\0x02"  // bootloaderVersion (0.22.02)
  "\0x01\0x00\0x00\0x00"  // Incerto 
  "\0x01\0x01\0xa8\0xc0"  // my_ipaddress (ad es. 192.168.1.1)
  "\0x00\0x00\0x00\0x00"; // Riservato (?)

L' invio viene ripetuto finchè ADAM2 risponde dall' indirizzo IP assegnatogli con un pacchetto di conferma (del tutto simile). Ora possiamo loggarci al server FTP all' indirizzo voluto: notare che la variabile my_ipaddress viene salvata dal sistema fino alla sua successiva reimpostazione. Il server consente i seguenti comandi specifici:

REBOOT

Riavvia il sistema

UNSETENV <var>

Elimina la variabile specificata

SETENV <var>,<valore>

Imposta la variabile specificata con <valore>. Notare che gli spazi vuoti vengono interpretati sia nel nome della variabile sia nel suo valore, dunque è importante non lasciare spazi prima e dopo la virgola.

GETENV <var>

Mostra il valore della variabile specificata

MEDIA [FLSH]

Imposta il tipo di supporto in scrittura utilizzato per il comando STOR.
FLSH = Memoria flash.
Qualunque altra cosa = Memoria SDRAM.

STOR <file> [blockname]

La funzione di STOR è condizionata dal comando MEDIA: se MEDIA è impostato su FLSH, STOR salva il file immagine in memoria flash nel blocco <blockname>. Per qualunque altro valore di MEDIA il parametro <blockname> non è richiesto poichè l' immagine viene trasferita in memoria SDRAM e immediatamente eseguita: sono accettati solo file "in formato ADAM2", in caso contrario il trasferimento viene immediatamente interrotto.

Gli altri comandi (SYST, RETR, TYPE, USER, PASS, PASV, P@SW, PORT, QUIT, BYE, ABOR) hanno il consueto significato, ma il sistema è case-sensitive, dunque andranno scritti tutti in maiuscolo, mentre nome utente e password ("adam2") vanno scritti in minuscolo. Ecco un alcuni esempi pratici:

$ telnet 192.168.1.1 21
220 ADAM2 FTP Server ready.
USER adam2
331 Password required for adam2.
PASS adam2
230 User adam2 successfully logged in.
SYST
215 UNIX emulated bye ADAM2's FTP Server.
GETENV bootloaderVersion
bootloaderVersion 0.22.02

200 GETENV command successful
SETENV usb_prod,302T Hacked
200 SETENV command successful
GETENV usb_prod
usb_prod          302T Hacked

200 GETENV command successful
REBOOT
221-Thank you for using the FTP service on ADAM2.
221 Goodbye.

Con un client ftp possiamo leggere il "file" env che contiene tutte le variabili d' ambiente del sistema (in maniera analoga possiamo trasferire config.xml):

ftp 192.168.1.1
Connesso a 192.168.1.1.
220 ADAM2 FTP Server ready.
Utente (192.168.1.1:(none)): adam2
331 Password required for adam2.
Password:
230 User adam2 successfully logged in.
ftp> get env
200 Port command successful.
150 Opening ASCII mode data connection for file transfer.
226 Transfer complete.
ftp: 1034 byte ricevuti in 0,05secondi 22,00Kbyte/sec)

4.3 Aggiornare il firmware con ADAM2

A questo punto dovrebbe essere chiaro che con un qualunque client FTP possiamo trasferire un file immagine in uno dei blocchi della flash memory. Se ad esempio "fs" è l' immagine del filesystem da caricare, dopo esserci loggati al server FTP di ADAM2, dobbiamo impartire le istruzioni seguenti:

ftp> quote TYPE I
200 Type set to I.
ftp> quote MEDIA FLSH
200 Media set to FLSH.
ftp> put fs "fs mtd0"
200 Port command successful.
150 Opening BINARY mode data connection for file transfer.
226 Transfer complete.
ftp: 1277960 byte inviati in 11,23secondi 113,75Kbyte/sec)
ftp> quote REBOOT
221-Thank you for using the FTP service on ADAM2.
221 Goodbye.

Ma chi non vuole complicarsi la vita facendo le cose a manina, deve (purtroppo per lui) continuare nella lettura di questo documento. IMPORTANTE: prima di procedere è caldamente consigliato effettuare un backup del firmware originale: per fare ciò basta "loggarsi" da telnet, come spiegato nelle sezioni precendenti e dare i seguenti comandi:

# cat /dev/mtdblock/0 > /var/oldfs.img 
# cat /etc/config.xml > /var/config.xml
# /usr/sbin/thttpd -g -d /var -u root -p 8080 

Possiamo così prelevare comodamente i nostri files con un qualsiasi browser all' indirizzo http://192.168.1.1:8080. In maniera analoga possiamo salvare anche il vecchio kernel.

Passiamo ora all' aggiornamento vero e proprio: gli utenti windows possono anche evitare di scrivere un programmino ad hoc (peraltro molto semplice da realizzare) perchè tutta la procedura viene effettuata automaticamente dal recovery tool dell' Actiontec GT701 (che è basato sulla medesima architettura). Basta infatti scaricare il firmware voluto (ad esempio quello del DSL-300T) e rinominare i due files nsp.ar7wrd.squashfs.img (filesystem) e ram_zimage_pad.ar7wrd.nsp.squashfs.bin (kernel). Ora bisogna installare il recovery-tool in una directory temporanea e sostituire i due files immagine nella directory "image" con quelli appena rinominati. Nella stessa directory si deve sostituire anche config.xml con quello inizialmente salvato. A questo punto non resta che lanciare il programma e seguire le istruzioni.

NOTA: Alcuni mi hanno segnalato dei problemi nell'utilizzo del recovery tool: quindi effettuate le operazioni descritte con estrema cautela (se manca la corrente, o il PC si blocca durante il processo ci possono essere degli inconvenienti), conviene anche disattivare tutte le applicazioni (antivirus, firewall, ecc.) che potrebbero interferire con l' operazione.

4.4 Ridimensionare le partizioni

La memoria flash è organizzata in blocchi di 64 kB: ognuno costituisce un' "erase block" cioè la più piccola unità che è possibile cancellare (si veda in proposito la documentazione Intel). È facile comprendere che la dimensione delle partizioni dovrà essere un multiplo di 64 kB. Dovendo destinare un blocco ad ADAM2 (mtd2) e almeno un altro per i dati di configurazione (mtd3), restano 30 blocchi (per un totale di 1920 kB) da dividere fra immagine del filesystem e kernel. ADAM2 ci permette di modificare la dimensione delle partizioni attraverso le variabili di ambiente mtdx. Ad esempio volendo riservare 23 blocchi al filesystem (mtd0) e i restanti 7 al kernel, possiamo dare i seguenti comandi:

SETENV mtd0,0x90080000,0x901f0000 
SETENV mtd1,0x90010000,0x90080000 

In questo modo otteniamo una partizione mtd0 (destinata a contenere l' immagine del filesystem) grande 1472 kB e una mtd1 (per il kernel) grande 448 kB.

4.5 Caricare il firmware del DSL-500T

Il ripartizionamento può essere utile se vogliamo caricare un filesystem di dimensioni maggiori di quello originale: ad esempio quello del DSL-500T. Ecco la procedura completa (come al solito "fs" e "kernel" sono rispettivamente le immagini del filesystem e del kernel del DSL-500T così rinominate per comodità).

> ftp 192.168.1.1
Connesso a 192.168.1.1.
220 ADAM2 FTP Server ready.
Utente (192.168.1.1:(none)): adam2
331 Password required for adam2.
Password:
230 User adam2 successfully logged in.
ftp> quote SETENV mtd0,0x90080000,0x901f0000
200 SETENV command successful
ftp> quote SETENV mtd1,0x90010000,0x90080000
200 SETENV command successful
ftp> bin
200 Type set to I.
ftp> quote MEDIA FLSH
200 Media set to FLSH.
ftp> put fs "fs mtd0"
200 Port command successful.
150 Opening BINARY mode data connection for file transfer.
226 Transfer complete.
ftp: 1486856 byte inviati in 12,97secondi 114,65Kbyte/sec)
ftp> put kernel "kernel mtd1"
200 Port command successful.
150 Opening BINARY mode data connection for file transfer.
426 Connection close; transfer aborted.
ftp: 458760 byte inviati in 4,22secondi 108,74Kbyte/sec)
ftp> quote REBOOT
221-Thank you for using the FTP service on ADAM2.
221 Goodbye.

Non preoccupatevi per quel "426 Connection close; transfer aborted" che sopraggiunge dopo aver caricato il kernel. Infatti controllando l'esito dell'operazione dalla console seriale:

Erasing from 0xb0080000 to 0xb01f0000.
FlashEraseBlock(b0080000,b01effff);
.......................
Erase Successful.

.......................
Erasing from 0xb0010000 to 0xb0080000.
FlashEraseBlock(b0010000,b007ffff);
.......
Erase Successful.

.......ERROR: Store to media failed

si vede che il trasferimento del kernel viene completato (ogni puntino rappresenta un erase block), ma alla fine viene interrotto poichè l'immagine caricata è di 458760 bytes contro i 458752 della partizione da noi creata. Ma questo non è un problema: gli 8 bytes di differenza infatti sono una checksum utilizzata per l'aggiornamento tramite interfaccia web e normalmente non sono salvati nella flash memory (avremmo potuto tranquillamente troncarli con il nostro editor esadecimale preferito).

4.6 Trasferire ed eseguire un applicativo in memoria

Come già detto, impostando MEDIA su un qualunque altro valore diverso da FLSH, il comando STOR salva l' immagine in memoria SDRAM e immediatamente dopo ne esegue il codice. Gli eseguibili sono accettati solo se sono in "formato ADAM2", altrimenti il trasferimento viene interrotto. Nell' header del file immagine deve essere infatti presente un' informazione fondamentale, cioè l' indirizzo di memoria a partire dal quale trasferire l'immagine da eseguire (compatibilmente con la variabile firstfreeaddress). Un esempio di applicazione in formato ADAM2 è proprio il kernel. Ecco un esempio:

ftp> bin
200 Type set to I.
ftp> quote MEDIA MEMORIA
200 Media set to MEMORIA.
ftp> put kernel
200 Port command successful.
150 Opening BINARY mode data connection for file transfer.
226 Transfer complete.

Ovviamente avremmo potuto tranquillamente evitare il comando MEDIA. Possiamo poi verificare l'esito dell'operazione dalla console seriale:

.......

Executing the RAM image at 0x9419a000
Launching kernel decompressor.  
Kernel decompressor was successful ... launching kernel.

LINUX started...

In questo modo possiamo provare kernel diversi, senza doverli ogni volta salvare nella flash memory.

5. Conclusioni

Il d-link DSL-302T è un dispositivo molto versatile: si può fare praticamente di tutto. Non è difficile infatti creare un filesystem personalizzato o compilare un nuovo kernel, facendo sempre attenzione a non sforare la massima dimesione consentita dalla flash memory.

I marchi e i nomi di prodotto citati in questo documento appartengono ai rispettivi proprietari. Copyright (c) 2004-2005 Andrea Tarallo. All rights reserved.