ADAM2

ADAM2 (Avalanche Device Application Manager?) is a simple bootloader/monitor for the Texas Instrument AR7 System-on-Chip. ADAM2 is used in the following devices: ActiontecGT701, ActiontecGT704, DlinkDslG604t, DlinkDslG624t, NetgearDG834G, LinksysWAG54Gv2, Asmax AR-804gu.

ADAM2 Revision 0.22.02
(C) Copyright 1996-2003 Texas Instruments Inc. All Rights Reserved.
(C) Copyright 2003 Telogy Networks, Inc.

ADAM2 includes support for the TI AR7 (16c550 compatible) serial console, TI Ethernet driver (cpmac), TCP/IP, DHCP client, FTP server and FLASH memory writer/eraser.

ADAM2 resides in the mtd2 FLASH partition (0x90000000 virtual KSEG0 == 0x10000000 physical addresses).

Texas Instrument AR7 chip has a tiny (4K) boot-ROM embedded at the 0xBFC00000 (standard MIPS 4KEc reset vector). This code initializes external memory interface (EMIF) and jumps to the 0x90000000 (ADAM2 start).

ADAM2 Serial commands

         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>

Several commands may be separated by ";" e.g. "printenv;info" .

The dm <start> <stop> command allows you to examine various memory regions :

Adam2_AR7RD > dm 0xbfc00000

bfc00000: 10000004 00000000 00000000 00000000 - ................
bfc00010: 0c081000 3c1aa861 375a1a00 8f5a0000 - ....a..<..Z7..Z.
bfc00020: 335a0007 24010001 13410013 00000000 - ..Z3...$..A.....
bfc00030: 24010002 13410013 00000000 24010003 - ...$..A........$
bfc00040: 1341001a 00000000 24010004 1341001a - ..A........$..A.
bfc00050: 00000000 24010005 13410021 00000000 - .......$!.A.....
bfc00060: 24010006 1341001e 00000000 24010007 - ...$..A........$
bfc00070: 13410017 00000000 3c1ab000 03400008 - ..A........<..@.

dumps a standard MIPS 4KEc reset code (internal CPU EEPROM).

ADAM2 DHCP

If the "dhcp" variable is true, ADAM2 acts as DHCP client on the Eth0 interface.

DHCP options supported:

subnet, timezone, router, timesvr, namesvr, dns, logsvr, cookiesvr, lprsvr, hostname, bootsize, domain, swapsvr, rootpath, ipttl, mtu, broadcast, ntpsrv, wins, requestip, lease, dhcp

ADAM2 FTP access

While booting up the device, it waits for a few seconds for incoming FTP connection. The listening IP-address is stored in "my_ipaddress" environment variable.

# strings mtd3.img | awk '/my_ipaddress/ {getline; print;}'
10.8.8.8
10.48.88.66

My box seems to have it stored twice. In this case, the latter one will be the one to connect to. Login with adam2/adam2 (hard-coded in all ADAM2 -based devices). The ADAM2 ftp commands and some more info can be found at http://www.nettwerked.net/actiontec.html

The recovery application can initiate such an FTP session while ADAM2 is working (usually 5 seconds after the device is rebooted) by sending a special broadcast packet to port 5035. The box goes reboot and waits for incoming FTP connection on assigned IP address.

TODO:(Which Linux process is listening to this port ? cm_ ? lsof required). Here's the output of netstat -lp: http://www.hack.fi/~sibbe/dsl/netstat.txt

UDP broadcast port 5035: (16 bytes)
        0x00 0x00 0x16 0x02 0x01 0x00 0x00 0x00
        0xc0 0xa8 0x00 0x01 0x00 0x00 0x00 0x00
UDP response from modem to port 5035: (16 bytes)
        0x00 0x00 0x16 0x02 0x02 0x00 0x00 0x00
        0x01 0x00 0xa8 0xc0 0x00 0x00 0x00 0x00

The 0xc0 0xa8 0x00 0x01 is an assigned IP address: 192.168.0.1 for recovery FTP session.

ADAM2 FTP commands

REBOOT          UNSETENV        SETENV          GETENV
MEDIA           RETR            TYPE            STOR
P@SW            PASV            SYST            PASS
USER            PORT            QUIT            ABOR

It's impossible to execute all of these FTP commands from some weird FTP clients (e.g. Windows). Try to telnet to port 21! All commands must be in Uppercase.

