.. -*- coding: utf-8 -*-

.. /*=============================================================================
      Readme file for Debugging in UEFI.
   
     Copyright (c) 2013, 2015 - 2016, 2018 - 2019 Qualcomm Technologies, Inc. All rights reserved.
   
                                 EDIT HISTORY
   
   
    when       who     what, where, why
    --------   ---     -----------------------------------------------------------
    03/08/16   yg      Update documentation
    10/28/15   bh      Update after path-related changes
    10/27/15   bh      Update for multiple driver debugging
    03/05/15   bh      Update after unification of 32/64-bit scripts
    06/05/13   yg      Initial version
   =============================================================================*/


.. _debug_uefi:

================
  Debugging UEFI
================

.. Note::

   Replace all instance of <TargetPkg> with valid target folder in QcomPkg:
   e.g: QcomPkg\<TargetPkg> is "QcomPkg\SocPkg\855"


Pre requisites and Setup
------------------------

1) Supported T32 sofware
2) Startup scripts and shortcuts from the source tree
3) JTAG connected and Target powered

   - If sys.m.a on Core 0 should be able to establish sync with CPU
   
4) Source tree with built binaries including symbols available



Debugging
---------

Main UEFI debug scripts are common across all targets and architecture states. Some of the params change per
target, so the starting scripts are located in the target tools folders. The script instructions hold good for
both 32-bit and 64-bit UEFI builds::

  Usage:
        do debug_uefi.cmm [[ram,][rel,][tools,][menu]] [sec|dxe|go|drvr1[,drvr2][,drvr2]]

Optional Arguments(choose any or all of the following options in a sensible manner, separated by commas where required)::

  REL:   Debug RELEASE build instead of the DEBUG builds (DEBUG builds debugging is default)
  RAM:   Load the UEFI binary built from the source tree into RAM and start debugging (without needing to flash)
  TOOLS: Load the tools binary built from the source tree into RAM and start using tools (no need to flash)
  <xxx>: Other possible options are to load any other image like tests, etc. Refer to the script for more details
  MENU:  Stop in the BDS menu without needing to press hotkeys or change variables
  
Modules to debug(specify the modules to debug)::

  SEC:  Debug Sec module and stop at SEC entry point function. If need to debug further modules, then press enter
        in the area window. This also continues to debug Dxe and stops at Dxe entry point (click on area window 
        and type continue in t32 to bring to focus)
  DXE:  Debug Dxe module, stop at Dxe entry point DxeMain as debugging starts
  go:   Mostly used in conjunction with RAM loading. Load image into RAM and go without needing to load
        any symbols further. This is the fastest way of seeing if things work fine without flashing UEFI/XBL.
        Symbols can be loaded later using symbol_load.cmm as needed.
  drvr: This is string that can be used to search in the driver name/path to stop and debug.
        For example: "do debug_uefi runtime" would stop at the entry point functions of the drivers 
        CapsuleRuntimeDxe, RuntimeDxe, ResetRuntimeDxe etc. Search is NOT case sensitive.
  mult drvrs: String containing up to 3 comma-separate driver or application names, that each work similar to
              the "drvr" command mentioned above. 


Debugging using T32 can be done in the following ways. Few possible examples of each method is also listed.

1) **Load the UEFI image into RAM for temporary debugging**

   This method helps when the code changes in development is not proven yet to flash it, or might crash,
   or just plain to try in easiest way without flashing (although time consuming).

   a) In T32 session, cd to "QcomPkg\<TargetPkg>\Tools" and run the following commands
   b) ``do debug_uefi.cmm ram go``
   
      Loads the image into ram and just runs without loading symbols
	  
   c) ``do debug_uefi.cmm ram sec``
   
      Loads the image into ram and load symbols and stop at entry points of Sec and Dxe for debugging
	  
   d) ``do debug_uefi.cmm ram dxe``
   
      Loads the image into ram and load symbols and stop at entry point of Dxe for debugging
	  
   e) ``do debug_uefi.cmm ram test``
   
      Loads the image into ram and load symbols as drivers load and stop at entry point of 
      the image whose name matches "test" anywhere in the path
	  
   f) ``do debug_uefi.cmm ram test1,test2,test3``
   
      Loads the image into ram and load symbols as drivers load and stop at entry point of 
      the images whose names match any of the comma separated arguments, anywhere in the path
	  
   g) ``do debug_uefi.cmm ram,tools go``
   
      Loads both UEFI and tools images into ram and continues to execute, nodebug, no symbol load
	  
   h) ``do debug_uefi.cmm ram,tools,menu go``
   
      Loads UEFI and tools images into RAM and automatically stops in BDS menu nodebug, no symbol load

