Debug Agent Based UEFI Debugging

Agent Based UEFI Firmware Debugging

using the Intel® System Debugger 2015 and a serial or USB connection.

The Intel® System Debugger now supports non-JTAG based debug of UEFI BIOS, this requires the use of a target-side debug agent and a USB or serial connection to the debug agent.

This article takes you through the steps necessary and the the debug methodology used bey the Intel® System Debugger to use this method to supplement the pure JTAG based UEFI debug method it also supports.

1.1 Pre-requisites

1.1.1 Using Ajasys* USB debug device

If a serial connection is for debugging, there is no need to install Ajays* drivers.

On initial USB debug connection use, the Intel® drivers for the Ajays* NET20DC USB debug device need to be installed.

  • Plug the Ajays* device into a USB port on the host PC, open device manager and right click on the device.
  • If the device isn’t visible in the device manager list, unplug the device and connect the other end to the host PC.
  • Select Update Driver Software and browse to the XDB installation folder. The drivers can be found in the following directory

C:\Program Files (x86)\Intel\System Studio 2014.0.xxx\

debugger\xdb\drivers\ajays-usb-dbg

  • Select the 32 or 64 bit drivers depending on your system setup.
  • If the device is in the device manager list, but “Update Driver Software” option is not available right after plugging in the debug device, wait until the option is available.

1.2 Setting up the Target

 

1.2.1 Hardware Setup

If you want to use the USB debug connection, the debug target must have an enabled USB debug port available. Check the target schematics to find the correct physical USB port. The target is connected via Ajays* NET20DC USB debug device to the PC running XDB. The debug device provides a host-to-host connection between the PC and the target.

If you are using serial debug connection, the debug target must have a connected serial port.

1.2.2 BIOS Setup

Debug agent can only be used with EDK II based BIOS. To debug the boot phase, the BIOS for the intended target needs to be rebuild. The debug agent must be included into the BIOS image and the target USB or serial driver has to be configured to support a debug channel.

  1. Download the BIOS sources for your target.
  2. Add or replace the latest SourceLevelDebugPkg from https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2 to your BIOS build.
  3. Modify BIOS configuration files to include the debug module and correct communication libraries.

For USB, set

SOURCE_DEBUG_ENABLE = TRUE

SOURCE_DEBUG_USE_USB = TRUE

For serial, set

SOURCE_DEBUG_ENABLE = TRUE

SOURCE_DEBUG_USE_USB = FALSE

  1. In edk2 reference implementation, configuration files OvmfPkgIa32.dsc and OvmfPkgX64.dsc use these flags to include needed modules. If your BIOS sources don’t have these configuration flags, see Intel UEFI Development Kit Debugger Tool User Manual chapter 2 for instructions how to add the debug configuration.
  2. If you are using serial connection,it is safest to disable flow control. Set the flag

gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl

to FALSE.

  1. Build and flash the images.

1.3 Connection Setup

If you are using a serial debug connection,

  1. Connect the serial cable from the debug target to the debug host.
  2. Modify the file softdebugger.ini to enable the serial connection.
  3. Comment out the USB connection settings and uncomment serial connection settings. Make sure the Port is set to the correct COM port in you system.

If you are using USB debug connection,

  1. the Ajays* NET20DC debug device must be connected with correct orientation or the connection may be unstable.
  2. The debug target must provide the power to the device.
  3. To check the connection orientation, open windows device manager and connect Ajays* NET20DC debug device to the host PC.
    • If device manager screen flickers (is updated), the Ajays* debug device is connected the wrong way.
    • Turn the device around and plug it in again.
    • The device may now  not recognized by the host PC. Plug the device into a powered on target, and the device gets powered on and recognized.

After the Ajays* NET20DC debug device is connected with correct orientation, disconnect the device, plug it first into the host and after that to the target. If you need to disconnect the device, make sure to always connect the host PC side first or the connection may not work.

1.4 Starting an Agent Based Debug Session

 

  • Connect the host PC to the target with Ajays* NET20DC debug device and launch the Intel System Debugger using the start_xdb_UEFI_agent.bat file.
  • Power on the target and click on the  “connect” icon at the upper left corner of the Intel System Debugger UI. If the setup is correct, The Intel System Debuggerwill connect and show disassembly on the screen.
  • Add module names to the UEFI module watchlist to break at the load of the module.
  • Let the target run. The execution will stop when a module with a matching name on the watchlist is loaded on the target.
    • Symbols for that module are automatically loaded to the debugger, if the symbol file is found at the same path on the host PC as read from BIOS. This is true if the PC used for debugging has the symbol files in the same path as used for building the BIOS. If symbol path doesn’t match, you must browse to the symbol file location and load the symbol file manually to be able to debug the source code.
  • After execution is stopped by a module load, the symbol file list on the left side of screen is updated.
  • Browse to the entry point of the loaded module, set a breakpoint there and run target again.
  • The module can now be debugged normally.

1.4.1 Handling the module watchlist

 

1.4.1.1 EFI "WATCHLIST"

Prints the names and break information of modules on EFI modules watchlist.

1.4.1.2 EFI "WATCHLIST ADD %s [INITBREAK=(ON|OFF)]"

Adds an EFI module to the module watchlist. Initbreak controls whether debugger breaks when a matching module is loaded or not. Initbreak parameter is not mandatory and is on by default.

