Setup Intel DCI Debugging on UP Squared Board
Tags: uefi, debug, firmware, tutorial
Published: 2022-05-25 09:00:00

Using Intel DCI (Direct Connect Interface), you can debug a whole system including the boot phase via USB cable. In this post, I'll first summarize the related technology of Intel DCI. After that, I'll show you how I setup the environment for Intel DCI Debugging on UP Squared board.


## Intel DCI and its surroundings

### Intel Trace Hub
![img](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cykannijglytvyz6d9ps.png)
(image from [Using the Intel Trace Hub for at-speed printf](https://www.asset-intertech.com/resources/blog/2021/09/using-the-intel-trace-hub-for-at-speed-printf/) by Alan Sguigna)

**Intel Trace Hub** is a mechanism that collects hardware/software events for the entire system, formats them with a time stamp, and  records them in the trace destination. It acts like a PCI device and consisted of below 4 components.
* **Trace Source**: sources of log such as internal hw signals, SoC performance data, software/firmware trace, and debug data from the Software Trace Hub
* **Trace Destination**: It can be MTB, system memory, or DCI
* **Global Trace Hub**: routes the data from the trace sources to the trace destinations according to the user’s configuration
* **Trigger Unit**: controls the starting and stopping of tracing operations

In other words, DCI is possible based on log information of the entire system provided by Intel Trace Hub.


### JTAG
JTAG is a mechanism to communicate with IC by serial communication. The interface specifications are defined by IEEE 11149.1, but in reality, semiconductor manufacturers extend them using private instructions and option registers. Functions such as CPU debugging and FPGA/CPLD sequences are realized using private instructions and option registers, so in many cases, only the semiconductor manufacturer and a third party that sined NDA can know.


### Intel DCI
Intel DCI is a function that allows you to debug the whole system including SMM and reset vector with just USB. More specifically, this allows you to JTAG debug a Intel CPU, with a trace data sent by Intel Trace Hub via USB.

You can connect target device and the analysis PC with a USB debug cable, and run **Intel System Debugger** on the analysis PC to debug. 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dr1vt9y94sq5o28ljs2f.png)
(image from [OSFC 2019 - Debugging Intel Firmware using DCI & USB 3.0](https://youtu.be/1NEtUxjJ9XM?t=134) by OSFC)
As you can see, there are two types of connections.
* **out-of-band (DCI OOB)**: This method uses USB but don't use USB protocol or USB controller, so we need external adapter
* **in-band (USB Debug Class)**: This method uses USB protocol. Supported in 7th gen and later


### Intel SVT CCA (Silicon View Technology Closed Chassis Adaptor)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qixgg3ex4wgx1ryygid4.png)
(image from [Source Level Debugging with Intel(R) SVT CCA](https://slimbootloader.github.io/developer-guides/debugging-with-cca.html) by Slim Bootloader) 

DCI OOB requires this adapter. This allows access to JTAG or Run-Control via USB3 port on silicon or platform which DCI is enabled.



## ISS (Intel System Studio)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fihgbf9nu2bbyeyw613p.png)
(image from [Introduction of System Debug and Trace in Intel® System Studio 2018](https://www.intel.com/content/www/us/en/developer/videos/introduction-of-system-debug-and-trace-in-intel-system-studio-2018.html) by Intel)

You have to install **Intel System Debug** in your analysis PC (host PC) to debug using Intel DCI, and System Debug is part of the tools in ISS. ISS debug tools includes the followings.
* **System Debug**: For source-level debugging of EFI
* **System Trace**: Realtime capture of logs of BIOS and CSME
* **Intel Debug Extension for Windbg**

### Methods of connecting target and host
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vzs81r6vtzzykmdd727j.png)
(image from [Introduction of System Debug and Trace in Intel® System Studio 2018](https://www.intel.com/content/www/us/en/developer/videos/introduction-of-system-debug-and-trace-in-intel-system-studio-2018.html) by Intel)

ISS provides below 3 methods to connect target and host.
* **ITP-XDP3**: Oldest methods. Directly connect to the JTAG socket. Costs about 3000 USD.
* **CCA (Closed Chassis Adapter**
* **DbC (DCI USB Native Debug Class)**


## Setup Intel DCI Environment on UP2 board

### Environment
* Windows PC that has USB 3.0 port (Host PC)
* [UP Squared ATOM Quad Core 08/64 (UP2 board)](https://up-shop.org/up-squared-board-atom-x7-e3950-8gb-memory-64gb-emmc.html)
* [SF100 SPI NOR Flash Programmer (SF100)](https://www.dediprog.com/product/SF100) + [ISP Testclip SO8 (TestClip)](https://www.dediprog.com/product/ISP-TC-8)
* [UEFITool v2.8 (UEFITool)](https://github.com/LongSoft/UEFITool/releases/tag/0.28.0)
* Ghidra
* [Intel System Studio (ISS)](https://registrationcenter-download.intel.com/akdlm/irc_nas/emb/17152/system_studio_2020_u3_ultimate_edition_offline.iso)
* [USB3.0 Debug Cable (Debug Cable)](https://www.datapro.net/products/usb-3-0-super-speed-a-a-debugging-cable.html)


### DCI Support on UP2 board
In order to use Intel DCI, your BIOS needs to support DCI. Looking at the [BIOS history of UP2 board](https://github.com/up-board/up-community/wiki/UP_Squared_BIOS_History), we can see that the DCI Debug Interface is supported since UPA1AM31. However, it is disabled as a default for formal release version since UPA1AM36.  My board had UPA1AM52 flashed (I found out by looking at BIOS SETUP screen), so we have to enable DCI in BIOS configuration first. 

Usually, there is a configuration called **HDCIEN** in the BIOS SETUP, and by enabling this, it should set the bit inside IA32_DEBUG_INTERFACE MSR and enable DCI. However, on this BIOS, enabling HDCIEN which was under `[CRB Setup] > [CRB Chipset] > [South Cluster Configuration] > [Miscellaneous Configuration] > [DCI enabled (HDCIEN)]` doesn't seem like to enable specific bit in the IA32_DEBUG_INTERFACE.

Intel has open source BIOS image [here](https://www.intel.com/content/www/us/en/download/674509/intel-atom-processor-e3900-series-apollo-lake-up-squared-board-flash-images-r-71.html), which is supposed to enable DCI on UP2 Atom board. However, it seems to not boot when I flash the BIOS with this image. Also, it seems like a common problem as the same problem is discussed in [up2 forum](https://forum.up-community.org/discussion/4806/opensource-uefi-bios-by-intel-appears-to-be-unusable-now).

So, I asked Tanda-san (the questioner of the above forum) how he managed to solve this problem, and he gave me a *hacky* solution. That is, to patch MSR initialization code to set the bit of IA32_DEBUG_INTERFACE on UP2 BIOS.


### Enabling DCI on UP2 board
I used SF100 to extract/write BIOS and the method is explained in my [previous post](https://dev.to/machinehunter/readwrite-bios-image-using-dediprog-sf100-spi-nor-flash-programmer-3pm3), so I will skip the details of this.

After you extracted UPA1AM52 BIOS image from UP2 board and saved as a `.bin` file, you can look at what kind of modules are included in that image by using UEFITool. If you look for the byte sequence `b9 80 0c 00 00` (`mov ecx, 0xc80` while `0xc80` is the number of MSR IA32_DEBUG_INTERFACE), you'll probably find 2 hits like below.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m0ks99fceyzdg5xjhpov.png)
If you double click the result, youl'll find that they are both in the same PEI module.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tjnmjg1llv5788zpdmw9.png)
UEFITool v2.8 can replace module in the image, but it has a disadvantage that it's hard to understand what module it is. By using different version of UEFITool, you can see that the PEI module is called SiInit PEI module.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u56zy6zovtcgbi7uw9j6.png)
Let's extract SiInit PEI module by right clicking `TE image section` and selecting `Extract body`.

Then, we open this module in ghidra. Ghidra recognizes this module as `Raw binary` but just go on with it, select `x86 64bit Visual Studio` and analyze. After that, again, search for the byte pattern `b9 80 0c 00 00`.

Disassembling around the first search result, you should get something like this.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ah5lpgnkpn2efygc10pp.png)
We have bits that enables DCI on the first bit of IA32_DEBUG_INTERFACE, so lets modify `0x40000000` to `0x40000001` (you can patch instruction on ghidra by `Ctrl-Shift-G`). 

Also, the second result looks like this.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/udhw7l6xgggsjhtusc6t.png)
Samely, modify `0x40000000` to `0x40000001`.
After that, `File > Export Program`, set `Binary` as a format and save this patched PEI module to somewhere.

Now let's go back to the UEFITool and locate that SiInit module again. Right click on the TE image section and select `Replace Body`, then select the patched module.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/imbkj8p30njj1mz3t7dg.png)
Once succeeded, you'll see some `Rebuild` displayed on the other module but that's normal behavior, so just `Ctrl-S` to save this.

Now, you made the patched UPA1AM52 BIOS image that has IA32_DEBUG_INTERFACE[0] set. Flash the BIOS with this image and you are ready to go.


## Intel System Debugger Setup

### ISS Installation
You can download ISO installer from [this download link](https://registrationcenter-download.intel.com/akdlm/irc_nas/emb/17152/system_studio_2020_u3_ultimate_edition_offline.iso). If you look inside iso file, you'll see some files like this.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xh9rakchgwtxamwjh7gk.png)
Double click `install.exe`, click Next a bunch of time and install ISS.

Usage of ISS are documented in `C:/IntelSWTools/system_studio_2020/documentation_2020/` (though it depends where you installed IntelSWTools). Some path of documents that I found useful are the followings.
* **Target Indicator**: `documentation_2020/en/debugger/system_studio_2020/system_debugger/target_indicator/TargetIndicator.pdf`
* **How to connect System Debugger**: `documentation_2020/en/debugger/system_studio_2020/system_debugger/system_debug/Getting_Started.pdf`
* **How to use System Debug**: `documentation_2020/en/debugger/system_studio_2020/system_debugger/system_debug/User_Guide.pdf`


### Connecting Intel System Debugger
First, make sure your UP2 board is powered on. Then, on the host PC, run **Intel System Debugger Target Indicator 2020**. When you run Target Indicator, it seems nothings happened but it's actually executed in the background.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nypbg0mtza87k5642aw9.png)
If you right click the red square icon and select `Intel(R) System Debugger Target Indicator`, you can check the current status of the connection.

Then, connect the UP2 board and host PC with USB3.0 debug cable (I always connect target first and then to host). UP2 board have 3 USB3.0 port and not all the port works for this. In my UP2 board, it only recognizes when I plugged it to the port below.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qdusv0b2p3wn8xlqp4a6.png)
I had trouble recognizing it first, but after I pull out debug cable from the host, reboot the target with the debug cable still plugged in and then, connect to the host again, it worked. Other methods of solving unrecognizing issue were stated [here](https://docs.microsoft.com/ja-jp/windows-hardware/drivers/debugger/setting-up-a-usb-3-0-debug-cable-connection#usb-device-not-recognized) but I haven't tried that out.

If connection works, Target Indicator should appear like follows.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jvfcqout7vrlhnwb5ilj.png)

Then, run Intel System Studio.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/da6glk2hue8ug8rch53t.png)
After closing the "Getting Started", we'll define connection like follows.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0suebmqt7038xfk5iui8.png)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/59vypzzyj7lgdy7kx3m9.png)
If the connection is established, you will see something like this.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/brfh2z95v2rpnrmca5tr.png)
If it didn't detect the target properly, you can "Manually Select Target" or try with different USB3.0 port on the target.

If you press Finish, you'll see the screen as follows.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sgd51csq3dzntmif4zgw.png)

Next, you have to setup **Debug Configuration**. Open the Debug Configuration as follows.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8tce0jbfm8qh9c4vdwpi.png)
Select Intel System Debugger and click Apply without changing any configuration.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8udk4q1hrxkf5kdzb226.png)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ck5egl27kd4l869l9q23.png)
You will see a popup like this, so click Switch.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/65v0sjiuyqqtyhgako3h.png)
Eventually, you'll get this kind of screen.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5f11xl5owd1dpe1wtiqj.png)


### Try suspending PC from System Debugger
Now if you click Suspend like below, and target freezes, then it's a success! Assembly will be displayed after you suspended.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6u8n7vozkood8zbqnosa.png)
If you want to debug boot phase, you can just reboot target.


### Second time connecting Intel System Debugger
For the second time debugging, you can follow these.
1. Power on UP2 board
2. Run Target Indicator on host
3. Connect debug cable
4. Open ISS and use previous workspace
5. Click `Verify Connected Target` to see if successfully connected
6. Click "Connect Button" to connect (tiny green icon)
7. Click icon with a "bug" to run with the previous Debug Configuration


## Acknowledgement
Again, great thanks to [Satoshi Tanda](https://github.com/tandasat?tab=repositories) for the support.