2) **The image is flashed to the storage device and debug by loading symbols when interested driver images get loaded**

   In this method, source and built binaries are available for the image that's flashed on the device
   SBL's load the UEFI image into RAM to execute.

   a) In Apps Boot Core T32 session, cd to QcomPkg\<TargetPkg>\Tools
   b) ``do debug_uefi.cmm sec``
   
      Start debug session by synchronously loading the symbols as drivers load. Stops at entry points of Sec and Dxe

   c) ``do debug_uefi.cmm dxe``
   
      Start debug session by synchronously loading the symbols as drivers load. Stops at entry point of Dxe

   d) ``do debug_uefi.cmm test``
   
      Start debug session by synchronously loading the symbols as drivers load. Stops at entry
      point of the image whose name matches "test" anywhere in the path

   e) ``do debug_uefi.cmm test``
   
      Start debug session by synchronously loading the symbols as drivers load. Stops at entry
      point of the image whose names match any of the comma separated arguements, anywhere in the path

3) **The image is already flashed to the storage device and debug by loading
   all symbols one shot when the target can be stopped (eg in shell) or
   target crashed in UEFI**
   
   In this method, source and built binaries are available for the image that's programmed
   target is in crashed state in UEFI or is in UEFI doing something (or crash dumps are loaded into T32 simulator)
   After placing a bkpt continuing to run would load other additional images need loading symbols for them::

    do symbol_load.cmm [FORCE,INCR]
    -Force: If build paths are changed during debug sessions, override the stored build path with current path.
    -Incr : Incrementally load any additional symbols after the last load. Helps with fast symbol loading when
            additional images get loaded when a bkpt is placed. Also helps retain symbols for other images (Like TZ/HYP etc) and
            load UEFI symbols as well. Note since symbols are not cleared, there is a chance for stale symbols being
            around might confuse the T32 IDE, when in doubt first use default symbol load which clears all loaded
            symbol definitions (or issue y.reset first).

   a) In Apps Boot Core T32 session
   
      - cd to QcomPkg\\<TargetPkg>\\Tools
      - sys.m.a
      - do symbol_load.cmm
        or click on S soft button shown in T32 window

   b) When a bkpt is hit after loading additional symbols or when need to load UEFI symbols with other image symbols retained
   
      - cd to QcomPkg\\<TargetPkg>\\Tools
      - sys.m.a (also do sys.u as needed in simulator for crash dumps)
      - do symbol_load.cmm INCR
        or click on iSym soft button shown in T32 window

.. note::

   Subsequent calls to debug scritps can be made from any directory after executing debug_uefi script from TargetPkg once



Debugging multithread/multicores
--------------------------------

Qualcomm UEFI provides T32 scripts that help in debugging multithreaded/multicore UEFI feature.

- To use the following script symbols should have been loaded already
- ``QcomPkg/Tools/cmm/show_thread.cmm`` is the script that lists all the active threads in the system

  - For each thread in the system most of the details of its status is also shown, and if its blocked, the
    object in question that kept it blocked and potentially who owns the object (only for mutex)
  - Looking at the threads status and other details help to debug any deadlock related problems
  - If the threads are actively running in other CPU cores (1-7), then T32 can be attached to those cores
    and debug using regular UEFI debug scripts (symbol_load, log etc)
  - If any thread is "NOT in running" state, it can be viewed by switching to it and observing its stack frame
  - To view the non running threads only any core, use the script with thread full name or address
 
    - With this except the top most function in stack frame everything else below that will be relevant to the
      thread in question
    - The CPU Core state has to be restored back to exact same state before continuing to execute further again

      - To do this, go down the stackframe completely and hit enter in the area window to restore (or just type
        continue in T32 cmd window and hit enter in area window)
  - If debug_uefi or symbol_load scripts were run atleast once, T32 will have 2 quick access buttons to display
    the complete thread list (Red "T") and some Gic/Timer configuration (Red "G") buttons.