$ telnet 10.48.88.66 21
220 ADAM2 FTP Server ready.
530 Please login with USER and PASS.
USER adam2
331 Password required for adam2.
PASS adam2
230 User adam2 successfully logged in.
ls
502 Command not implemented - Try HELP.
HELP
502 Command not implemented - Try HELP.
SYST
215 UNIX emulated bye ADAM2's FTP Server.
GETENV
501  environment variable not set.
GETENV *
501 * environment variable not set.
GETENV autoload
autoload              1

GETENV my_ipaddress
200 GETENV command successful
my_ipaddress          10.48.88.66

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

$

There are two special "virtual" filenames: env and config.xml, for storing & retrieving ADAM2's variables and /etc/config.xml content respectively.

...
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 bytes received in 0,05seconds 22,00Kbyte/sec)

For sending ADAM2 specific commands you have to use "quote COMMAND" (command should be UPPERCASE).

...
ftp> quote GETENV my_ipaddress
my_ipaddress          10.48.88.66

It is of course possible to flash a filesystem or a kernel image through FTP access.

...
ftp> quote MEDIA FLSH
200 Media set to FLSH.
ftp> bin
200 Type set to I.
ftp> put fs.bin "fs mtd0"
226 Transfer complete.
2015240 bytes sent in 00:27 (72.45 KB/s)
ftp> quote REBOOT
221-Thank you for using the FTP service on ADAM2.
221 Goodbye.

The put command needs that funny destination (the parameter after "fs.bin") where ADAM2 will store the image: "fs", any sequence of characters (example has a space), "mtd", and the partition number. Exception mtd3 - ADAM2 store files with offset, see note below. Also the connection might hang for a while before the transfer starts (while the partition is erased, progress is available on the serial console) - just be patient. This should work with kernel images too, just use mtd1 instead of mtd0.

It is possible to download and run an "ADAM2 application" even without storing it in the Flash. To do so, change mode to "MEDIA SDRAM" and STOR-e a binary image. The image should be in the ADAM2 "go" command format like mtd1 (described below).

ADAM2_dump archive contains an example.

ADAM2 Environment Variables

ADAM2 maintains a set of Environment Variables in a so-called "Non Volatile RAM", emulated by the last FLASH partition mtd3. This partition is split in two: the first 10kB contain the ADAM2 environment variables, while the last 54kB store an XML file detailing the global configuration of Montavista Linux as it was saved by the user.

The Linux /proc/ticfg/env file is a "cooked" interface to the ADAM2 environment variables.

Editing the Environment Variables

There are four ways to read and edit the persistent environment variables used by ADAM2 :

1. Use a serial console and the ADAM2 prompt commands setenv, unsetenv, printenv

2. Use the onboard FTP server's commands SETENV, UNSETENV, GETENV (all caps matter)

3. Use the Linux file /proc/ticfg/env:

# cat /proc/ticfg/env
memsize 0x01000000
flashsize       0x00400000
modetty0        38400,n,8,1,hw
modetty1        38400,n,8,1,hw
bootserport     tty0
cpufrequency    150000000
sysfrequency    125000000
bootloaderVersion       0.22.02
ProductID       AR7WRD
HWRevision      Unknown
SerialNumber    none
my_ipaddress    10.48.88.66
maca    00:0F:3D:98:09:F3
usb_vid 0x0
usb_pid 0x0
usb_rndis_mac   00.0d.88.11.03.02
usb_board_mac   00.0d.88.22.03.02
usb_man N/A
usb_prod        N/A
usb_serial      1234567890
prompt  Adam2_AR7RD
firstfreeaddress        0x9401d328
req_fullrate_freq       125000000
mtd0    0x900a0000,0x903f0000
mtd1    0x90010000,0x900a0000
mtd2    0x90000000,0x90010000
mtd3    0x903f0000,0x90400000
autoload        1
mac_ap  00:0F:3D:98:09:F4

# echo usb_prod Test > /proc/ticfg/env
# cat /proc/ticfg/env | grep usb_prod
usb_prod        Test

4. Edit the first 10kB of the mtd3 mtdblock file with an external hex editor and write it back to /dev/mtd.

WARNING: a corrupt mtd3 may place ADAM2 in a deadlocked state, thus making your device permanently inoperative. Editing mtd3 by hand is NOT recommended.

NVRAM format

Disclaimer: The following information was gained by reverse-engineering the NVRAM memory space storage format. As such, it is not authoritative and is currently incomplete.

ADAM2's environment variables are stored in the first 10kB of mtd3, hence from byte 0x0000 through byte 0x27FF (addresses relative to mtd3).

The "NVRAM" memory space is divided in records.

