9d98f8b7a7
The Linksys WAG200G router has a TI AR7 SoC and a 4MB Flash layout similar to the Netgear DG834v3 router [1]. Below is an example of a successful flash recovery, using a TUMPA, connected to the MIPS EJTAG 2.6 header (JP102) of the router. WAG200G [2] TUMPA [3] Desc Pin Pin Desc ------------------------ nTRST 1 3 nTRST TDI 3 5 TDI TDO 5 13 TDO TMS 7 7 TMS TCK 9 9 TCK nSRST 11 15 RST GND 2 4 GND Note that nSRST is optional to halt the CPU, but is required to probe the flash. For instance, recover the kernel with: $ sudo ./src/openocd -s tcl \ -f interface/ftdi/tumpa.cfg \ -f tools/firmware-recovery.tcl \ -c 'board linksys-wag200g; reset_config srst_only; flash_part kernel /path/to/kernel.bin; shutdown' [1] https://wiki.openwrt.org/toh/linksys/wag200g [2] https://www.linux-mips.org/wiki/JTAG#JTAG_headers [3] http://www.tiaowiki.com/w/TIAO_USB_Multi_Protocol_Adapter_User's_Manual#20_PIN_JTAG_Connector Change-Id: I952ba9f706e2e4f8f95ca03a5fa58f391ca030b6 Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Reviewed-on: http://openocd.zylin.com/3776 Tested-by: jenkins Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
114 lines
3.3 KiB
Tcl
114 lines
3.3 KiB
Tcl
echo "\n\nFirmware recovery helpers"
|
|
echo "Use -c firmware_help to get help\n"
|
|
|
|
set known_boards {
|
|
"asus-rt-n16 ASUS RT-N16"
|
|
"asus-rt-n66u ASUS RT-N66U"
|
|
"linksys-wag200g Linksys WAG200G"
|
|
"linksys-wrt54gl Linksys WRT54GL v1.1"
|
|
"netgear-dg834v3 Netgear DG834G v3"
|
|
"tp-link_tl-mr3020 TP-LINK TL-MR3020"
|
|
"bt-homehubv1 BT HomeHub v1"
|
|
}
|
|
|
|
proc firmware_help { } {
|
|
echo "
|
|
Your OpenOCD command should look like this:
|
|
openocd -f interface/<jtag adapter>.cfg -f tools/firmware-recovery.tcl -c \"<commands>*; shutdown\"
|
|
|
|
Where:
|
|
<jtag adapter> is one of the supported devices, e.g. ftdi/jtagkey2
|
|
<commands> are firmware-recovery commands separated by semicolon
|
|
|
|
Supported commands:
|
|
firmware_help get this help
|
|
list_boards list known boards and exit
|
|
board <name> select board you work with
|
|
list_partitions list partitions of the currently selected board
|
|
dump_part <name> <filename> save partition's contents to a file
|
|
erase_part <name> erase the given partition
|
|
flash_part <name> <filename> erase, flash and verify the given partition
|
|
ram_boot <filename> load binary file to RAM and run it
|
|
adapter_khz <freq> set JTAG clock frequency in kHz
|
|
|
|
For example, to clear nvram and reflash CFE on an RT-N16 using TUMPA, run:
|
|
openocd -f interface/ftdi/tumpa.cfg -f tools/firmware-recovery.tcl \\
|
|
-c \"board asus-rt-n16; erase_part nvram; flash_part CFE cfe-n16.bin; shutdown\"
|
|
\n\n"
|
|
shutdown
|
|
}
|
|
|
|
# set default, can be overriden later
|
|
adapter_khz 1000
|
|
|
|
proc get_partition { name } {
|
|
global partition_list
|
|
dict get $partition_list $name
|
|
}
|
|
|
|
proc partition_desc { name } { lindex [get_partition $name] 0 }
|
|
proc partition_start { name } { lindex [get_partition $name] 1 }
|
|
proc partition_size { name } { lindex [get_partition $name] 2 }
|
|
|
|
proc list_boards { } {
|
|
global known_boards
|
|
echo "List of the supported boards:\n"
|
|
echo "Board name\t\tDescription"
|
|
echo "-----------------------------------"
|
|
foreach i $known_boards {
|
|
echo $i
|
|
}
|
|
echo "\n\n"
|
|
}
|
|
|
|
proc board { name } {
|
|
script [find board/$name.cfg]
|
|
}
|
|
|
|
proc list_partitions { } {
|
|
global partition_list
|
|
set fstr "%-16s%-14s%-14s%s"
|
|
echo "\nThe currently selected board is known to have these partitions:\n"
|
|
echo [format $fstr Name Start Size Description]
|
|
echo "-------------------------------------------------------"
|
|
for {set i 0} {$i < [llength $partition_list]} {incr i 2} {
|
|
set key [lindex $partition_list $i]
|
|
echo [format $fstr $key [partition_start $key] [partition_size $key] [partition_desc $key]]
|
|
}
|
|
echo "\n\n"
|
|
}
|
|
|
|
# Magic to work with any targets, including semi-functional
|
|
proc prepare_target { } {
|
|
init
|
|
catch {halt}
|
|
catch {reset init}
|
|
catch {halt}
|
|
}
|
|
|
|
proc dump_part { name filename } {
|
|
prepare_target
|
|
dump_image $filename [partition_start $name] [partition_size $name]
|
|
}
|
|
|
|
proc erase_part { name } {
|
|
prepare_target
|
|
flash erase_address [partition_start $name] [partition_size $name]
|
|
}
|
|
|
|
proc flash_part { name filename } {
|
|
prepare_target
|
|
flash write_image erase $filename [partition_start $name] bin
|
|
echo "Verifying:"
|
|
verify_image $filename [partition_start $name]
|
|
}
|
|
|
|
proc ram_boot { filename } {
|
|
global ram_boot_address
|
|
prepare_target
|
|
load_image $filename $ram_boot_address bin
|
|
resume $ram_boot_address
|
|
}
|
|
|
|
echo ""
|