Igor Skochinsky
/
JTAG_Search
JTAG pinout detector
main.cpp@0:948e97043afb, 2010-07-14 (annotated)
- Committer:
- igorsk
- Date:
- Wed Jul 14 23:20:48 2010 +0000
- Revision:
- 0:948e97043afb
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
igorsk | 0:948e97043afb | 1 | /* |
igorsk | 0:948e97043afb | 2 | * JTAG pinout detector |
igorsk | 0:948e97043afb | 3 | * Version 0.1 |
igorsk | 0:948e97043afb | 4 | * 2010-07-15 |
igorsk | 0:948e97043afb | 5 | * |
igorsk | 0:948e97043afb | 6 | * Copyright (c) 2010 Igor Skochinsky |
igorsk | 0:948e97043afb | 7 | * |
igorsk | 0:948e97043afb | 8 | * This software is provided 'as-is', without any express or implied |
igorsk | 0:948e97043afb | 9 | * warranty. In no event will the authors be held liable for any damages |
igorsk | 0:948e97043afb | 10 | * arising from the use of this software. |
igorsk | 0:948e97043afb | 11 | * |
igorsk | 0:948e97043afb | 12 | * Permission is granted to anyone to use this software for any purpose, |
igorsk | 0:948e97043afb | 13 | * including commercial applications, and to alter it and redistribute it |
igorsk | 0:948e97043afb | 14 | * freely, subject to the following restrictions: |
igorsk | 0:948e97043afb | 15 | * |
igorsk | 0:948e97043afb | 16 | * 1. The origin of this software must not be misrepresented; you must not |
igorsk | 0:948e97043afb | 17 | * claim that you wrote the original software. If you use this software |
igorsk | 0:948e97043afb | 18 | * in a product, an acknowledgment in the product documentation would be |
igorsk | 0:948e97043afb | 19 | * appreciated but is not required. |
igorsk | 0:948e97043afb | 20 | * |
igorsk | 0:948e97043afb | 21 | * 2. Altered source versions must be plainly marked as such, and must not be |
igorsk | 0:948e97043afb | 22 | * misrepresented as being the original software. |
igorsk | 0:948e97043afb | 23 | * |
igorsk | 0:948e97043afb | 24 | * 3. This notice may not be removed or altered from any source |
igorsk | 0:948e97043afb | 25 | * distribution. |
igorsk | 0:948e97043afb | 26 | */ |
igorsk | 0:948e97043afb | 27 | |
igorsk | 0:948e97043afb | 28 | |
igorsk | 0:948e97043afb | 29 | /* |
igorsk | 0:948e97043afb | 30 | |
igorsk | 0:948e97043afb | 31 | The overall idea: |
igorsk | 0:948e97043afb | 32 | 1) choose any 2 pins as TMS and TCK |
igorsk | 0:948e97043afb | 33 | 2) using them, reset TAP and then shift DR, while observing the state of all other pins |
igorsk | 0:948e97043afb | 34 | 3) for every pin that received anything like a TAP ID (i.e. bit 0 is 1): |
igorsk | 0:948e97043afb | 35 | 4) using the pin as TDI, feed in a known pattern into the TAP |
igorsk | 0:948e97043afb | 36 | 5) keep shifting and monitor the rest of the pins |
igorsk | 0:948e97043afb | 37 | 6) if any of the remaining pins received the pattern, it is TDO |
igorsk | 0:948e97043afb | 38 | |
igorsk | 0:948e97043afb | 39 | Current algorithm assumes chain length of 1 |
igorsk | 0:948e97043afb | 40 | |
igorsk | 0:948e97043afb | 41 | */ |
igorsk | 0:948e97043afb | 42 | |
igorsk | 0:948e97043afb | 43 | #include "mbed.h" |
igorsk | 0:948e97043afb | 44 | |
igorsk | 0:948e97043afb | 45 | |
igorsk | 0:948e97043afb | 46 | // pin description structure |
igorsk | 0:948e97043afb | 47 | struct PinInfo |
igorsk | 0:948e97043afb | 48 | { |
igorsk | 0:948e97043afb | 49 | DigitalInOut pin; |
igorsk | 0:948e97043afb | 50 | const char *name; |
igorsk | 0:948e97043afb | 51 | }; |
igorsk | 0:948e97043afb | 52 | |
igorsk | 0:948e97043afb | 53 | // define the pins to use for bruteforcing |
igorsk | 0:948e97043afb | 54 | PinInfo g_pins[] = { |
igorsk | 0:948e97043afb | 55 | {p21, "pin 21", }, |
igorsk | 0:948e97043afb | 56 | {p22, "pin 22", }, |
igorsk | 0:948e97043afb | 57 | {p23, "pin 23", }, |
igorsk | 0:948e97043afb | 58 | {p24, "pin 24", }, |
igorsk | 0:948e97043afb | 59 | {p25, "pin 25", }, |
igorsk | 0:948e97043afb | 60 | }; |
igorsk | 0:948e97043afb | 61 | |
igorsk | 0:948e97043afb | 62 | #define NPINS sizeof(g_pins)/sizeof(g_pins[0]) |
igorsk | 0:948e97043afb | 63 | |
igorsk | 0:948e97043afb | 64 | // indexes of found pins |
igorsk | 0:948e97043afb | 65 | int pin_TCK = -1; |
igorsk | 0:948e97043afb | 66 | int pin_TMS = -1; |
igorsk | 0:948e97043afb | 67 | int pin_TDO = -1; |
igorsk | 0:948e97043afb | 68 | int pin_TDI = -1; |
igorsk | 0:948e97043afb | 69 | |
igorsk | 0:948e97043afb | 70 | inline const char *pinname(int pinno) |
igorsk | 0:948e97043afb | 71 | { |
igorsk | 0:948e97043afb | 72 | return pinno == -1 ? "unknown" : g_pins[pinno].name; |
igorsk | 0:948e97043afb | 73 | } |
igorsk | 0:948e97043afb | 74 | |
igorsk | 0:948e97043afb | 75 | // print current layout |
igorsk | 0:948e97043afb | 76 | inline void printpins() |
igorsk | 0:948e97043afb | 77 | { |
igorsk | 0:948e97043afb | 78 | printf("TCK: %s, TMS: %s, TDO: %s, TDI: %s\n", |
igorsk | 0:948e97043afb | 79 | pinname(pin_TCK), pinname(pin_TMS), pinname(pin_TDO), pinname(pin_TDI)); |
igorsk | 0:948e97043afb | 80 | } |
igorsk | 0:948e97043afb | 81 | |
igorsk | 0:948e97043afb | 82 | // set pin with a given index |
igorsk | 0:948e97043afb | 83 | inline void setpin(int pinno, int value) |
igorsk | 0:948e97043afb | 84 | { |
igorsk | 0:948e97043afb | 85 | g_pins[pinno].pin.write(value != 0); |
igorsk | 0:948e97043afb | 86 | } |
igorsk | 0:948e97043afb | 87 | |
igorsk | 0:948e97043afb | 88 | // read pin with a given index |
igorsk | 0:948e97043afb | 89 | inline int getpin(int pinno) |
igorsk | 0:948e97043afb | 90 | { |
igorsk | 0:948e97043afb | 91 | return g_pins[pinno].pin.read(); |
igorsk | 0:948e97043afb | 92 | } |
igorsk | 0:948e97043afb | 93 | |
igorsk | 0:948e97043afb | 94 | // make a pin output pin |
igorsk | 0:948e97043afb | 95 | inline void makeoutput(int pinno) |
igorsk | 0:948e97043afb | 96 | { |
igorsk | 0:948e97043afb | 97 | g_pins[pinno].pin.output(); |
igorsk | 0:948e97043afb | 98 | } |
igorsk | 0:948e97043afb | 99 | |
igorsk | 0:948e97043afb | 100 | // make a pin input pin |
igorsk | 0:948e97043afb | 101 | inline void makeinput(int pinno) |
igorsk | 0:948e97043afb | 102 | { |
igorsk | 0:948e97043afb | 103 | g_pins[pinno].pin.input(); |
igorsk | 0:948e97043afb | 104 | } |
igorsk | 0:948e97043afb | 105 | |
igorsk | 0:948e97043afb | 106 | // init all pins as inputs |
igorsk | 0:948e97043afb | 107 | void InitGPIO() |
igorsk | 0:948e97043afb | 108 | { |
igorsk | 0:948e97043afb | 109 | for (int i=0; i<NPINS; i++) |
igorsk | 0:948e97043afb | 110 | makeinput(i); |
igorsk | 0:948e97043afb | 111 | } |
igorsk | 0:948e97043afb | 112 | |
igorsk | 0:948e97043afb | 113 | // feed in one tms pulse with given value |
igorsk | 0:948e97043afb | 114 | void clock_tms(int tms) |
igorsk | 0:948e97043afb | 115 | { |
igorsk | 0:948e97043afb | 116 | //TMS is sampled by TAP on the rising edge of TCK, i.e. on change from 0 to 1 |
igorsk | 0:948e97043afb | 117 | //so the proper sequence is TCK=0; TMS=value; TCK=1 |
igorsk | 0:948e97043afb | 118 | setpin(pin_TCK, 0); |
igorsk | 0:948e97043afb | 119 | setpin(pin_TMS, tms); |
igorsk | 0:948e97043afb | 120 | //printpins(1); |
igorsk | 0:948e97043afb | 121 | //Delay(1); |
igorsk | 0:948e97043afb | 122 | setpin(pin_TCK, 1); |
igorsk | 0:948e97043afb | 123 | //printpins(1); |
igorsk | 0:948e97043afb | 124 | setpin(pin_TCK, 0);//to make sure the TDO value gets set |
igorsk | 0:948e97043afb | 125 | } |
igorsk | 0:948e97043afb | 126 | |
igorsk | 0:948e97043afb | 127 | // same as above but also set the tdi and return tdo |
igorsk | 0:948e97043afb | 128 | int clock_tms_tdi(int tms, int tdi) |
igorsk | 0:948e97043afb | 129 | { |
igorsk | 0:948e97043afb | 130 | setpin(pin_TCK, 0); |
igorsk | 0:948e97043afb | 131 | setpin(pin_TMS, tms); |
igorsk | 0:948e97043afb | 132 | setpin(pin_TDI, tdi); |
igorsk | 0:948e97043afb | 133 | //printpins(2); |
igorsk | 0:948e97043afb | 134 | //Delay(1); |
igorsk | 0:948e97043afb | 135 | setpin(pin_TCK, 1); |
igorsk | 0:948e97043afb | 136 | //printpins(2); |
igorsk | 0:948e97043afb | 137 | setpin(pin_TCK, 0);//to make sure the TDO value gets set |
igorsk | 0:948e97043afb | 138 | return getpin(pin_TDO); |
igorsk | 0:948e97043afb | 139 | } |
igorsk | 0:948e97043afb | 140 | |
igorsk | 0:948e97043afb | 141 | // the end |
igorsk | 0:948e97043afb | 142 | void exit_on_button(char* msg) |
igorsk | 0:948e97043afb | 143 | { |
igorsk | 0:948e97043afb | 144 | printf(msg); |
igorsk | 0:948e97043afb | 145 | while(1); |
igorsk | 0:948e97043afb | 146 | } |
igorsk | 0:948e97043afb | 147 | |
igorsk | 0:948e97043afb | 148 | const unsigned int pattern=0xAA55AA55; |
igorsk | 0:948e97043afb | 149 | |
igorsk | 0:948e97043afb | 150 | void try_tdi(int tdi) |
igorsk | 0:948e97043afb | 151 | { |
igorsk | 0:948e97043afb | 152 | int output; |
igorsk | 0:948e97043afb | 153 | if (tdi==pin_TCK || tdi==pin_TMS || tdi==pin_TDO) |
igorsk | 0:948e97043afb | 154 | return; |
igorsk | 0:948e97043afb | 155 | //at this point we know which pin is TDO |
igorsk | 0:948e97043afb | 156 | //so we'll shift a known pattern into all possible TDIs and monitor the TDO |
igorsk | 0:948e97043afb | 157 | //since we were shifting in garbage into them during reading the IDCODE, |
igorsk | 0:948e97043afb | 158 | //we'll skip the 32 bits of output while we're shifting in the pattern |
igorsk | 0:948e97043afb | 159 | pin_TDI = tdi; |
igorsk | 0:948e97043afb | 160 | printf("Trying %s as TDI\n", pinname(tdi)); |
igorsk | 0:948e97043afb | 161 | makeoutput(tdi); |
igorsk | 0:948e97043afb | 162 | |
igorsk | 0:948e97043afb | 163 | printpins(); |
igorsk | 0:948e97043afb | 164 | //reset TAP (11111) |
igorsk | 0:948e97043afb | 165 | puts("Resetting TAP\n"); |
igorsk | 0:948e97043afb | 166 | clock_tms(1);clock_tms(1);clock_tms(1);clock_tms(1);clock_tms(1); |
igorsk | 0:948e97043afb | 167 | //go to Shift DR (0100) |
igorsk | 0:948e97043afb | 168 | puts("Go to Shift DR\n"); |
igorsk | 0:948e97043afb | 169 | clock_tms(0);clock_tms(1);clock_tms(0);clock_tms(0); |
igorsk | 0:948e97043afb | 170 | puts("Shifting in pattern.\n"); |
igorsk | 0:948e97043afb | 171 | |
igorsk | 0:948e97043afb | 172 | for (int i=0; i<32; i++) |
igorsk | 0:948e97043afb | 173 | { |
igorsk | 0:948e97043afb | 174 | //printf("%d: ",i); |
igorsk | 0:948e97043afb | 175 | clock_tms_tdi(0, pattern & (1<<i)); |
igorsk | 0:948e97043afb | 176 | //puts(stringbuf);putc('\r');putc('\n'); |
igorsk | 0:948e97043afb | 177 | } |
igorsk | 0:948e97043afb | 178 | printf("Reading in the output.\n"); |
igorsk | 0:948e97043afb | 179 | //now keep shifting and read output from TDO |
igorsk | 0:948e97043afb | 180 | output = 0; |
igorsk | 0:948e97043afb | 181 | for (int i=0;i<32;i++) |
igorsk | 0:948e97043afb | 182 | { |
igorsk | 0:948e97043afb | 183 | //printf("%d: ",i); |
igorsk | 0:948e97043afb | 184 | output |= getpin(pin_TDO) << i; |
igorsk | 0:948e97043afb | 185 | clock_tms_tdi(0, 0); |
igorsk | 0:948e97043afb | 186 | //puts(stringbuf);putc('\r');putc('\n'); |
igorsk | 0:948e97043afb | 187 | } |
igorsk | 0:948e97043afb | 188 | printf("Got %08X (expected %08X)\n", output, pattern); |
igorsk | 0:948e97043afb | 189 | if (output==pattern) |
igorsk | 0:948e97043afb | 190 | { |
igorsk | 0:948e97043afb | 191 | printf("Success! Final pinout:\n"); |
igorsk | 0:948e97043afb | 192 | printpins(); |
igorsk | 0:948e97043afb | 193 | exit_on_button("Found!"); |
igorsk | 0:948e97043afb | 194 | } |
igorsk | 0:948e97043afb | 195 | else if (output!=0 && output!=0xFFFFFFFF) |
igorsk | 0:948e97043afb | 196 | { |
igorsk | 0:948e97043afb | 197 | printf("Got some pattern but not ours..."); |
igorsk | 0:948e97043afb | 198 | } |
igorsk | 0:948e97043afb | 199 | makeinput(tdi); |
igorsk | 0:948e97043afb | 200 | } |
igorsk | 0:948e97043afb | 201 | |
igorsk | 0:948e97043afb | 202 | union idcode_reg { |
igorsk | 0:948e97043afb | 203 | struct { |
igorsk | 0:948e97043afb | 204 | unsigned int res: 1; |
igorsk | 0:948e97043afb | 205 | unsigned int manuf_id: 11; |
igorsk | 0:948e97043afb | 206 | unsigned int part_no: 16; |
igorsk | 0:948e97043afb | 207 | unsigned int version: 4; |
igorsk | 0:948e97043afb | 208 | }; |
igorsk | 0:948e97043afb | 209 | unsigned int reg32; |
igorsk | 0:948e97043afb | 210 | }; |
igorsk | 0:948e97043afb | 211 | |
igorsk | 0:948e97043afb | 212 | // check if we can see a valid TAP id on any of the pins |
igorsk | 0:948e97043afb | 213 | void try_id() |
igorsk | 0:948e97043afb | 214 | { |
igorsk | 0:948e97043afb | 215 | int outputs[NPINS] = {0}; |
igorsk | 0:948e97043afb | 216 | printf("Trying TCK %s, TMS %s\n", pinname(pin_TCK), pinname(pin_TMS)); |
igorsk | 0:948e97043afb | 217 | makeoutput(pin_TCK); |
igorsk | 0:948e97043afb | 218 | makeoutput(pin_TMS); |
igorsk | 0:948e97043afb | 219 | printpins(); |
igorsk | 0:948e97043afb | 220 | //reset TAP (11111) |
igorsk | 0:948e97043afb | 221 | printf("Resetting TAP\n"); |
igorsk | 0:948e97043afb | 222 | clock_tms(1);clock_tms(1);clock_tms(1);clock_tms(1);clock_tms(1); |
igorsk | 0:948e97043afb | 223 | //go to Shift DR (0100) |
igorsk | 0:948e97043afb | 224 | printf("Go to Shift DR\n"); |
igorsk | 0:948e97043afb | 225 | clock_tms(0);clock_tms(1);clock_tms(0);clock_tms(0); |
igorsk | 0:948e97043afb | 226 | //shift out the DR |
igorsk | 0:948e97043afb | 227 | printf("Shifting DR\n"); |
igorsk | 0:948e97043afb | 228 | //printpins(1); |
igorsk | 0:948e97043afb | 229 | //puts(stringbuf);putc('\r');putc('\n'); |
igorsk | 0:948e97043afb | 230 | for (int i=0;i<32;i++) |
igorsk | 0:948e97043afb | 231 | { |
igorsk | 0:948e97043afb | 232 | //printf("%d: ",i); |
igorsk | 0:948e97043afb | 233 | for (int j=0;j<NPINS;j++) |
igorsk | 0:948e97043afb | 234 | { |
igorsk | 0:948e97043afb | 235 | if (j!=pin_TCK && j!=pin_TMS) |
igorsk | 0:948e97043afb | 236 | outputs[j] |= getpin(j) << i; |
igorsk | 0:948e97043afb | 237 | } |
igorsk | 0:948e97043afb | 238 | clock_tms(0); |
igorsk | 0:948e97043afb | 239 | //puts(stringbuf);putc('\r');putc('\n'); |
igorsk | 0:948e97043afb | 240 | //printpins(1); |
igorsk | 0:948e97043afb | 241 | } |
igorsk | 0:948e97043afb | 242 | puts("Done. Checking pin outputs.\n"); |
igorsk | 0:948e97043afb | 243 | bool found = false; |
igorsk | 0:948e97043afb | 244 | for (int j=0;j<NPINS;j++) |
igorsk | 0:948e97043afb | 245 | { |
igorsk | 0:948e97043afb | 246 | if (j==pin_TCK || j==pin_TMS) |
igorsk | 0:948e97043afb | 247 | continue; |
igorsk | 0:948e97043afb | 248 | //printf("%2d: %08X\n", j, outputs[j]); |
igorsk | 0:948e97043afb | 249 | //check for possible ID code: 32 bits captured are not all zeroes or ones and the 0th bit is 1 |
igorsk | 0:948e97043afb | 250 | if (outputs[j]!=0 && outputs[j]!=0xFFFFFFFF && (outputs[j]&1) ) |
igorsk | 0:948e97043afb | 251 | { |
igorsk | 0:948e97043afb | 252 | found = true; |
igorsk | 0:948e97043afb | 253 | union idcode_reg idc; |
igorsk | 0:948e97043afb | 254 | idc.reg32 = outputs[j]; |
igorsk | 0:948e97043afb | 255 | printf("Found a possible TDO on %s. ID code reply is %08X (manufacturer: %02X, part no.: %02X, version: %X)\n", |
igorsk | 0:948e97043afb | 256 | pinname(j), outputs[j], idc.manuf_id, idc.part_no, idc.version); |
igorsk | 0:948e97043afb | 257 | pin_TDO = j; |
igorsk | 0:948e97043afb | 258 | for (int k=0;k<NPINS;k++) |
igorsk | 0:948e97043afb | 259 | try_tdi(k); |
igorsk | 0:948e97043afb | 260 | } |
igorsk | 0:948e97043afb | 261 | } |
igorsk | 0:948e97043afb | 262 | if ( !found ) |
igorsk | 0:948e97043afb | 263 | printf("Didn't find any good reply...\n"); |
igorsk | 0:948e97043afb | 264 | makeinput(pin_TCK); |
igorsk | 0:948e97043afb | 265 | makeinput(pin_TMS); |
igorsk | 0:948e97043afb | 266 | } |
igorsk | 0:948e97043afb | 267 | |
igorsk | 0:948e97043afb | 268 | // try the selected pins |
igorsk | 0:948e97043afb | 269 | void try_comb(int v[], int maxk) |
igorsk | 0:948e97043afb | 270 | { |
igorsk | 0:948e97043afb | 271 | //for (int i=0; i<maxk; i++) printf ("%i ", v[i]); |
igorsk | 0:948e97043afb | 272 | //printf ("\n"); |
igorsk | 0:948e97043afb | 273 | pin_TCK = v[0]; |
igorsk | 0:948e97043afb | 274 | pin_TMS = v[1]; |
igorsk | 0:948e97043afb | 275 | try_id(); |
igorsk | 0:948e97043afb | 276 | pin_TCK = v[1]; |
igorsk | 0:948e97043afb | 277 | pin_TMS = v[0]; |
igorsk | 0:948e97043afb | 278 | try_id(); |
igorsk | 0:948e97043afb | 279 | } |
igorsk | 0:948e97043afb | 280 | |
igorsk | 0:948e97043afb | 281 | // source: http://userweb.cs.utexas.edu/users/djimenez/utsa/cs3343/lecture25.html |
igorsk | 0:948e97043afb | 282 | void combinations(int v[], int start, int n, int k, int maxk) |
igorsk | 0:948e97043afb | 283 | { |
igorsk | 0:948e97043afb | 284 | int i; |
igorsk | 0:948e97043afb | 285 | /* k here counts through positions in the maxk-element v. |
igorsk | 0:948e97043afb | 286 | * if k >= maxk, then the v is complete and we can use it. |
igorsk | 0:948e97043afb | 287 | */ |
igorsk | 0:948e97043afb | 288 | if ( k >= maxk ) |
igorsk | 0:948e97043afb | 289 | { |
igorsk | 0:948e97043afb | 290 | try_comb(v, maxk); |
igorsk | 0:948e97043afb | 291 | return; |
igorsk | 0:948e97043afb | 292 | } |
igorsk | 0:948e97043afb | 293 | |
igorsk | 0:948e97043afb | 294 | /* for this k'th element of the v, try all start..n |
igorsk | 0:948e97043afb | 295 | * elements in that position |
igorsk | 0:948e97043afb | 296 | */ |
igorsk | 0:948e97043afb | 297 | for (i=start; i<n; i++) |
igorsk | 0:948e97043afb | 298 | { |
igorsk | 0:948e97043afb | 299 | v[k] = i; |
igorsk | 0:948e97043afb | 300 | /* recursively generate combinations of integers |
igorsk | 0:948e97043afb | 301 | * from i+1..n |
igorsk | 0:948e97043afb | 302 | */ |
igorsk | 0:948e97043afb | 303 | combinations (v, i+1, n, k+1, maxk); |
igorsk | 0:948e97043afb | 304 | } |
igorsk | 0:948e97043afb | 305 | } |
igorsk | 0:948e97043afb | 306 | |
igorsk | 0:948e97043afb | 307 | int main() |
igorsk | 0:948e97043afb | 308 | { |
igorsk | 0:948e97043afb | 309 | int v[NPINS]; |
igorsk | 0:948e97043afb | 310 | InitGPIO(); |
igorsk | 0:948e97043afb | 311 | // try all combinations of 2 pins |
igorsk | 0:948e97043afb | 312 | combinations (v, 0, NPINS, 0, 2); |
igorsk | 0:948e97043afb | 313 | } |