There are two kinds of records : records that store an environment variable and empty records. Empty records are simply filled with 0xFF. Records that store an environment variable use the following format :

Offset

Value

Comment

0x00

0x42

Capital 'B' or possible Douglas Adams reference

0x01

Checksum byte

The least significant byte of the sum of all data bytes

0x02

Record index

Index of the record, starting at 0x00

0x03

Data length

Length of the record's data, including the 0x00 bytes

0x04

Data

variable name+0x00+variable value+0x00

Example:

0x0100 42 9B 02 18 6D 6F 64 65 74 74 79 30 00 33 38 34
0x0110 30 30 2C 6E 2C 38 2C 31 2C 68 77 00 FF FF FF FF
0x0120 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0x0130 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0x0140 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0x0150 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0x0160 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0x0170 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
0x0180 42 9C 03 18 6D 6F 64 65 74 74 79 31 00 33 38 34
0x0190 30 30 2C 6E 2C 38 2C 31 2C 68 77 00 FF FF FF FF

FIXME : The behaviour of the fixenv command in ADAM2 prompt needs to be addressed here. fixenv rebuilds env space and delete unusable slots.

FIXME : Records may not always be contiguous.

ADAM2 API

ADAM2 provides two APIs for standalone applications, like OS second stage bootloaders or decompressor.

The first API emulates a MIPS YAMON bootloader. It formed as a "call vector" table, started at the address 0x90000500 (not 0xBFC00500):

#define YAMON_FUNCTION_BASE                 0x90000500

/* YAMON Vector table offsets */
#define YAMON_FUNC_PRINT_COUNT_OFS          0x04
#define YAMON_FUNC_EXIT_OFS                 0x20
#define YAMON_FUNC_FLUSH_CACHE_OFS          0x2C
#define YAMON_FUNC_PRINT_OFS                0x34
#define YAMON_FUNC_REGISTER_CPU_ISR_OFS     0x38
#define YAMON_FUNC_DEREGISTER_CPU_ISR_OFS   0x3c
#define YAMON_FUNC_REGISTER_IC_ISR_OFS      0x40
#define YAMON_FUNC_DEREGISTER_IC_ISR_OFS    0x44
#define YAMON_FUNC_REGISTER_ESR_OFS         0x48
#define YAMON_FUNC_DEREGISTER_ESR_OFS       0x4c
#define YAMON_FUNC_GETCHAR_OFS              0x50
#define YAMON_FUNC_SYSCON_READ_OFS          0x54

Only 3 YAMON calls are supported (PRINT_COUNT, PRINT, EXIT). Unfortunately, GETCHAR does not work.

The second API is ADAM2's own API. Its gateway address is 0x90000480.

ADAM2 Applications

ADAM2 can load and execute MIPS LE applications in a specific binary format. (One application of this is a Linux Kernel, stored in the mtd1 FLASH partition.)

There is a format to the "ADAM2 application" and mtd1 content, as required by ADAM2's "go" command.

Record #1 Offset:
----------
0x00000000 SIGNATURE:  .word    0xfeedfa42  ; NL! ADAM2 MIPS LE signature

0x00000004 LENGTH1:    .word    xxxx        ; NL! Record #1 Length
0x00000008 ADDRESS1:   .word    0x94192000  ; NL! RAM Address to load Record #1

                       .code
0x0000000c app:        nop                  ; The first loaded instruction
                                            ; (will be loaded at ADDRESS)
                       ...
0x0001000x _main:      addiu    sp, -0x5c0  ; Application entry point
                       ...
0x0001000x             j        ra
                       addui    sp, 0x5c0
                       .end
0x0002xxxx CHECKSUM1:  .word    xxxx        ; NL! Record #1 CHECKSUM

Record #2 Offset
----------
0x0002xxxx LENGTH2:    .word    0           ; NL! Record #2 length (==0x0)
0x0002xxxx ADDRESS2:   .word    _main       ; NL! Application entry point
0x0002xxxx CHECKSUM2:  .word    0x6be6xxxx  ; NL! Record #2 CHECKSUM

NL! -- Not Loaded

There is tiny ADAM2_dump utility to dump an application's information. If you have a full firmware image you should disassemble it before using adam2_dump.

$ ./adam2_dump DLinkUK_DSL-G604T_kernel_V1.00B02T02.UK.20040618

        ADAM2 application Header:

ADAM2 Magic= 0xfeedfa42 - GOOD!

        ADAM2 application Record #1 Header:

LENGTH   = 0x0006cd8f (445839)
ADDRESS  = 0x94198000
.......... DATA
CHECKSUM = 0x688e3589

        ADAM2 application Record #2 Header:

LENGTH   = 0x00000000
ADDRSESS = 0x94198000 (entry point)
CHECKSUM = 0x6be68000

Compressed kernel image found!
Offset = 0x4b60 (19296), Length = 0x6823b (426555)
LZMA z7 compressed image.
File is signed by TI_chksum.

The ADAM2_app contains an ADAM2 MIPS sample application (without decompressor, ofcource). You need a MIPS toolchain installed to build it.

ADAM2 sourcecode

ADAM2 sourcecode is available as part of the Linksys GPL tarball.

Direct link to Linksys FTP

GPL code is also available on SF.net Files

Linux firmware

Linux firmware consists of 3 parts: Linux kernel + FS image + Config data

There is a Windows firmware recovery/update utility, which disassembles the entire firmware and stores it in the mtd partitions.

FLASH layout (sorted by mtdN number):

mtd0 - CRAMFS image (for root filesystem)
mtd1 - Linux kernel (in ADAM2 application format)
mtd2 - ADAM2
mtd3 - Environment variables and Linux XML configuration data

It is possible to "repartition" a FLASH, just change an ADAM2 variables:

mtd0    0x900a0000,0x903f0000
mtd1    0x90010000,0x900a0000
mtd2    0x90000000,0x90010000
mtd3    0x903f0000,0x90400000

Note: the partitions are not in order. The mtd2 partition (64Kb) is the ADAM2 code and must be at address 0x90000000! The mtd3 is a NVRAM space and occupies the last 64Kb of FLASH. Linux kernel MTD driver will find all partitions automatically.

Linux kernel Boot sequence

ADAM2 automatically executes a "go" command to load and run the contents of mtd1, provided there is no activity on the Serial console, "autoload" is true and "autoload_timeout" is exceeded. Usually the mtd1 (0x90010000) contains a compressed Linux kernel image.

ADAM2's "go" command moves mtd1 content to the RAM ADDRESS1 and runs it. This piece of code (zlib/LZMA piggyback) decompresses Linux kernel to RAM address 0x94020000, and runs it there. The decompressor uses ADAM2's "call vector" API to print a string on successful decompression.

The /proc/iomem contains a list of the physical addresses; to get the corresponding virtual kernel (KSEG0) addresses, add 0x80000000.

# cat /proc/iomem
00000000-13ffffff : reserved
14000000-1401ffff : System RAM
14020000-14ffffff : System RAM
  14020000-14169fdf : Kernel code
  14176300-14191fff : Kernel data
a8612800-a8612fff : eth0
#

Live Linux Kernel symbols (sorted) :

# cat/proc/ksyms
...
94024000 invalid_pte_table_Re30a91e5
94026000 init_task_union_R56b55918
94028a00 kernel_thread_R7e9ebb05
94028a68 get_wchan_R182e7552
9402c5a0 machine_restart_Re6e3ef70
9402c5c4 machine_halt_R9aa32630
9402c5e8 machine_power_off_R091c824a
...

Recovery app

Enrik Berkhan has written a perl program "recover" that mimics "recover.exe" for non-Windows users. It works for the AVM Fritz!Box device. Modifying it for the D-Link DSL-G604T should be trivial...

http://www.akk.org/~enrik/fbox/util/recover (perl script)
[Alternate link] http://web.archive.org/web/20041120225126/http://www.akk.org/~enrik/fbox/recover (perl script)
http://www.akk.org/~enrik/fbox/recovery.txt (German Language)

Linux config

The /dev/ticfg is a "raw" interface to the second half of the mtd3, where the /etc/config.xml stored:

# cat /dev/ticfg

The first two bytes seem to be a data length.

The entirety of mtd3 (/dev/mtdblock/3) contains a "raw" data of the ADAM2 environment and the config.xml data.

Retrieving MTD content

How to get a content of the any MTDs on running Linux:

As it is known, a ram-disk is mounted on /var. The idea is to copy a bulk MTD content to the /var and run a second copy of the thttp server to get it.

# cat /dev/mtdblock/2 > /var/mtd2.bin
# cat /dev/mtdblock/3 > /var/mtd3.bin
# /usr/sbin/thttpd -g -d /var -u root -p 1080

Then, open a following URL in any browser: "http://192.168.1.1:1080/" and get a mtd2.bin (ADAM2 code) and mtd3.bin (device configuration) files from this folder.

It is possible, of course, to use Busybox's TFTP command.

Other

ADAM2 (last edited 2011-09-12 19:25:14 by fa0-0)