Что такое JTAG
Ну и конечно, компания Altera предоставляет исчерпывающую документацию по использованию JTAG и BST (Boundary Scan Test ) в своих микросхемах FPGA и CPLD:
На нашей плате Марсоход тоже есть разъем JTAG для подключения программатора UsbBlaster или ByteBlaster. Через этот разъем мы программируем нашу ПЛИС.
Попробую рассказать, что же такое JTAG своими словами.
Еще в 1980 году группа разработчиков Joint Test Action Group (JTAG ) разработала спецификацию для тестирования межсоединений на плате: » boundary-scan testing «. Позже эта спецификация была стандартизована как IEEE Std. 1149.1.
Представьте себе, что Вы разрабатываете плату скажем с 5 микросхемами и у каждой микросхемы 100-1000 контактов. Микросхемы соединены между собой тысячами соединений на плате. На заводе плата будет выпускаться партиями десятками тысяч экземпляров. Понятно, что часть плат после монтажа компонентов будет браком. Где-то не пропаяются контакты, где-то трещина в PCB или не получилось переходное отверстие между слоями платы и так далее. Как же все таки тестировать устройства?
Вот собственно первоначальное предназначение JTAG — предоставить производителям средство тестирования собранных устройств.
Производители микросхем обязывались выпускать JTAG совместимые микросхемы. Все микросхемы на плате соединялись специальным последовательным интерфейсом из 4х сигналов TDI , TDO , TMS , TCK .

Каждый контакт микросхемы снабжается специальной логикой Boundary Scan Cell . Все эти ячейки Boundary Scan Cell всех микросхем на плате получаются объеденены в одну последовательную цепочку. Это позволяет по запросу с компьютера через интерфейс JTAG менять состояние почти любого вывода любой микросхемы, активизировать его как выход или как вход. Выход одной микросхемы выдает сигнал который передается по проводникам печатной платы и принимается входом другой микросхемы — так проверяется соединение на плате.
Внутри каждой микросхемы с JTAG есть специальный TAP контроллер ( Test Access Port ), который принимает последовательные команды и выполняет их. TAP контроллер управляет всеми ячейками Boundary Scan Cells . Кроме этого, через TAP контроллер можно выполнять всяческие специфические для каждой микросхемы команды.
Так, например, микросхемы компании Альтера можно: программировать CPLD, загружать образ в FPGA, считывать внутреннее состояние виртуальных пинов, использовать «внутренний цифровой осцилограф» SignalTap (для FPGA) и прочее. Для некоторых микросхем процессоров через JTAG и соответственно TAP контроллер можно вести пошаговую отладку программ, считывать состояния регистров процессора и встроенных контроллеров. В общем, довольно универсальный интерфейс.
Давайте посмотрим, как устроен TAP контроллер.
Работа TAP контроллера описывается вот таким автоматом ( state-machine ):

