JTAG pinout detector

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * JTAG pinout detector
00003  * Version 0.1
00004  * 2010-07-15
00005  *
00006  * Copyright (c) 2010 Igor Skochinsky
00007  *
00008  * This software is provided 'as-is', without any express or implied
00009  * warranty. In no event will the authors be held liable for any damages
00010  * arising from the use of this software.
00011  *
00012  * Permission is granted to anyone to use this software for any purpose,
00013  * including commercial applications, and to alter it and redistribute it
00014  * freely, subject to the following restrictions:
00015  *
00016  *    1. The origin of this software must not be misrepresented; you must not
00017  *    claim that you wrote the original software. If you use this software
00018  *    in a product, an acknowledgment in the product documentation would be
00019  *    appreciated but is not required.
00020  *
00021  *    2. Altered source versions must be plainly marked as such, and must not be
00022  *    misrepresented as being the original software.
00023  *
00024  *    3. This notice may not be removed or altered from any source
00025  *    distribution.
00026 */
00027 
00028 
00029 /*
00030 
00031  The overall idea:
00032  1) choose any 2 pins as TMS and TCK
00033  2) using them, reset TAP and then shift DR, while observing the state of all other pins
00034  3) for every pin that received anything like a TAP ID (i.e. bit 0 is 1):
00035  4)   using the pin as TDI, feed in a known pattern into the TAP
00036  5)   keep shifting and monitor the rest of the pins
00037  6)   if any of the remaining pins received the pattern, it is TDO
00038  
00039  Current algorithm assumes chain length of 1
00040  
00041 */
00042 
00043 #include "mbed.h"
00044 
00045 
00046 // pin description structure
00047 struct PinInfo
00048 {
00049   DigitalInOut pin;
00050   const char *name;
00051 };
00052 
00053 // define the pins to use for bruteforcing
00054 PinInfo g_pins[] = { 
00055     {p21, "pin 21", },
00056     {p22, "pin 22", },
00057     {p23, "pin 23", },
00058     {p24, "pin 24", },
00059     {p25, "pin 25", },
00060 };
00061 
00062 #define NPINS sizeof(g_pins)/sizeof(g_pins[0])
00063 
00064 // indexes of found pins
00065 int pin_TCK = -1;
00066 int pin_TMS = -1;
00067 int pin_TDO = -1;
00068 int pin_TDI = -1;
00069 
00070 inline const char *pinname(int pinno)
00071 {
00072   return pinno == -1 ? "unknown" : g_pins[pinno].name;
00073 }
00074 
00075 // print current layout
00076 inline void printpins()
00077 {
00078   printf("TCK: %s, TMS: %s, TDO: %s, TDI: %s\n",
00079     pinname(pin_TCK), pinname(pin_TMS), pinname(pin_TDO), pinname(pin_TDI));
00080 }
00081 
00082 // set pin with a given index
00083 inline void setpin(int pinno, int value)
00084 {
00085   g_pins[pinno].pin.write(value != 0);
00086 }
00087 
00088 // read pin with a given index
00089 inline int getpin(int pinno)
00090 {
00091   return g_pins[pinno].pin.read();
00092 }
00093 
00094 // make a pin output pin
00095 inline void makeoutput(int pinno)
00096 {
00097   g_pins[pinno].pin.output();
00098 }
00099 
00100 // make a pin input pin
00101 inline void makeinput(int pinno)
00102 {
00103   g_pins[pinno].pin.input();
00104 }
00105 
00106 // init all pins as inputs
00107 void InitGPIO()
00108 {
00109   for (int i=0; i<NPINS; i++)
00110     makeinput(i);
00111 }
00112 
00113 // feed in one tms pulse with given value
00114 void clock_tms(int tms)
00115 {
00116   //TMS is sampled by TAP on the rising edge of TCK, i.e. on change from 0 to 1
00117   //so the proper sequence is TCK=0; TMS=value; TCK=1
00118   setpin(pin_TCK, 0);
00119   setpin(pin_TMS, tms);
00120   //printpins(1);
00121   //Delay(1);
00122   setpin(pin_TCK, 1);
00123   //printpins(1);
00124   setpin(pin_TCK, 0);//to make sure the TDO value gets set
00125 }
00126 
00127 // same as above but also set the tdi and return tdo
00128 int clock_tms_tdi(int tms, int tdi)
00129 {
00130   setpin(pin_TCK, 0);
00131   setpin(pin_TMS, tms);
00132   setpin(pin_TDI, tdi);
00133   //printpins(2);
00134   //Delay(1);
00135   setpin(pin_TCK, 1);
00136   //printpins(2);
00137   setpin(pin_TCK, 0);//to make sure the TDO value gets set
00138   return getpin(pin_TDO);
00139 }
00140 
00141 // the end
00142 void exit_on_button(char* msg)
00143 {
00144   printf(msg);
00145   while(1);
00146 }
00147 
00148 const unsigned int pattern=0xAA55AA55;
00149 
00150 void try_tdi(int tdi)
00151 {
00152   int output;
00153   if (tdi==pin_TCK || tdi==pin_TMS || tdi==pin_TDO)
00154     return;  
00155   //at this point we know which pin is TDO
00156   //so we'll shift a known pattern into all possible TDIs and monitor the TDO
00157   //since we were shifting in garbage into them during reading the IDCODE, 
00158   //we'll skip the 32 bits of output while we're shifting in the pattern
00159   pin_TDI = tdi;
00160   printf("Trying %s as TDI\n", pinname(tdi));
00161   makeoutput(tdi);
00162 
00163   printpins();
00164   //reset TAP (11111)
00165   puts("Resetting TAP\n");
00166   clock_tms(1);clock_tms(1);clock_tms(1);clock_tms(1);clock_tms(1);
00167   //go to Shift DR (0100)
00168   puts("Go to Shift DR\n");
00169   clock_tms(0);clock_tms(1);clock_tms(0);clock_tms(0);
00170   puts("Shifting in pattern.\n");
00171   
00172   for (int i=0; i<32; i++)
00173   {
00174     //printf("%d: ",i);
00175     clock_tms_tdi(0, pattern & (1<<i));
00176     //puts(stringbuf);putc('\r');putc('\n');        
00177   }
00178   printf("Reading in the output.\n");
00179   //now keep shifting and read output from TDO
00180   output = 0;
00181   for (int i=0;i<32;i++)
00182   {
00183     //printf("%d: ",i);
00184     output |= getpin(pin_TDO) << i;
00185     clock_tms_tdi(0, 0);
00186     //puts(stringbuf);putc('\r');putc('\n');    
00187   }
00188   printf("Got %08X (expected %08X)\n", output, pattern);
00189   if (output==pattern)
00190   {
00191     printf("Success! Final pinout:\n");
00192     printpins();
00193     exit_on_button("Found!");
00194   }
00195   else if (output!=0 && output!=0xFFFFFFFF)
00196   {
00197     printf("Got some pattern but not ours...");
00198   }
00199   makeinput(tdi);
00200 }
00201 
00202 union idcode_reg {
00203   struct {
00204     unsigned int res: 1;
00205     unsigned int manuf_id: 11;
00206     unsigned int part_no: 16;
00207     unsigned int version: 4;
00208   };
00209   unsigned int reg32;
00210 };
00211 
00212 // check if we can see a valid TAP id on any of the pins
00213 void try_id()
00214 {
00215   int outputs[NPINS] = {0};
00216   printf("Trying TCK %s, TMS %s\n", pinname(pin_TCK), pinname(pin_TMS));
00217   makeoutput(pin_TCK);
00218   makeoutput(pin_TMS);
00219   printpins();
00220   //reset TAP (11111)
00221   printf("Resetting TAP\n");
00222   clock_tms(1);clock_tms(1);clock_tms(1);clock_tms(1);clock_tms(1);
00223   //go to Shift DR (0100)
00224   printf("Go to Shift DR\n");
00225   clock_tms(0);clock_tms(1);clock_tms(0);clock_tms(0);
00226   //shift out the DR
00227   printf("Shifting DR\n");
00228   //printpins(1);
00229   //puts(stringbuf);putc('\r');putc('\n');
00230   for (int i=0;i<32;i++)
00231   {
00232     //printf("%d: ",i);
00233     for (int j=0;j<NPINS;j++)
00234     {
00235       if (j!=pin_TCK && j!=pin_TMS)
00236         outputs[j] |= getpin(j) << i;
00237     }
00238     clock_tms(0);
00239     //puts(stringbuf);putc('\r');putc('\n');
00240     //printpins(1);
00241   }
00242   puts("Done. Checking pin outputs.\n");
00243   bool found = false;
00244   for (int j=0;j<NPINS;j++)
00245   {
00246     if (j==pin_TCK || j==pin_TMS) 
00247       continue;
00248     //printf("%2d: %08X\n", j, outputs[j]);    
00249     //check for possible ID code: 32 bits captured are not all zeroes or ones and the 0th bit is 1
00250     if (outputs[j]!=0 && outputs[j]!=0xFFFFFFFF && (outputs[j]&1) )
00251     {
00252       found = true;
00253       union idcode_reg idc;
00254       idc.reg32 = outputs[j];
00255       printf("Found a possible TDO on %s. ID code reply is %08X (manufacturer: %02X, part no.: %02X, version: %X)\n",
00256         pinname(j), outputs[j], idc.manuf_id, idc.part_no, idc.version);
00257       pin_TDO = j;
00258       for (int k=0;k<NPINS;k++)
00259         try_tdi(k);
00260     }
00261   }
00262   if ( !found )
00263     printf("Didn't find any good reply...\n");
00264   makeinput(pin_TCK);
00265   makeinput(pin_TMS);
00266 }
00267 
00268 // try the selected pins
00269 void try_comb(int v[], int maxk)
00270 {
00271     //for (int i=0; i<maxk; i++) printf ("%i ", v[i]);
00272     //printf ("\n");
00273     pin_TCK = v[0];
00274     pin_TMS = v[1];
00275     try_id();
00276     pin_TCK = v[1];
00277     pin_TMS = v[0];
00278     try_id();
00279 }
00280 
00281 // source: http://userweb.cs.utexas.edu/users/djimenez/utsa/cs3343/lecture25.html
00282 void combinations(int v[], int start, int n, int k, int maxk)
00283 {
00284     int     i;
00285     /* k here counts through positions in the maxk-element v.
00286      * if k >= maxk, then the v is complete and we can use it.
00287      */
00288     if ( k >= maxk )
00289     {
00290         try_comb(v, maxk);
00291         return;
00292     }
00293 
00294     /* for this k'th element of the v, try all start..n
00295      * elements in that position
00296      */
00297     for (i=start; i<n; i++)
00298     {
00299         v[k] = i;
00300         /* recursively generate combinations of integers
00301          * from i+1..n
00302          */
00303         combinations (v, i+1, n, k+1, maxk);
00304     }
00305 }
00306 
00307 int main()
00308 {
00309     int v[NPINS];
00310     InitGPIO();
00311     // try all combinations of 2 pins
00312     combinations (v, 0, NPINS, 0, 2);
00313 }