Examples;

efi “watchlist add mymodule”

efi “watchlist add mymodule initbreak=off”

1.4.1.3 EFI "WATCHLIST MODIFY %s INITBREAK=(ON|OFF)"

Modifies the watchlist entry initbreak information for an EFI module.

Example;

efi “watchlist modify mymodule initbreak=off”

1.4.1.4 EFI "WATCHLIST REMOVE ALL"

Removes all EFI modules from the module watchlist.

1.4.1.5 EFI "WATCHLIST REMOVE %s"

Removes the selected EFI module from the watchlist.

Example;

efi “watchlist remove mymodule”

1.5 Troubleshooting

Problem

Possible root cause

Resolution

USB connection to target doesn’t work.

Target BIOS is not compiled with USB debug connection configuration

 

 

 

 

 

Ajays* NET20DC debug device needs to be reset.

 

 

 

 

Ajays* NET20DC debug device has been connected the wrong way

Make sure the BIOS image is compiled with configuration flags

SOURCE_DEBUG_ENABLE = TRUE

SOURCE_DEBUG_USE_USB = TRUE

 

Close XDB and power down the target. Disconnect the Ajays* NET20DC debug device from both ends and plug it back in with the host side first.

 

Disconnect the Ajays* NET20DC debug device from both host and target. Plug it back in only to the host PC and make sure device manager screen doesn’t flicker (is not updated) when you plug it in Connect the debug device to the target.

 

 

1.6 Known issues

 

1.6.1 Debugging a module on the watchlist

The debugger will stop the target when a module on the watchlist gets loaded. Target will stop at the debug agent code and load the symbols for the module on the watchlist. To debug the module you need to browse to the module source files and set a breakpoint somewhere in the code.

  1. Add your module into the watchlist.
  2. Wait for the module to get loaded and target to stop.
  3. Open the “source files” window. The window is visible at the left side of the screen.
  4. Browse to module source code and set a breakpoint.
  5. Run the target. Execution stops at the breakpoint and you can debug the module.

1.6.2 Using breakpoints

After reset, the breakpoints will get disabled in target even though they look enabled in the GUI. After target stops at a watchlist module load, the breakpoints need to be disabled and re-enabled for them to work.

  1. Open the breakpoints window.
  2. Disable breakpoint by unchecking the enable box.
  3. Re-enable breakpoint by checking the enable box.
  4. Run the target.

1.7 UEFI Debug Appendix

 

1.7.1 Using an Emulator for EDK2 debugging

It is possible to use an emulator to run and debug edk2 reference BIOS. The debugger is connected to the emulator over a serial port emulation.

1.7.1.1 Emulator BIOS Setup

The reference BIOS is built using VS2008 tool chain.  You must have VS2008 installed on your computer before building the reference BIOS.

  1. Check out the EDK2 sources from https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2.
  2. Open command prompt to the root of downloaded EDK2 sources and run edksetup.bat
  3. Give build command;

build -a IA32 -a X64 -p OvmfPkg\OvmfPkgIa32X64.dsc -v -D SOURCE_DEBUG_ENABLE -t VS2008x86

  1. The image will be created to ..\Build\Ovmf3264\DEBUG_VS2008x86\FV\OVMF.fd
  2. Create a new directory for running the BIOS you built.
  3. Copy the image file into this directory and rename it to “bios.bin”.

1.7.1.2 Serial emulation for emulator

  1. Download and install “com0com” from http://sourceforge.net/projects/com0com/. This will emulate a virtual com port pair to connect XDB and target emulation. Windows must be in test mode for the installation to succeed. Test mode allows you to install unsigned drivers. See com0com readme for instructions how to enable test mode.
  2. Create a virtual com port pair.
  3. Open the ..\bin\softdebugger.ini file in the XDB install folder.
  4. Comment out USB configuration settings (Channel and Port) and uncomment serial configuration settings at the beginning of the file.
  5. Change the setting “Channel” in softdebugger.ini file to one of the virtual COM port pair you created.

1.7.2 Setting up the emulator

  1. Download Qemu* version 0.13.0 from http://homepage3.nifty.com/takeda-toshiya/qemu/qemu-0.13.0-windows.zip. Using an unsupported Qemu*version may cause problems with the serial connection.
  2. Create a new folder for Qemu* in the same location as BIOS run directory created earlier.
  3. Open a command prompt in the new run folder where you copied the bios.bin file from edk2 build. Start Qemu* with the command;

..\qemu-0.13.0-windows\qemu-system-x86_64.exe -L . -serial COMX

where COMX is the other end of the virtual com pair.

  1. Qemu* will prompt for connection settings. Select 115200 and hardware flow control.

1.7.3 Starting a debug session

  1. Start XDB using the start_xdb_sd.bat file.
  2. Add interesting modules to the watchlist.
  3. Start Qemu*with the command described in previous section step 3.

 

References:

[1] " UEFI Development Kit 2010”, Sourceforge, a Dice Holdings, Inc. company

http://sourceforge.net/apps/mediawiki/tianocore/.

[2] “EDK II Remote Debug Support”, Laurie Jarlstrom, Intel Corp, 2010

http://www.uefi.org/sites/default/files/resources/EDK_II_SW_debugger_v0.1_lj-Plugfest.pdf

For more complete information about compiler optimizations, see our Optimization Notice.