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