Кажется не понятным, но на самом деле все просто.
Интерфейс JTAG передает TAP контроллеру 3 сигнала TDI , TMS и TCK .
TCK — это тактовая частота, на которой работает интерфейс. Состояние контроллера меняется по фронту тактовой частоты TCK согласно состоянию линии TMS . Сигнал TMS определает в какое состояние переходит контроллер на следующем шаге.
Рассмотрим конкретную ситуацию.
Предположим мы находимся в начальном состоянии TEST_LOGIC/RESET . Если TMS=1 , то при каждом новом импульсе тактовой частоты TCK мы так и будем оставаться в этом состоянии.
Если на вход микросхемы TMS подать ноль, то при очередном импульсе TCK контроллер переходит в новое состояние RUN_TEST/IDLE .
Если держать TMS=0 , то мы так и будем оставаться в этом состоянии. Однако наша цель — это достичь два других возможных состояния CAPTURE_DR или CAPTURE_IR . Если мы попадем в эти состояния меняя TMS соответствующим образом, то дальше мы можем последовательно передать контроллеру либо команду (состояния SHIFT_IR ) либо данные ( SHIFT_DR ).
Передача в контроллер выполняется через сигнал TDI в одном исз состояний SHIFT_IR или SHIFT_DR . Одновременно контроллер может отдавать уже свои данные через сигнал TDO .
Обратите внимание, что из любого состояния можно вернуться в исходное состояние TEST_LOGIC/RESET если держать TMS=1 несколько тактов подряд.
Таким образом, через JTAG интерфейс в микросхему и ее TAP контроллер можно передавать разные команды и данные. Набор команд для каждых микросхем конечно свой и определяется производителем. Нас в первую очередь интересуют команды для программирования микросхем Альтера. Где бы их узнать?
На самом деле и это в общем не проблема. Среда разработки Altera Quartus может генерировать файлы в формате *.SVF. Это текстовый файл, который на специальном языке описывает последовательность действий для программирования микросхемы через JTAG/TAP . В принципе, есть некоторое описание языка SVF . Не знаю насколько это стандарт — вы можете его скачать у нас на сайте (
Если Вам нужен файл для программирования микросхемы Altera в формате *.SVF, то зайдите в меню среды Quartus Assignments\Device найдите и нажмите кнопку Device and Pin Options и увидите вот такое диалоговое окно:

Нужно установить флажок на Serial Vector Format File (*.svf).
Теперь после компиляции проекта у вас появится этот файл и вы сможете его внимательно посмотреть.
Вот фрагмент этого файла:
!
!CHECKING SILICON ID
!
SIR 10 TDI (203);
RUNTEST 93 TCK;
SDR 13 TDI (0089);
SIR 10 TDI (205);
RUNTEST 93 TCK;
SDR 16 TDI (FFFF) TDO (8232) MASK (FFFF);
SDR 16 TDI (FFFF) TDO (2AA2);
SDR 16 TDI (FFFF) TDO (4A82);
SDR 16 TDI (FFFF) TDO (0C2C);
SDR 16 TDI (FFFF) TDO (0000);
Из этого можно понять, что для того что бы проверить ID (тип) микросхемы перед прошивкой нужно:
- передать в регистр команд IR 10ти битное число 0x203;
- выждать паузу 93 такта;
- передать данные в регистр DR из 13ти бит 0x0089;
- передать в регистр команд IR десятибитное число 0x205;
- выждать паузу 93 такта;
- передавая 5 раз 16ти битное число 0xFFFF одновременно принимаем с TDO собственно ID 0x8232, 0x2aa2, 0x4A82, 0x0c2c и 0x0000
Вот эта последовательность и есть ID микросхемы платы Марсоход EPM240T100C5
Background
To follow up on my last post about SWD and hardware debugging, I wanted to do a deep dive into JTAG from a reverse-engineering perspective. The previous post received a lot of great feedback and it seems that people are interested in this topic, so I wanted to continue the series and expand upon another hardware debugging mechanism. For those who are unfamiliar, JTAG is a hardware level debugging mechanism that many embedded CPUs utilize, with this post I hope to explain how to approach JTAG from a reverse engineers perspective and provide some practical examples along the way.
Goals
With this post, I hope to do the following:
- Explain how JTAG works
- Demonstrate how to discover and utilize a JTAG port/interface on an unknown target
- Provide an overview of some of the current OSS tools that can be used to interact with a JTAG interface
- Utilize JTAG to extract firmware and debug a target
Also, before I give an overview, I wanted to point out a few great resources for learning about JTAG
Blog Updates (as of 2022):
- Future blog posts and entries can be found here.
- If you are interested in learning more about reverse engineering check out my 5 day hardware hacking course, public and private offerings are available upon request
- Never want to miss an update or blog post? Check out my mailing list for a quarterly newsletter about reverse engineering embedded devices
JTAG Overview
JTAG is a hardware interface that was developed to assist developers and testers with low level debugging. JTAG was originally developed for testing integrated circuits and more specifically, sampling IO pins on a target under test. This type of debugging interface allows engineers to test connections on PCBs without needing the probe the physical pin itself. The JTAG interface is controlled via the state machine outlined below:

One of the important things to remember about JTAG at this level is that it involves two registers, the instruction register, and the data register. To utilize these registers, the proper states in the above state machine must be entered using the following interface signals:
The state machine is navigated using the TMS and TCK lines, while data is written to or read from via TDI and TDO respectively. TMS is sampled on the rising edge of TCK, meaning that the TMS line must be asserted before TCK is toggled to navigate through the state machine. Data is then shifted into the instruction register (IR) or data register (DR) depending on the state of the JTAG state machine. When an operation is completed (or after the update DR/IR phase) the resulting data can be shifted out of DR by entering the Shift-DR state. With these primitives in place, manufacturers can implement whatever features they wish over JTAG.
The JTAG standard treats IR and DR as shift registers, and due to this, multiple targets can be daisy-chained together.
In a nutshell, JTAG defines a state machine that is navigated with a minimum of 4 signals. With this state machine in place, end users can write and read from two shift registers, IR and DR.
JTAG Registers
JTAG utilizes two main registers, the instruction register, and the data register. The instruction register is used to determine what function the JTAG controller is about to carry out such as a memory read, or memory write for example. The data register is then used as an additional input to the instruction register, for the previous example, they may be used to provide an address to read from or write to. These registers can vary in size based on their function.
To write to a register one would perform the following steps, we’ll use the IR as an example:
- Enter Test Logic Reset state (TLR) (This can be done by asserting the TMS line and cycling CLK 5 times)
- Enter Select IR Scan state
- Enter Capture IR state
- Enter Shift IR – This is where we load the data into IR from TDI
- Enter Exit IR state
- Enter Update IR state – This stage “latches” the value into IR.
Following this, if there were no data registers required, the operation would be performed, and the result (if any) would be loaded into the data register to be shifted out. However, many instructions require a data register to be filled out as well before operating. In that case, once the data register is written to and updated, the operation will be performed and the result can be shifted out of the data register.
Some instructions do not require the DR to be loaded, for example, if we had loaded the IDCODE instruction into IR (1110b), this would load the processor’s IDCODE value into the data register for us to then clock out and read it on TDO . To read the result out of TDO , one would navigate to the Shift-DR state, and clock in 32 bits on TDI , this would cause the data in the data register to be shifted out on the TDO line. See the image below for a visual representation of what would happen if one loaded the IR with the IDCODE instruction

It’s important to remember, that IR and DR can be thought of as shift registers, meaning that when we update them with new values, the old values are then shifted out on TDO .
The JTAG standard defines the following instruction registers:
- BYPASS
- This instruction connects TDI and TDO
- In the Shift DR state, data is transferred from TDI to TDO with a delay of one TCK cycle
- 0 is loaded into the data register during the Capture DR state
- This can be used to determine how many devices are in a scan chain
- When loaded the Device Code Id Register is selected as the serial path between TDI and TDO
- In the Capture-DR state, the 32-bit device ID code is loaded into this shift section
- In the Shift-DR state, this data is shifted out, least significant bit first
- The state machine is navigated with 4 signals: TCK , TMS , TDO and TDI
- TDI is used to provide input, TDO is used for output
- Using this state machine data can be shifted into the IR ( Shift IR ) and the DR ( Shift DR )
- The instruction register ( IR ) can be thought of as a function, and the data register ( DR ) can be considered the argument to that function
- As data is shifted into DR and IR , the previous contents are shifted out on TDO
- Once data is shifted into these registers, an operation can be performed (entirely dependent on host implementation aside from a few reserved instructions)
- Data is read out of the target by shifting it onto TDO from the data register in the Shift DR state.
So now that we have gone over how JTAG works at a low level, we should talk about why we might care about it, and how this interface can grant access to useful features for reverse engineers. One of the most commonly used applications of the JTAG interface is hardware-level debugging (hence the title of this post). This is implemented by the chip manufacturer, and can vary from chip to chip, however, one of the most common implementations of hardware-level debugging for ARM targets is ARM’s CoreSight Debug Interface. This is the same implementation that we communicated with over SWD in my last post, only, in this case, the Debug Access Port is communicated with over JTAG. The specifics of the JTAG implementation can be found here. Luckily for us, some excellent OSS tools can be used to communicate with these ports — this post will focus on using OpenOCD.
OpenOCD takes care of utilizing the JTAG or SWD interface to grant the end-user various primitives that are provided by the debug interface exposed through the CoreSight DAP. The Coresight / DAP architecture is fairly complicated and too much to cover in this (already long) post, so I will potentially save that for another post
JTAG for Reverse Engineers
It’s extremely important to have a solid understanding of the protocol fundamentals when approaching something like this from a reverse engineer’s perspective. When reverse engineering hardware (or software) you want to have your ground truth covered since there are always infinite unknowns. These next few sections will go over how we can take advantage of our low-level knowledge of these protocols to assist us on our path to gaining access to hardware level debugging via JTAG. The first thing that we need to do is determine the pinout, and if the pins exposed allow access to the JTAG interface.
Determining the pinout
JTAG signal lines are often grouped together, sometimes (if you’re extremely lucky!) you will see one of the following headers:

If you find something like this however, it may not have the exact signal groupings, so we will discuss how to determine a pinout if one assumes it’s used for JTAG.
When reverse engineering something like this, you want to start with what you know. Since we know that most manufacturers at least implement IDCODE and BYPASS let’s talk about how we can take advantage of those two instructions.
If you have identified what you believe to be a potential JTAG header or pinout, but do not know the pins, we can use the behavior of these two registers to determine the pinout.
Since the IDCODE register is typically loaded as the default IR, one can test an assumed pinout by doing the following:
- Assign roles to potential output pins (TMS, TCK, etc)
- Enter the Test Logic Reset state
- Enter the Select DR Scan , Capture DR , Shift DR
- Clock 32 values on TDI and monitor TDO for a valid IDCODE value
- Check the IDCODE value that you shifted out if it looks valid congratulations! Otherwise, reassign pins and repeat!
In addition to taking advantage of the fact that the IDCODE register is often loaded into the IR by default, we can also utilize the fact that both the IR and DR behave as shift registers, so if we assume a common register length (32 bits often works) we can attempt to brute force the pinout by doing the following:
- Assign roles to potential output pins (TMS, TCK,etc)
- Using these assumed values, enter the Test Logic Reset state
- Enter the Shift IR state
- Shift in a unique 32-bit value on TDI
- Continue to shift 1’s on TDI while monitoring for your unique pattern on TDO (be sure to do this as lease 32 times!).
- If the pattern is discovered, congratulations! Otherwise, choose new assignments for the pins and repeat!
Both of these methods are used by the previously mentioned JTAGEnum script, as well as the JTAGULATOR.
Determining Instruction Length
Once you have determined the pinout of the target, then the real fun can begin. The next step is to then determine the length of the IR / DR. To do this, starting with IR, enter the Shift IR state and flood the chain with 1’s on TDI , using a large number like 1024 or 4096, and then clock in a 0. Once this has been done, simply continue to clock in 1’s on TDI , counting the number of clock cycles that it takes before a 0 appears on TDO . This will tell you the length of the IR. Once you have that, you can enter the Shift DR state and repeat the process to determine the state of the DR. This is something that urjtag does very well.
Practical Example: Samsung M.2 SSD
The target for this post is going to be a Samsung M.2 SSD that I recently recovered from an older laptop. After looking at the PCB and spotting what could potentially be JTAG headers, I wanted to outline the process from start to finish.


Practical Example: Locating JTAG Headers / Determining Pinout
As mentioned before JTAG lines are often grouped — so when looking at a new platform from a hardware perspective, looking for pin groupings greater than 5 is always a good start. Luckily for us on this target, there are 9 vias located along the outside of the PCB. Let’s start by examining the voltage levels of these pins with the drive in a normal operating state
From a first pass — these voltage values don’t tell us anything, so what can we determine based on the information we have? First off, we have a GND which is an easy one to determine by using continuity mode on the multimeter and testing against something like a shield of the USB connector (while the target is unplugged of course!). Next, we have one line at 1.8V, typically one would expect this to be TMS as it is recommended to be held high in most documentation.
To determine the pinout, we will use a Raspberry Pi and the JTAGEnum project. This script uses the aforementioned methods to attempt to identify a JTAG pinout. It is also important to note here that the logic levels are at 1.8V so we will need to use a logic level shifter if we’re going to interface to this target. JTAGEnum.sh uses the Raspberry Pi’s GPIO lines to actuate the target interface, in the shell script they include a map of the GPIO values which can be seen below:

Using our table above, we will wire the following GPIOs to the unknown header:
In JTAGenum.sh we will modify the pins variable to be as follows:
Now with the pins wired up, and the logic level shifter in place we can run JTAGenum.sh .
Running the script wired up as shown below yields a TON of results, the output can be seen [here]. Luckily for us, it properly identifies two possible configurations which can be seen below:
Next, the script ran an ID scan. You might notice that a lot of results were generated for this, how do we filter through these? There are a few things that you can do to filter through the results, for example, we probably only have 1-2 devices on the scan chain (CPU and flash) so we can immediately ignore those that have more than 2-3 entries. Next, you can rule out those that have long (more than 4-5) sequences of 1’s or 0’s. Luckily in this list, there is an ID that I have seen before: 0x4ba00477 — this ID is for an ARM Cortex core and I’ve seen it before when attempting to get access to Beaglebone Black.
You’ll notice that with the IDCODE scan, the value for TDI varies, that is because this method does not rely on TDI at all so it is a guess.
Luckily some of these results line up nicely with the pattern scan, so we can now assume that we know the pinout of the JTAG interface!
Practical Example: Determining Instruction Length with UrJtag
While OpenOCD is excellent for interfacing with DAP controllers and connecting to debugging cores, the UrJTAG project is great for interfacing with JTAG at a low level. We can use this to detect the various DR lengths with their useful discover command. This method uses the same principles mentioned earlier to select an IR then shift a large number of 1’s into DR followed by a 0, then clocking more 1’s until a 0 is read on TDO!
UrJTAG can use an rc file located at
/.jtag/rc mine is as follows
Below we can see the result of running UrJTAG with these commands:
I wanted to highlight UrJTAG in this post because it is extremely useful when looking at a target with a completely unknown scan chain, or DAP architecture. Luckily for us, the IDCODE of this target tells us that it is ARM and we will likely be able to utilize the CoreSight DAP, to do this, we will use OpenOCD. If you are looking at a scan chain where you know nothing about it, I typically start with UrJtag just to get a map of all of the registers. The python bindings for UrJTAG also work quite well and can be used to interface with JTAG at a low level.
JTAG Debugging via OpenOCD.
Since we know the pinout of the JTAG interface on our target, we can now move onto using OpenOCD to communicate with it. I am choosing OpenOCD for this task because it has excellent debugging support for ARM MCUs, particularly the Cortex series which uses CoreSight. The first thing we’ll need to do is choose a hardware adapter, we will use the FT2232H breakout module.
JTAG via FT2232H
With the pinout understood, we can now attempt to talk to the DAP using OpenOCD. For this we will use an FT2232H adapter, for this post I am using a standard FT2232H breakout board. These boards can be used to interract with multiple hardware level interfaces and have excellent software support. You may recall I’ve used them for things such as SWD as well as dumping SPI flash. Using this board, along with a 3.3V to 1.8V logic level converyer we can wire it up to the target as follows:
Next, we will write the outline of our config file, starting with the variables that we know about the target.
When we run openocd with this config file, these are the results:
Now let’s have a look at the DAP, and see if there is any more relevant information in there:
The first thing that sticks out is that this is a Cortex R4, with this additional information we can create a target in the config file, which should grant access to the MEM-AP allowing for debugging. This can be done by adding the following line:
With this additional line, we can try to halt the target via the halt command and read memory via mdw from the OpenOCD prompt:
Here we test stepping through the running firmware:
Success! It appears to be working, and we can single-step through the firmware. Next, let’s use this capability to get some RAM dumps, this page gives an overview of the memory model, so we can use that as a reference. Memory can be dumped to a file with OpenOCD via the dump_image command.
Finally, let’s take these RAM dumps and load them into GHIDRA to see if they make sense:

Excellent, we have some xrefs and the init code looks fairly sane. It also looks like there is some sort of debug menu that is presented over the UART, these are likely pins 8/9 on our pinout! Safe to say that this is a valid RAM dump, and with this, I will finish up this post.
Conclusion
This was quite a long post — realistically it probably should have been broken up into 2-3 parts. With this post, we learned how JTAG functions at a low level, as well as how to approach JTAG as a reverse engineer. We were also able to get JTAG access to an undocumented target, extract memory, and single-step through the running firmware. There are lots of things left to do here, like determine if the flash chips themselves can be dumped via JTAG, RE the firmware to look for interesting ways to recover data from the drive (I recently discovered that lots of cool work has been done here already!). As always, if you have any questions or comments, please feel free to reach out on twitter.
I wanted to mention some awesome work that I found after going through all of this, both of these have already done a lot of what we did in this post today, albeit on slightly different drives. I’m sure that someone on twitter will let me know this so I wanted to link to some excellent previous work that was pointed out to me by some members of the OpenOCD community!
JTAG на службе специалиста по безопасности
Представьте, что вы держите в руках устройство подобное тому, которое показано на рисунке ниже, и вас просят получить полный доступ к системе этого устройства. С чего вы начнете?
Автор: Senrio
Представьте, что вы держите в руках устройство подобное тому, которое показано на рисунке ниже, и вас просят получить полный доступ к системе этого устройства. С чего вы начнете? (если хотите увидеть, как добываются права суперпользователя к роутеру, сразу переходите к разделу «Реализация атаки: получение полного доступа к домашнему роутеру»).
Рисунок 1: Наша цель: ОЧЕНЬ популярная модель пользовательской точки доступаПоскольку имеется неограниченный физический доступ к устройству, возможно, у вас появится мысль об атаке непосредственно на аппаратную часть. С другой стороны, если у вас недостаточно опыта в этой области, могут возникнуть разные сомнения и вопросы. В данной статье будет представлена фундаментальная информация об использовании интерфейса JTAG для исследования оборудования. Кроме того, мы рассмотрим пример, иллюстрирующий преимущества прямого доступа к аппаратной части.
Почему производители используют JTAG?

Рисунок 2: История развития JTAG
JTAG – распространенный аппаратный интерфейс для прямой связи компьютера с чипами на плате. Первая версия интерфейса была разработана консорциумом Joint (European) Test Access Group в середине 80-х годов вследствие постоянного усложнения методов тестирования печатных плат. JTAG начал приобретать популярность с тех пор, когда стал использоваться в процессорах Intel 80486 в 1990 году и стал соответствовать стандарту IEEE 1491 (в том же году). В наши дни JTAG используется для отладки, программирования и тестирования практически всех встроенных устройств.
Периферийное сканирование
Рисунок 3: Пины, используемые при периферийном сканировании
С изобретением интегральных микросхем появилась необходимость в тестировании соединений. Задача формулировалась так: нужно выяснить, что «Точка А» на плате корректно подсоединена к «Точке С». По мере того как индустрия двигалась в сторону увеличения плотности соединений и уменьшения размера компонентов, появилась необходимость в разработке стандартизированного способа тестирования интегральных микросхем (или «чипов»). Далее в микросхемы начали внедрять тестовую логику и ограничивать физический интерфейс до нескольких сигналов. В итоге появилось элегантное решение в виде интерфейса JTAG и периферийного сканирования, предназначенных для тестирования, отладки и диагностики современных электронных систем. Попросту говоря, периферийное сканирование позволяет читать и записывать отдельные биты на отдельные пины отдельных чипов на плате. Чтение и запись единиц и нулей напрямую на пины – чрезвычайно полезная возможность. Однако зачастую возникает и непонимание сути данного вопроса.
Рисунок 4: Выводы интегральной микросхемы
Интерфейс JTAG позволяет производителю тестировать физические соединения между пинами на чипе. Когда инженер говорит об использования JTAG для «отладки» платы, подразумевается нечто совсем другое, чем традиционная отладка приложения. В данном случае говорится о тестирование пина А у чипа А на предмет корректного соединения с пином Б чипа Б и того, что данные пины функционируют корректно. Поскольку JTAG дает прямой доступ к аппаратной части, данный интерфейс является отличным инструментом для исследования безопасности устройства.
Основы JTAG

Рисунок 5: Базовая схема JTAG
Перед тем как рассматривать JTAG как инструмент исследователя, поговорим про основы.
4 пина, плюс 1
Официальный стандарт требует для JTAG наличия 4 пинов (или сигналов) и одного необязательного (пятого). Эти сигналы и небольшие части кремниевой логики, которые подсоединены к тем пинам в целях управления, в общем, обозначаются как порт доступа к средствам тестирования (Test Access Port) или TAP-контроллер.
JTAG – «Вавилонская башня»
При изучении методов работы с JTAG приходится сталкиваться с огромным количеством информации, сбивающей с толку. Сайты производителей рассказывают «теорию» о том, как работает JTAG, и умалчивают о практических аспектах. Существуют и другие факторы, которые вносят еще больше путаницы:
- Использование сленга: а конкретно словосочетания «информационная безопасность. Все толкуют об информационной безопасности, но мало кто дает рабочие методики.
- Разночтения терминаJTAG: термин JTAG означает разное для разных групп людей. Например, в сообществе геймеров «JTAG» означает аппаратную модификацию консоли, позволяющую играть в пиратские игры или загружать доморощенный контент. Сей факт затрудняет поиск полезной информации.
- Разночтения родственных терминов: как упоминалось ранее, когда электроинженер говорит об «отладке», то подразумевает следующее: «Все ли пины на правильных местах? Достаточно мощности? Корректно ли работает логика цепи?». Когда программист упоминает об «отладке», то подразумевает отладчик GDB или WinDBG. JTAG разработан для тестирования аппаратной части, а не программной.
- Недопонимание: для программистов наиболее близкая область, похожая на работу с JTAG, — отладка ядра через отладочный кабель (USB, Parallel или Serial). Однако данное сравнение некорректно, поскольку даже в этом случае происходит отладка кода, запускаемого на удаленной системе, и передача команд по отладочному кабелю. В случае с JTAG происходит работа исключительно с аппаратной частью.
Чем JTAG не является!
В целях рассеивания дезинформации (звучит угрожающе) ниже рассказывается о том, чем JTAG не является:
- Специфическим устройством для отладки прошивки и аппаратной части.
- Приложением для отладки кода на устройстве.
- Протоколом. В спецификации на JTAG не указана схема информационного обмена между отладчиком и целевой системой (то есть нет .h файла, описывающего «JTAG-пакет», передаваемый по серийному, параллельному или USB-кабелю).
- Коннектором. В отличие от спецификаций для USB и Ethernet в стандарте JTAG не указано, как должны выглядеть коннекторы, что приводит к ОЧЕНЬ большой путанице касательно «JTAG» коннекторов. Особенно в среде программистов. Представьте, если бы каждый USB-кабель был различным.

Рисунок 6: Все модели, показанные на рисунке, можно отнести к «JTAG» коннекторам

Рисунок 7: JTAG-коннектор для роутера с прошивкой DD WRT

Рисунок 8: JTAG-коннектор для кассового аппарата
Все коннекторы, показанные на рисунке выше, относятся к JTAG-коннекторами. Но почему они выглядят по-разному? Где стандартизация? На практике вы можете столкнуться с сотнями и тысячами различных JTAG-коннекторов. Почему? Прежде чем ответить на этот вопрос, рассмотрим, что такое интерфейс JTAG, согласно стандарту. А согласно спецификации 1149 в JTAG-коннекторе должно быть 5 пинов (или сигналов):
- TCK: Test Clock (тестовая синхронизация)
- Играет роль метронома, задающего скорость TAP-контроллера. На данном пине просто пульсирует напряжение в определенном постоянном ритме. При каждом биении TAP-контроллер выполняет одно действие. Частота в стандарте не указана и зависит от внешнего устройства, которое управляет интерфейсом JTAG.
- Посредством манипуляции напряжением на данном пине мы управляем деятельностью интерфейса JTAG.
- Пин, передающий информацию на чип. В стандарте не определен протокол для передачи через данный пин. Решение о выборе протокола принимает производитель. Функция интерфейса JTAG – только передать нули и единицы на чип.
- Пин, предназначенный для вывода информации с чипа. Так же как и в пине TDI протокол передачи в стандарте не определен.
- Опциональный пин, используемый для сброса JTAG в начальное состояние. Далее будет объяснено, почему этот пин является необязательным.
Теперь, когда мы познакомились с назначением пинов/сигналов, взглянем еще раз на коннекторы, показанные выше:

Рисунок 9: Каждый коннектор имеет пины, имеющие отношение к JTAG
Сейчас мы понимаем, что каждый коннектор, строго говоря, не является JTAG-коннектором, а лишь имеет набор сигналов, имеющих отношение к интерфейсу JTAG. Именно при помощи данных сигналов мы можем манипулировать и общаться с машиной состояний (state machine) целевого устройства через TAP (Test Access Port) контроллер, встроенный в кристалл.
Машина состояний интерфейса JTAG
В спецификации IEEE 1149.1 указаны не только сигналы, но и модель поведения «Машины состояний», которая встроена в TAP-контроллер устройства. Диаграмма контроллера состояний показана в левом верхнем углу на видео ниже. Манипуляцией напряжением на пине TMS у TAP-контроллера и пине TCK мы можем управлять алгоритмом, при помощи которого Машина изменяет состояния. При каждом такте часов TAP-контроллер на целевом устройстве проверяет, есть ли напряжением на пине TMS и интерпретирует данный сигнал как 1 (есть напряжение) и 0 (нет напряжения). Эта серия единиц и нулей перемещает интерфейс JTAG через относительно простую машину состояний. Данная машина состояний настолько проста, что вы можете записать Arduino-код в целях различных манипуляций. Значение пина TMS, необходимое для изменения состояния, обозначено крошечными «1» и «0» на диаграмме машины состояний. Операции машины состояний можно найти на анимации ниже.
Your browser does not support the video tag.
Видео 1: Механика работы машины состояний интерфейса JTAG (в очень упрощенном виде). В действительности дискретизация сигнала немного отличается (дискретизация сигналов при нарастающем и спадающем фронте происходит по-разному). Кроме того, визуализация тактового сигнала, показанного выше, немного барахлит. В один цикл машина состояний выполняет только одну операцию. Дискретизация происходит при каждом цикле.
Обратите внимание, что информация читается и передается с пинов TDI и TDO в то время, когда машина состояний находится в состояниях Shift-IR и Shift-DR. Отличия между этими состояниями и соответствующими регистрами выходит за рамки этой статьи. Скажем лишь, что регистр инструкций IR и регистр данных DR похожи на вызовы функций. Значение в регистре IR определяет «функцию», в регистре DR – «аргумент». В спецификации для JTAG информации на этот счет нет. Конкретную функцию определяет производитель.Your browser does not support the video tag.
Видео 2: Анимация TAP-контроллера, работающего в режиме «Железнодорожной станции». По пинам TDI/TDO (путям) происходит передача через регистр (платформу).
Интересно отметить, что если на пине в течение 5 циклов подряд висит 1, то вы сразу же попадаете в состояние «Test Logic – Reset» (обнуление тестовой логики). Если пин TRST не используется, то этим методом можно сбрасывать TAP-контроллер в базовое состояние, вследствие чего, как упоминалось выше, пин TRST является необязательным.
Наконец, следует учитывать, что интерфейсы JTAG нескольких чипов на одной плате могут быть объединены в одну цепь и имеют общие выводы. То есть тестирование каждого чипа можно пользоваться данным объединенным набором. Данная схема особенно интересна в отношении однокристальных систем (System-On-Chip; SoC), где множество компонентов (ethernet, wifi, bluetooth и т. д.) объединены в один чип. Зачастую JTAG-цепь объединяет несколько ядер внутри одного чипа.

Рисунок 10: Примеры объединения нескольких устройств или нескольких ядер внутри одного чипаИсследование безопасности при помощи JTAG
Как вы уже знаете, в целях предоставления инженерам и разработчикам простого способа для тестирования и программирования был придуман интерфейс JTAG. С другой стороны, если вы разработаете суперсовершенный замок и оставите ключ под ковриком, ваша дверь будет закрытой ровно до тех пор, пока кто-нибудь не узнает где лежит ключ. В случае с JTAG ситуация примерно похожая. По сути, этот интерфейс дает злоумышленникам простой способ найти ключи от сокровищницы. Давайте рассмотрим, чем JTAG может быть полезен для специалиста по безопасности.
JTAG – простой и прямолинейный интерфейс
Вначале не лишним будет напомнить, что JTAG – это просто интерфейс, который не учитывает внутреннее устройство чипа. То есть взломать устройство только при помощи JTAG технически возможно, но на практике потребует слишком много времени, поскольку необходимо разобраться с внутренним устройством. Чтобы JTAG стал эффективным инструментом, потребуется нечто, что может преобразовывать информацию, пригодную для чтения человеком, в низкоуровневые инструкции входящие и выходящие из TAP-контроллера. Воспользоваться всей мощью JTAG позволяет отладчик OpenOCD.

Рисунок 11: Домашняя страница отладчика OpenOCD
OpenOCD – единственный репозиторий с открытым исходным кодом (база знаний) для различных чипов и интерфейсов. OpenOCD в сочетании с интерфейсом JTAG может управлять TAP-контроллером на целевом устройстве, отсылая биты (через машину состояний, описанную выше), которые затем чип интерпретирует как корректные команды.
Отладка аппаратной части при помощи софта
Запуск OpenOCD поверх интерфейса JTAG позволяет останавливать и пошагово проходить операции, инспектировать память, писать байты напрямую в память, устанавливать точки останова и наблюдения и даже инжектировать код в процесс или память. По сути, мы управляем аппаратной частью, выполняя стандартные отладочные задачи при помощи софта. Более того, OpenOCD позволяет использовать традиционные отладочные утилиты через GDB-сервер, позволяя отлаживать прошивки и софт в устройства при помощи GDB, IDA Pro и других приложений, которые могут работать как GDB-клиент.
Конфигурационные файлы
Здесь возникает закономерный вопрос. Как при всем обилии архитектур и чипов OpenOCD может взаимодействовать со всеми? Попросту говоря, OpenOCD использует специальные конфигурационные файлы для изучения инструкций, которые понимают устройства. Настроечные файлы обучают OpenOCD как правильно управлять TAP-контроллером, используемого под конкретную архитектуру. Соответственно, у вас должен быть корректный конфигурационный файл под тот чип, с которым вы хотите работать. Наиболее распространенные конфигурации уже включены в состав OpenOCD, а другие легко загрузить из репозитария.
Дополнительное оборудование
Большинство компьютеров не имеют встроенного оборудования для взаимодействия с JTAG. Для решения эти задач вполне подойдут устройства наподобие Shikra или BusPirate, которые легко можно купить в интернете.

Рисунок 12: Shikra – устройство для исследования аппаратной части
Профессиональное оборудование имеет больше плюсов: лучший контроль над процессом и большую производительность. Часто в составе подобных комплексов есть собственный отладчик. Однако и стоимость возрастает пропорциально. При использовании OpenOCD вам лишь нужен конфигурационный файл, который «обучит», как правильно взаимодействовать с устройством. Обычно коммуникация между компьютером и JTAG-контроллером происходит через последовательный интерфейс.
Недооцененный метод проникновения
Надеемся, что вы уже начали понимать потенциальные последствия после получения доступа к интерфейсу JTAG. Если все настроено корректно, то вы, получаете неограниченные возможности, и, по сути, становитесь полным владельцем устройства. Вы можете просматривать и модифицировать информацию и выгружать содержимое RAM и FLASH-чипов. Несмотря на очевидные преимущества, зачастую специалисты по безопасности не обращают особого внимания на JTAG, предпочитая программные методы проникновения.
Реализация атаки: получение полного доступа к домашнему роутеру

Рисунок 13: Внутреннее устройство подопытного домашнего роутера
В качестве подопытного экземпляра мы взяли устройство, которое упоминалось в самом начале статьи. Производитель предусмотрел стандартную систему авторизации в целях недопущения запуска команд до тех пор, пока у вас не будет учетной записи. Информацию об аккаунте держится в секрете, и наша задача – получить доступ к роутеру во что бы то ни стало.
Примечание: как вы уже догадались, обход встроенной системы защиты и получение полного доступа и прав суперпльзователя мы будет осуществлять через интерфейс JTAG.
Подготовительная часть

В нашем примере мы будем использовать устройство Shikra в качестве JTAG-контроллера и приложение OpenOCD в качестве отладчика, запущенного на виртуальной машине с OC Linux.
Рисунок 14: Назначение пинов устройства Shikra
- Подсоединяем кабель Serial-USB к UART-интерфейсу роутера, что позволит нам наблюдать за поведением устройства во время установки аппаратных битов.
- Включаем устройство и дожидаемся запроса на ввод логина и пароля. Именно данную защиту мы будем обходить с целью получения доступа к оболочке через UART-порт.
- Каждый пин Shikra подсоединяется к соответствующему пину роутера. Если вы не уверены, какой из пинов Data-In, а какой Data-Out, просто попробуйте разные подключения и в случае ошибки поменяйте включения местами. Назначение пинов, имеющие отношения к JTAG, на устройстве Shikra показаны на рисунке выше. Более детальную информацию по подключении Shirka можно найти в этой статье. Подключаем Shikra к USB-порту вашего компьютера, а затем физически соединяем пины Shirka и JTAG-интерфейса на роутере.
- Чтение и запись в память.
- Остановка выполнения прошивки (при помощи точек останова и наблюдения).
- Изменение инструкции и данных в памяти.
- Инжектирование инструкций напрямую в магистраль (pipeline) целевого чипа (без изменения памяти).
- Извлечение прошивки (для реверс-инжиниринга и поиска уязвимостей).
- Обход защитных механизмов (проверки шифрования, проверки паролей, контрольные сумму и т. д.).
- Нахождение скрытых JTAG-функций, которые могут намного больше, чем можно представить.
- и многое другое.
После подключения к UART-порту при включении роутера мы увидим процесс загрузки.
Your browser does not support the video tag.
Видео 3: Загрузка роутера
Эмоциональное возбуждение быстро ослабевает при появлении запроса на ввод логина после полной загрузки устройства.

Рисунок 15: Запрос на ввод логина
Далее мы рассмотрим, как использовать соединение с JTAG для обхода авторизации. Но вначале нужно найти этот самый интерфейс на роутере, что может оказаться непростой задачей. JTAG редко выводится наружу и вам, скорее всего, придется открыть крышку и залезть внутрь устройства.

Рисунок 16: Интерфейс JTAG подопытной точки доступа
Иногда интерфейс виден сразу, а иногда производитель скрывает или вовсе удаляет соответствующие пины. Если пины интерфейса JTAG сразу найти сложно, обращайтесь к спецификации и технической документации. Если же документация недоступна, придется воспользоваться подручными средствами: вольтметром, логическим анализатором и устройством JTAGulator. В случае если производитель подошел к сокрытию интерфейса особо тщательно, возможно, вам потребуется паяльник.

Рисунок 17: Микроконтроллер находится по центру платы
Получение полного доступа к системе
После подключения всех устройств полная схема будет выглядеть примерно так, как показано на рисунке ниже. Целевое устройство (точка доступа/роутер) подсоединено через «JTAG-интерфейс» (Shikra) к системе с программным обеспечением, предназначенным для взаимодействия с JTAG (OpenOCD и GDB).

Рисунок 18: Полная схема установки. Роутер подсоединен к компьютеру через устройство Shikra
В итоге у нас перед глазами три терминала. Первый – последовательное соединение через UART-порт, предназначенный для отслеживания состояния роутера на случай возникновения ошибок или перезагрузки. Второй отображает информацию фоновой службы OpenOCD. Третий используется непосредственно для работы с отладчиком OpenOCD.

Рисунок 19: Три терминала для работы с сессией OpenOCD
Первое, что необходимо сделать, остановить роутер при помощи команды halt. К сожалению, если посмотреть на терминал UART-порта, то можно увидеть, что через секунду после остановки роутер перезагружается. Подобное происходит потому, что в операционной системе работает функция Watchdog Timer, которая автоматически перезагружает устройство в случае остановки в течение определенного промежутка времени (обычно меньше секунды). Данная проблема обходится при помощи повторного ввода команды halt во время перезагрузки, пока функция Watchdog Timer еще не успела загрузиться. Поскольку наша задача изменить параметры загрузки, необходимо использовать команду halt перед стартом операционной системы.

Рисунок 20: Остановка роутера при помощи повторной команды halt
Остановив роутер, мы можем устанавливать точки останова, пошагово проходить операции и инспектировать/изменять память.

Рисунок 21: Выполнение различных команд в отладчике
Чтобы получить полный доступ к роутеру, изменим в памяти аргументы загрузки так, чтобы роутер загрузился в режиме единичного пользователя. Для решения этой задачи нужно добавить пробел и цифру 1 в конец параметров загрузки. Чтобы посмотреть аргументы загрузки, воспользуемся извлеченным образом прошивки. Для переключения редактора Vim в режим шестнадцатеричного редактирования воспользуемся командой xxd.
Рисунок 22: Использование Vim в качестве шестнадцатеричного редактора
Рисунок 23: Место, где хранятся аргументы загрузки
Исследуя извлеченную прошивку, находим адреса, где хранятся аргументы загрузки. Далее мы будем устанавливать точки наблюдения (watch point) на эту область памяти, где, весьма вероятно, будут находиться аргументы после распаковки ядра вскоре после загрузки. Данный трюк позволит нам не только отслеживать операции во время распаковки ядра, но и считывать аргументы перед загрузкой. Устанавливаем точки наблюдения на найденный адрес и возобновляем загрузку.

Рисунок 24: Установка точек наблюдения в то место, где будут находиться аргументы загрузки ядра
В процессе загрузки, как только дело дойдет до адреса, где установлена точка наблюдения, роутер опять остановится. После остановки в процессе распаковки ядра в память, мы можем дописать в конец параметров загрузки ядра последовательность "<пробел> 1" (или 0x2031, если перевести в шестнадцатеричный код). Затем удаляем точку наблюдения и позволяем роутеру завершить загрузку.

Рисунок 25: При помощи команд mdw (memory dump word; выгрузить слово из памяти) и mww (memory write word; записать слово в память) дописываем аргумент загрузки
После дописывания аргумента изменилась последовательность загрузки.

Рисунок 26: Шелл с правами суперпользователя
Теперь у нас есть шелл с правами суперпользователя, с которым можно работать через UART-интерфейс. Весь процесс занял около 15 минут.
Средства защиты
JTAG нужен производителю для решения разнообразных задач, начиная от проверки качества сборки и заканчивая загрузкой прошивки.
JTAG – невероятно полезен для производителей чипов при проектировании, тестировании и производстве и поэтому используется практически в каждом встроенном устройстве. С другой стороны, как было продемонстрировано в этой статье, JTAG представляет большую угрозу. Производители знают об этой проблеме и часто предпринимают шаги для ограничения доступа к JTAG. Способы защиты могут быть различными: сокрытие следов на плате или полностью удаление пинов. Во время производства провода, ведущие к интерфейсу, могут намеренно повредить. Данные методы в некоторой степени эффективны, но умелый злоумышленник с паяльником в руках практически всегда может восстановить повреждение. Некоторые стандарты рекомендуют использовать шифрование и криптографическую аутентификацию, но на практике эти методы используются крайней редко.
Заключение
Одно из железобетонных убеждений в IT-безопасности заключается в том, что если у злоумышленника есть неограниченный физический доступ к вашему оборудования, считайте, устройство вам уже не принадлежит. JTAG – технология, которая подтверждает истинность этого утверждения, и мы надеемся, что теперь вы понимаете почему.
Возможности, которые доступны через JTAG:
JTAG – чрезвычайно функциональный и полезный интерфейс для встроенных устройств. Разработчики, пишущие код для встроенных систем, обычно не подозревают о возможностях, которые доступны благодаря этой технологии. Мы видели множество систем, где разработчики тратили массу усилий на шифрование и защиту кода, даже не подозревая, что защита легко обходится на аппаратном уровне.
Естественно, в рамках одной статьи невозможно рассказать обо всем, но мы надеемся, что вы задумаетесь о тех бескрайних возможностях, которые доступны с JTAG.
Со всеми этими вездесущими отладочными интерфейсами, используемыми во встроенных устройствах, открываются двери для всех и каждого. Так как же защитить дверь, которая открыта? Занимайтесь мониторингом своего оборудования!
Отдельное спасибо Далин Макклеллан за помощь в подготовке статьи!
How JTAG Works
Street View for Circuit Boards, Part Three


The Pragmatic Programmers
In part one, we looked at JTAG boundary scan as a way to tour the electronic networks of a circuit board, much like Street View in Google Maps lets you virtually roam road networks. In part two, we installed some software packages with open-source implementations of essential algorithms. Those software packages also include the drivers you need to communicate over the JTAG serial bus from your PC.
For those of you interested in a deeper dive, in part three, we’ll look at when to use JTAG, it’s formal syntax, and how the bits and pieces of information it returns get mapped into a full picture of the on-board landscape.
When to Use JTAG
The JTAG circuitry inside all those chips on your personal electronics is designed to be normally inert. JTAG is the doctor that your circuit board, just like any patient, never really wants a visit from. As long as your device is functioning, JTAG stays in the background and out of the way, ready to be called only if needed.
If a device has failed and is in need of repair, your best course of action is to contact the manufacturer. Always service the device in accordance with the manufacturer’s recommendations. Failure to do so will void the factory warranty. If a device requires service, its manufacturer may deliver a software upgrade electronically. Often, the upgrade uses JTAG to configure or rewrite non-volatile memory and firmware. During this process, the manufacturer will ensure the safety of the device and anything connected to it.
Outside the warranty period, a device can be taken out of operation and repurposed, for example, inside a digital twin or system mock-up. In that way, you can use JTAG boundary scan on out-of-service devices to remotely simulate faults or diagnose a failure.
The full potential of JTAG for the consumer after-market is yet to be realized. As more manufacturers come on board with the right to repair and repurpose programmable equipment, the features that JTAG makes possible may move to a more secure and open standard. While we’re not there yet, understanding JTAG as it is today can give you a glimpse into what the future may bring.
The Highs and Lows of JTAG
JTAG originates from features built into modern ICs. Physically, it’s made up of seven pins on the chip. The board manufacturer configures these pins from chip to chip and then puts them on a connector for you to access.
Two of these pins are the serial I/O lines we discussed in part two: the one named test-data in (or TDI); and the other, test-data out (TDO). Serial I/O lines shift one bit at a time in sync with the rising and falling edges of the clock line, called TCK. Also on the JTAG connector you’ll find a logic high pin (VCC, or VTref), a logic low pin (GND), and an optional hard test reset line (TRST or nRESET).
Above all others, the last pin remaining on the connector is called the test-mode selector (TMS). This pin drives JTAG’s state machine, also known as the test-access port (TAP) controller. You’ll use the TMS pin before sending and receiving on the serial I/O lines to let the bus know what to expect. The Python language offers the shortest and most definitive answer to how activity on the TMS pin sets the stage for the JTAG bus:
That line of code returns the regular expression (regex) representing any number of complete passes of the JTAG TAP controller state machine. I’ve presented it above in its entirety to give you the overview. It’s ugly, right?
Regex uses math to describe machines. In each of the sections that follow, I’ll put into plain language what the regex means. First, notice how the TMS regex is arranged in pairs of opening and closing delimiters. I’ll break the expression down one delimited string at a time for a clear view of what each inner term describes.
Normally Passive
The outermost delimiters can be replaced by the following function:
The term “^” means that upon power-on and also in response to a hard reset on the TRST line, JTAG will stay out of the way. The “*” symbol near the end means it will do so even in the absence of any activity clocked out on the TMS line. The “$” terminal means that the system returns to the normally passive state when TMS activity (if any) completes.
TMS Activity
The next pair of delimiters is used to make the call to put the JTAG diagnostic tool into action.
TMS activity consists of a series of “1”s and “0”s clocked out one per cycle by the TCK line. The “+” symbol following the “1” in the code means that, from the passive state, the board can be explicitly held in reset indefinitely by keeping the TMS equal to 1. The “?” preceding it means that any changes to TMS beyond that are entirely optional. The board manufacturer takes advantage of this feature by installing a pull-up resistor that keeps TMS at “1” until you connect your JTAG cable.
Waking Up
Of course, holding the controller in reset is not what your aim is. So lets look at the other option, which is waking up and getting ready to run.
The JTAG bus will transition to being ready for action when TMS is driven low. The bus will transition back to sleep when TMS is held high for more than two ticks after any number of update cycles.
Update Cycle
Now you’re at the meat and potatoes section of JTAG’s theory of operation. The update cycle is where the commands and data payload get transferred from your software to the onboard chips. The drivers you installed in part two do most of their work here. During the cycle, the driver checks to see if TDO and TDI respond as expected, and then completes the update to write the selected JTAG register.
As needed, any number of update cycles can be called. Each begins by setting TMS high for exactly one or two cycles. The number of cycles selects either a data register (1 cycle) or the instruction register (2 cycles).
Once one of these two registers is selected, it must be followed by at least one sample cycle; otherwise the register is de-selected and the update cycle aborts.
After the last sample cycle completes, the actual update itself occurs on the next cycle with TMS held high. Next, if you like, you can idle the JTAG controller in neutral by setting TMS low. Whether you idle or not, the board stands ready either for the next update cycle, or otherwise, the soft reset that sends it back to sleep.
Sample Cycle
The sample cycle is the meat to the update cycle’s potatoes. Upon entry to the sample cycle, the JTAG bus takes a single image of the selected register’s bit-pattern. This image is then shifted out over the TDO serial line for each tick of the TCK clock. At the same time as the current image is shifted out, incoming bits on the TDI line are queued for update. Depending on the OPCODE you last sent to the instruction register, this incoming data will be written to the selected register once the sample cycle ends and control returns to the update phase.
Activity on the TMS is described by the following regex:
That formula indicates that TMS drops low for at least one clock at the start of each sample cycle. TMS can then be held low indefinitely: during this time the TDI and TDO bits start shifting through the digital avenues negotiated by the instruction register. Normally the tour ends when TMS goes high for one cycle, but you can instead choose to detour back if you quickly signal your intention with a high to low transition on the TMS line. Otherwise, skip the detour to end this set of sample cycles.
Detour Option
The detour option is indicated when the rising TMS signal is immediately followed by dropping TMS low again:
Detouring lets you pause the JTAG bus for however long you want. The longer you hold TMS at zero, the longer the detour lasts. Messages traveling from TDI to TDO are paused during the detour.
When you’ve lingered long enough, you raise the TMS line again like pulling the bell on the bus. Your detour grants you the privilege of commencing a new sample cycle. The set of sample cycles end if you choose not to exercise this option.
Working with RegEx
You can compose the original string presented at the start of this section from the lambda expressions in each sub-section. If you are familiar with using regular expressions, you’ll appreciate the following Python code for working with both outer and inner terms:
You’ll find ways to apply the 6 resulting sub-strings to a regular expression parser. That will help you identify how long the JTAG controller spends in each of the corresponding cycles, and how many bits of serial activity are shifted in and out.
A Map of Bits and Pieces
We’ve covered the seven signals that make up the JTAG bus: VCC, GND, TRST, TCK, TMS TDI, and TDO. The first two change only during power-on and shutdown. The third is a hard reset signal that turns out to be entirely optional: most of the time you will use a soft-reset on the TMS line to ensure that all chips on the bus are in a known starting state. In addition to performing a soft reset, the TMS line supports any number of high and low transitions and interprets them according to the formal grammar presented in the previous section. The purpose of the TMS line is to make sure that the JTAG bus is in the right state to direct intelligible data over the TDI and TDO lines.
The bits of data that flow out the TDO line come from snapshots of in-chip registers on the circuit board. Some of these registers are tied to the voltages on input and output pins. You can peer out onto the physical circuitry from those registers. You’ll need the software algorithms introduced in part two to do so. You’ll also need a map, which comes from the chip manufacturers in the form of a BSDL file.
Additional details about the on-chip registers and how to use them is available directly from datasheets and application notes published by the manufacturer. Those resources tell you what to send on the TDI line in order to access advanced capabilities. If the board employs highly scaled, system-on-chip solutions, then advanced capabilities may include access to embedded virtual or soft instruments that monitor internal on-chip features.
On the BDSL website, you’ll find plenty of BSDL files to get you started. Those files are intended to be parsed by machines and software. If you are a visual learner like I am, you’ll prefer software that illustrates how the data in these files relates to the real-world bill-of-materials on an actual circuit board. As a first cut, I’ve refactored some of the code from the Viveris JTAG Boundary Scan utility. My version is based on the CMake build system and relies on SWIG (the Simplified Wrapper and Interface Generator) to export portions of the Viveris library to C++ and Python. SWIG also supports exporting to other languages such as Tcl, C#, Java, and Octave.
The preceding commands will build a Python 3 example in the folder cmake/test/apps/py3 called py3UI.py . When provided with the path to a BSDL file as an input, it produces a rudimentary graphic from a BSDL file, as the following figure shows:
In the graphic, the JTAG chain is shown near the outer edge of the image. In the center, the pins of the chip are illustrated. Each pin on the chip may map to several bits from the JTAG chain. Chain-bits control the direction and state of the chip’s pin-out. Lines in the graphic connect the pin to the corresponding chain bit(s) in the JTAG boundary scan register. Lines with arrows are input/output lines. Lines without arrows are control lines that set the direction of the pin. A few bits in the JTAG chain are not directly connected to any pin. Those have internal purposes, and are sometimes included to support a common chain-length across a family of chips.
Wrapping Up
In this series, we started with an overview of JTAG and what you can do with it. Next we covered open source software packages you can use for JTAG boundary testing. To wrap up, in this article we looked more in-depth at the origins of JTAG and how it works.
As chips become more integrated and feature-rich, there is a need for software that can mine the large inventory of documentation that explains their operation. The topics covered in this series of three articles are intended to encourage software developers to create such software. Are you up for the challenge?
If you have questions or would like to me to cover other topics related to JTAG, please leave a comment.
