9d7e0fce848dca903340ddff1e3c96ca3e3f9f9a
[fw/openocd] / tcl / tools / firmware-recovery.tcl
1 echo "\n\nFirmware recovery helpers"
2 echo "Use -c firmware_help to get help\n"
3
4 set known_boards {
5     "asus-rt-n16                ASUS RT-N16"
6     "asus-rt-n66u               ASUS RT-N66U"
7     "linksys-wag200g            Linksys WAG200G"
8     "linksys-wrt54gl            Linksys WRT54GL v1.1"
9     "netgear-dg834v3            Netgear DG834G v3"
10     "tp-link_tl-mr3020          TP-LINK TL-MR3020"
11     "bt-homehubv1               BT HomeHub v1"
12 }
13
14 proc firmware_help { } {
15     echo "
16 Your OpenOCD command should look like this:
17 openocd -f interface/<jtag adapter>.cfg -f tools/firmware-recovery.tcl -c \"<commands>*; shutdown\"
18
19 Where:
20 <jtag adapter> is one of the supported devices, e.g. ftdi/jtagkey2
21 <commands> are firmware-recovery commands separated by semicolon
22
23 Supported commands:
24 firmware_help                   get this help
25 list_boards                     list known boards and exit
26 board <name>                    select board you work with
27 list_partitions                 list partitions of the currently selected board
28 dump_part <name> <filename>     save partition's contents to a file
29 erase_part <name>               erase the given partition
30 flash_part <name> <filename>    erase, flash and verify the given partition
31 ram_boot <filename>             load binary file to RAM and run it
32 adapter speed <freq>            set JTAG clock frequency in kHz
33
34 For example, to clear nvram and reflash CFE on an RT-N16 using TUMPA, run:
35 openocd -f interface/ftdi/tumpa.cfg -f tools/firmware-recovery.tcl \\
36         -c \"board asus-rt-n16; erase_part nvram; flash_part CFE cfe-n16.bin; shutdown\"
37 \n\n"
38     shutdown
39 }
40
41 # set default, can be overridden later
42 adapter speed 1000
43
44 proc get_partition { name } {
45     global partition_list
46     dict get $partition_list $name
47 }
48
49 proc partition_desc { name } { lindex [get_partition $name] 0 }
50 proc partition_start { name } { lindex [get_partition $name] 1 }
51 proc partition_size { name } { lindex [get_partition $name] 2 }
52
53 proc list_boards { } {
54     global known_boards
55     echo "List of the supported boards:\n"
56     echo "Board name\t\tDescription"
57     echo "-----------------------------------"
58     foreach i $known_boards {
59         echo $i
60     }
61     echo "\n\n"
62 }
63
64 proc board { name } {
65     script [find board/$name.cfg]
66 }
67
68 proc list_partitions { } {
69     global partition_list
70     set fstr "%-16s%-14s%-14s%s"
71     echo "\nThe currently selected board is known to have these partitions:\n"
72     echo [format $fstr Name Start Size Description]
73     echo "-------------------------------------------------------"
74     for {set i 0} {$i < [llength $partition_list]} {incr i 2} {
75         set key [lindex $partition_list $i]
76         echo [format $fstr $key [partition_start $key] [partition_size $key] [partition_desc $key]]
77     }
78     echo "\n\n"
79 }
80
81 # Magic to work with any targets, including semi-functional
82 proc prepare_target { } {
83     init
84     catch {halt}
85     catch {reset init}
86     catch {halt}
87 }
88
89 proc dump_part { name filename } {
90     prepare_target
91     dump_image $filename [partition_start $name] [partition_size $name]
92 }
93
94 proc erase_part { name } {
95     prepare_target
96     flash erase_address [partition_start $name] [partition_size $name]
97 }
98
99 proc flash_part { name filename } {
100     prepare_target
101     flash write_image erase $filename [partition_start $name] bin
102     echo "Verifying:"
103     verify_image $filename [partition_start $name]
104 }
105
106 proc ram_boot { filename } {
107     global ram_boot_address
108     prepare_target
109     load_image $filename $ram_boot_address bin
110     resume $ram_boot_address
111 }
112
113 echo ""