Skip to content

Latest commit

 

History

History
1783 lines (1378 loc) · 68 KB

PITCHME.md

File metadata and controls

1783 lines (1378 loc) · 68 KB

---?image=assets/images/gitpitch-audience.jpg @title[EDK II Debugging]




UEFI & EDK II Training

EDK II Debugging w/ Linux Lab


tianocore.org Note: PITCHME.md for UEFI / EDK II Training EDK II Debugging Pres-lab

Copyright (c) 2019, Intel Corporation. All rights reserved.

Redistribution and use in source (original document form) and 'compiled' forms (converted to PDF, epub, HTML and other formats) with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code (original document form) must retain the above copyright notice, this list of conditions and the following disclaimer as the first lines of this file unmodified.

  2. Redistributions in compiled form (transformed to other DTDs, converted to PDF, epub, HTML and other formats) must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS DOCUMENTATION IS PROVIDED BY TIANOCORE PROJECT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TIANOCORE PROJECT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


@title[Lesson Objective]

<p align="center"Lesson Objective


  • @fa[certificate gp-bullet-green]  Define DebugLib and its attributes
  • @fa[certificate gp-bullet-cyan]  List the ways to debug
  • @fa[certificate gp-bullet-gold]  Using PCDs to Configure DebugLib -LAB
  • @fa[certificate gp-bullet-ltgreen]  Change Compiler & Linker Flags for debugging
  • @fa[certificate gp-bullet-yellow]  Change the DebugLib instance to modify the debug
            output - LAB
  • @fa[certificate gp-bullet-magenta]  Debug EDK II using VS Debugger - LAB

---?image=assets/images/binary-strings-black2.jpg @title[Debugging Overview]






     Debugging Overview

        

Note:

---?image=/assets/images/slides/Slide4.JPG @title[Debug Methods]

Debug Methods


@ul[no-bullet] - DEBUG and ASSERT macros in EDK II code

- DEBUG instead of Print functions

- Software/hardware debuggers

- Shell commands to test capabilities for simple debugging @ulend
 

Note:

  • Ways to Debug . . .

  • Use DEBUG instead of Print functions in code

  • Use a software debugger (COM/USB)

  • Use a hardware debugger (JTAG/XDB)

  • Soft loading driver through UEFI shell

  • Use shell commands to test capabilities

  • What are some alternatives if I don't want to use the debug lib?

  • You can use print statements and soft load my driver to the shell to see what is going on. The downside is that you then have print statements in your code. This doesn't work really well if you want to make a release to a customer.

  • You could use a software debugger, and there is a hardware debugger but if they are not available EDK II debug macro might be a good place to start.

  • We believe the debug lib is the simplest and cleanest way to get it all working


@title[EDK II DebugLib Library]

EDK II DebugLib Library

@snap[north-west span-60 fragment]


@box[bg-gold2 text-white rounded my-box-pad2 ](

Debug and Assert macros in code
 

)
@snapend

@snap[north-east span-80 fragment]






 

@box[bg-green-pp text-white rounded my-box-pad2 ](

Enable/disable when compiled ("target.txt")
 

)
@snapend

@snap[north-west span-80 fragment]










 

@box[bg-purple-pp text-white rounded my-box-pad2 ](

Connects a Host to capture debug messages
 

)
@snapend

Note:

  • DebugLib library is clean & very portable

  • Using DEBUG and ASSERT macros in code

  • Enable/disable when compiled (target.txt)

  • Can connect a 2nd PC to capture debug messages

  • The main message-- the debug lib library is portable, it's clean, it's very easy to use, and we believe it's the easiest way to do debugging on a UEFI platform.

  • The debug lib library has the debug and assert macros.

  • There are library instances that allow you to use a second PC to capture all messages coming out

---?image=assets/images/binary-strings-black2.jpg @title[Debugging with PCDs]






     Debugging with PCDs

        

Note:


@title[Using PCDs to Configure DebugLib]

Using PCDs to Configure DebugLib

@snap[west span-100 ]
@box[bg-grey-05 text-white my-box-pad2 ](







  

) @snapend

@snap[north-west span-100 ]



MdePkg Debug Library Class


   [PcdsFixedAtBuild. PcdsPatchableInModule]
     gEfiMdePkgTokenSpaceGuid.@color[red](PcdDebugPropertyMask)|0x1f
     gEfiMdePkgTokenSpaceGuid.@color[red](PcdDebugPrintErrorLevel)|0x80000040

@snapend

@snap[south span-90 fragment] @box[bg-purple-pp text-white rounded my-box-pad2 ](

PCDs set which drivers report errors and change what messages get printed
 

)
@snapend

Note:

  • MdePkg Debug Library Class

    • PcdDebugPropertyMask
  • Bit mask to determine which features are on/off

    • PcdDebugPrintErrorLevel
    • Types of messages produced
  • PCDs set which drivers report errors and change what messages get printed

  • Example from EmulatorPkg.dsc:

    • [PcdsFixedAtBuild.IA32]
      • EfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x1f
      • gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000040
  • How do you configure the debug lib?

  • It is configured through PCD entries and some platform configuration database entries.

  • This is part of the MDE package, where is the debug library class is defined.

  • Remember, the library instance can be anywhere, but the library class is defined in the MDE package. This is where the PCDs are defined.

  • It is required for the debug Lib instance to use these PCDs for control.

  • PcdDebugPropertyMask and PcdDebugPrintErrorLevel can change sets of driver report errors, and they can also change the error messages that print out.

  • Per the example at the bottom of the slide, the assignment for PcdDebugPropertyMask is 0x1f and PcdDebugPrintErrorLevel is 0x80000040 . These are the values for these two PCDs.


@title[PcdDebugPropertyMask Values]

@color[white](PcdDebugPropertyMask) Values

@snap[north-west span-100 ]


 

@box[bg-grey-05 text-white my-box-pad2 ](








  

) @snapend

@snap[north-west span-100 ]

Debugging Features Enabled

     #define DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED        0x01
     #define DEBUG_PROPERTY_DEBUG_PRINT_ENABLED         0x02
     #define DEBUG_PROPERTY_DEBUG_CODE_ENABLED          0x04
     #define DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED        0x08
     #define DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED   0x10
     #define DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED     0x20

Default value in OvmfPkg is 0x2f
Default value in EmulatorPkg is 0x1f

@snapend

@snap[south span-90 fragment]

@box[bg-purple-pp text-white rounded my-box-pad2 ](

Determines which debugging features are enabled.
 

)
@snapend

Note:

  • Enables debugging features
  • What kinds of outputs are produced?
  • What kind of debugging is being done?
 #define DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED       0x01
 #define DEBUG_PROPERTY_DEBUG_PRINT_ENABLED        0x02
 #define DEBUG_PROPERTY_DEBUG_CODE_ENABLED         0x04
 #define DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED       0x08
 #define DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED  0x10
 #define DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED    0x20
  • another Note: Default value in EmulatorPkg is 0x1f

  • Determines which debugging features are enabled.

  • What kinds of output are produced.

  • What kind of debugging is being done.

  • Default in Ntr32 is 0x1f

  • So what does that mean?

  • for DebugPropertyMask, 1F turns on:

    • debug assert,
    • debug print,
    • debug code enabled,
    • clear memory,
    • assert breakpoint
  • It does not turn on assert dead loop.

  • This turns on the debug features for the property mask one at a time. The property mask tells the debug command what we really want to have happen.


@title[PcdDebugPrintErrorLevel Values]

@color[white](PcdDebugPrintErrorLevel) Values

Debugging Messages Displayed

 #define DEBUG_INIT      0x00000001  // Initialization
 #define DEBUG_WARN      0x00000002  // Warnings
 #define DEBUG_LOAD      0x00000004  // Load events
 #define DEBUG_FS        0x00000008  // EFI File system
 #define DEBUG_POOL      0x00000010  // Alloc & Free's  Pool
 #define DEBUG_PAGE      0x00000020  // Alloc & Free's  Page
 #define DEBUG_INFO      0x00000040  // Verbose
 #define DEBUG_DISPATCH  0x00000080  // PEI/DXE Dispatchers
 #define DEBUG_VARIABLE  0x00000100  // Variable
 #define DEBUG_BM        0x00000400  // Boot Manager
 #define DEBUG_BLKIO     0x00001000  // BlkIo Driver
 #define DEBUG_NET       0x00004000  // SNP / Network Io Driver
 #define DEBUG_UNDI      0x00010000  // UNDI Driver
 #define DEBUG_LOADFILE  0x00020000  // Load File 
 #define DEBUG_EVENT     0x00080000  // Event messages
 #define DEBUG_GCD       0x00100000  // Global Coherency Database changes
 #define DEBUG_CACHE     0x00200000  // Memory range cache-ability changes
 #define DEBUG_VERBOSE   0x00400000  // Detailed debug messages that may
                                     // significantly impact boot performance
 #define DEBUG_ERROR     0x80000000  // Error

    Aliases EFI_D_INIT == DEBUG_INIT, etc...
 

Default value in OvmfPkg is 0x8000004f          Default value in EmulatorPkg is 0x80000040

@snap[south span-90 fragment]

@box[bg-purple-pp text-white rounded my-box-pad2 ](

Determines which messages we want to print
 

)

@snapend

Note:

  • Determines if each print message is displayed

  • Use Binary-AND setting to set parameter TRUE

  • Note that Aliases EFI_D_INIT == DEBUG_INIT, etc..

  • DebugPrintErrorLevel Values

  • This has to do with what messages we want to come out

  • Let's say you have a debug print enabled as in the previous slide.

    • You must state what message type you want to print out
  • You can assign your own values to this debug print error level.

  • However, these are the guideline values that these drivers use in terms of what their debug output messaging will be.


@title[Changing PCD Values ]

Changing PCD Values

@snap[north-west span-100 fragment]

@color[yellow](Change all instances of a PCD in platform DSC)

@box[bg-black text-white rounded my-box-pad2 ](

  [PcdFixedAtBuild]
  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x00000000
  

)
@snapend

@snap[north-west span-90 rounded fragment]






@color[yellow](Change a single module's PCD values in the DSC)

@box[bg-black text-white rounded my-box-pad2 ](

  MyPath/MyModule.inf {
  <PcdFixedAtBuild>
  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x00000000
  }
  

)
@snapend

@snap[south span-100 fragment]

@box[bg-purple-pp text-white rounded my-box-pad2 ](

Minimize message output and minimize size increase
 

)

@snapend

Note:

  • Use different PCD values only on the module being debugged
  • Minimize message output and minimize size increase

@title[Other Debug Related Libraries ]

Other Debug Related Libraries

@snap[north-west span-90 fragment]

@box[bg-green-pp text-white rounded my-box-pad2 ](

ReportStatusCodeLib - Progress codes
 

) @box[bg-black text-white rounded my-box-pad2 ](

  gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask 

)
@snapend

@snap[north-west span-90 fragment]






 

@box[bg-royal text-white rounded my-box-pad2 ](

PostCodeLib - Enable Post codes
 

) @box[bg-black text-white rounded my-box-pad2 ](

  gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask  

)
@snapend

@snap[north-west span-90 fragment]











 

@box[bg-gold2 text-white rounded my-box-pad2 ](

PerformanceLib - Enable Measurement
 

) @box[bg-black text-white rounded my-box-pad2 ](

  gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask  

)
@snapend

Note:

  • ReportStatusCodeLib - Progress codes
    • gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask
  • PostCodeLib - Enable Post codes
    • gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask
  • PerformanceLib - Enable Measurement
    • gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask

---?image=/assets/images/slides/Slide_LabSec.JPG @title[Lab 1: Adding Debug Statements]

Lab 1: Adding Debug Statements


In this lab, you'll add debug statements to the previous lab's SampleApp UEFI Shell application
 

Note: In this lab, you'll learn how to add debug statements.
This lab uses code from a previous exercise as a starting point (refer to Writing Simple UEFI Applications). Before proceeding, verify that the SampleApp code is present in your workspace and that the code references the OvmfPkgX64.dsc file.


@title[Lab 1: Catch Up SampleApp]

Lab 1: Catch up from previous lab

@snap[north-west span-60 ]










@box[bg-black text-white rounded my-box-pad2 ](


 

) @snapend

@snap[north-east span-98 ]











# Add new modules here
  SampleApp/SampleApp.inf

@snapend

@snap[north-west span-100 ]

Skip if Lab Writing UEFI App Lab completed

  • Perform Lab Setup from previous Labs
  • Create a Directory under the workspace @size[.8em](~/src/edk2-ws/edk2 : "SampleApp")
  • Copy contents of @size[.8em](~/FW/LabSampleCode/SampleAppDebug to ~/src/edk2-ws/edk2/SampleApp)
  • Open @size[.8em](~src/edk2-ws/edk2/OvmfPkg/OvmfPkgX64.dsc)
  • Add the following to the [Components] section:



  • Save and close the file @size[.8em](C:/FW/edk2-ws/edk2/OvmfPkg/OvmfPkgX64.dsc)
@snapend

Note:


@title[Lab 1: Add debug statements SampleApp]

Lab 1: Add debug statements to SampleApp

@snap[north-west span-85 ]





@box[bg-black text-white rounded my-box-pad2 ](



 

)





@box[bg-black text-white rounded my-box-pad2 ](

 

)

@snapend


  • Open a Teminal Prompt and type @size[.8em](cd ~/src/edk2-ws)




  • Open @size[.8em](~/src/edk2-ws/edk2/SampleApp/SampleApp.c)

  • Add the following to the include statements at the top of the file after the last "#include" statement:

@snap[north-east span-98 ]





bash$ export WORKSPACE=$PWD
bash$ export PACKAGES_PATH=$WORKSPACE/edk2:$WORKSPACE/edk2-libc
bash$ cd edk2
bash$ . edksetup.sh










#include <Library/DebugLib.h>

@snapend

Note:

From the terminal

    bash$ cd ~/src/edk2-ws
    bash$ export WORKSPACE=$PWD
    bash$ export PACKAGES_PATH=$WORKSPACE/edk2:$WORKSPACE/edk2-libc
    bash$ cd edk2
    bash$ . edksetup.sh
  • Add the following to the include statements at the top of the file after below the last “include” statement:
 #include <Library/DebugLib.h>

@title[Lab 1: Add debug statements SampleApp 02]

Lab 1: Add debug statements to SampleApp

Locate the UefiMain function. Then copy and paste the following code after the  "EFI_INPUT_KEY KEY;" statement: and before the first  Print() statement

DEBUG ((0xffffffff, "\n\nUEFI Base Training DEBUG DEMO\n") );
DEBUG ((0xffffffff, "0xffffffff USING DEBUG ALL Mask Bits Set\n") );

DEBUG ((DEBUG_INIT,     " 0x%08x USING DEBUG DEBUG_INIT\n" , (UINTN)(DEBUG_INIT))  );
DEBUG ((DEBUG_WARN,     " 0x%08x USING DEBUG DEBUG_WARN\n", (UINTN)(DEBUG_WARN))  );
DEBUG ((DEBUG_LOAD,     " 0x%08x USING DEBUG DEBUG_LOAD\n", (UINTN)(DEBUG_LOAD))  );
DEBUG ((DEBUG_FS,       " 0x%08x USING DEBUG DEBUG_FS\n", (UINTN)(DEBUG_FS))  );
DEBUG ((DEBUG_POOL,     " 0x%08x USING DEBUG DEBUG_POOL\n", (UINTN)(DEBUG_POOL))  );
DEBUG ((DEBUG_PAGE,     " 0x%08x USING DEBUG DEBUG_PAGE\n", (UINTN)(DEBUG_PAGE))  );
DEBUG ((DEBUG_INFO,     " 0x%08x USING DEBUG DEBUG_INFO\n", (UINTN)(DEBUG_INFO))  );
DEBUG ((DEBUG_DISPATCH, " 0x%08x USING DEBUG DEBUG_DISPATCH\n",(UINTN)(DEBUG_DISPATCH)));
DEBUG ((DEBUG_VARIABLE, " 0x%08x USING DEBUG DEBUG_VARIABLE\n",(UINTN)(DEBUG_VARIABLE)));
DEBUG ((DEBUG_BM,       " 0x%08x USING DEBUG DEBUG_BM\n", (UINTN)(DEBUG_BM))  );
DEBUG ((DEBUG_BLKIO,    " 0x%08x USING DEBUG DEBUG_BLKIO\n", (UINTN)(DEBUG_BLKIO))  );
DEBUG ((DEBUG_NET,      " 0x%08x USING DEBUG DEBUG_NET\n", (UINTN)(DEBUG_NET))  );
DEBUG ((DEBUG_UNDI,     " 0x%08x USING DEBUG DEBUG_UNDI\n", (UINTN)(DEBUG_UNDI))  );
DEBUG ((DEBUG_LOADFILE, " 0x%08x USING DEBUG DEBUG_LOADFILE\n",(UINTN)(DEBUG_LOADFILE)));
DEBUG ((DEBUG_EVENT,    " 0x%08x USING DEBUG DEBUG_EVENT\n", (UINTN)(DEBUG_EVENT))  );
DEBUG ((DEBUG_GCD,      " 0x%08x USING DEBUG DEBUG_GCD\n", (UINTN)(DEBUG_EVENT))  );
DEBUG ((DEBUG_CACHE,    " 0x%08x USING DEBUG DEBUG_CACHE\n", (UINTN)(DEBUG_EVENT))  );
DEBUG ((DEBUG_VERBOSE,  " 0x%08x USING DEBUG DEBUG_VERBOSE\n", (UINTN)(DEBUG_EVENT))  );
DEBUG ((DEBUG_ERROR,    " 0x%08x USING DEBUG DEBUG_ERROR\n", (UINTN)(DEBUG_ERROR))  );

Note:

---?image=/assets/images/slides/Slide16.JPG @title[Lab 1: Update the Qemu Script]

Lab 1: Update the Qemu Script

@snap[north-west span-50 ]




@box[bg-black text-white rounded my-box-pad2 ](

 

) @snapend

@snap[north-west span-100 ]

Edit the Linux shell script to run the QEMU from the run-ovmf directory and add the option for a serial log


   @size[.8em](bash$ gedit RunQemu.sh)



qemu-system-x86_64 -pflash bios.bin -hda fat:rw:hda-contents \
-net none -debugcon file:debug.log \
-global isa-debugcon.iobase=0x402 -serial file:serial.log

 

Save and Exit

@snapend

Note:

 qemu-system-x86_64 -pflash bios.bin -hda fat:rw:hda-contents -net none     -debugcon file:debug.log -global isa-debugcon.iobase=0x402  -serial file:serial.log

@title[Lab 1 Build and Test Application]

Lab 1: Build and Test Application


Build SampleApp - Cd to ~/src/edk2-ws/edk2 dir ```shell bash$ build ``` Copy the OVMF.fd to the run-ovmf directory naming it bios.bin ```shell bash$ cd ~/run-ovmf bash$ cp cp ~/src/edk2-ws/Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd bios.bin ```

Copy SampleApp.efi to hda-contents

 bash$ cd ~/run-ovmf/hda-contents
 bash$ cp ~/src/edk2-ws/Build/OvmfX64/DEBUG_GCC5/X64/SampleApp.efi .

Note:

---?image=/assets/images/slides/Slide18.JPG @title[Lab 1: Run Qemu Script]

Lab 1: Run the Qemu Script

@snap[north-west span-50 ]







@box[bg-black text-white rounded my-box-pad2 ](


 

)



@box[bg-black text-white rounded my-box-pad2 ](

 

)








@box[bg-black text-white rounded my-box-pad2 ](

 

)

@snapend

@snap[north-west span-50 ]

Test by Invoking Qemu


   bash$ cd ~/run-ovmf
   bash$ . RunQemu.sh


Run the application from the shell
   @size[.7em](@color[yellow](Shell>)  SampleApp) 

Check the contents of the debug.log file

   @size[.7em]( bash$ cat debug.log)

Exit QEMU

Note:

---?image=/assets/images/slides/Slide_LabSec.JPG @title[Lab 2: Changing PCD Value]

Lab 2: Changing PCD Value


In this lab, you'll learn how to use PCD values to change debugging capabilities.
 

Note: In this lab, you'll learn how to use PCD values to change debugging capabilities. The previous lab, Adding Debug Statements, did not display all the DEBUG messages added to SampleApp.c. This lab shows how to change this behavior.


@title[Lab 2: Change PCDs for SampleApp]

Lab 2: Change PCDs for SampleApp


Open `~src/edk2-ws/edk2/OvmfPkg/OvmfPkgX64.dsc`
Replace `SampleApp/SampleApp.inf` with the following:
```c SampleApp/SampleApp.inf { gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xff gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xffffffff } ``` Save and close ~src/edk2-ws/edk2/OvmfPkg/OvmfPkgX64.dsc
Build SampleApp :   bash$ build  
Copy SampleApp.efi to hda-contents ```shell bash$ cd ~/run-ovmf/hda-contents bash$ cp ~/src/edk2-ws/Build/OvmfX64/DEBUG_GCC5/X64/SampleApp.efi . ```

Note:

---?image=/assets/images/slides/Slide21.JPG @title[Lab 2: Run Qemu Script]

Lab 2: Run the Qemu Script

@snap[north-west span-50 ]







@box[bg-black text-white rounded my-box-pad2 ](


 

)



@box[bg-black text-white rounded my-box-pad2 ](

 

)








@box[bg-black text-white rounded my-box-pad2 ](

 

)

@snapend

@snap[north-west span-50 ]

Test by Invoking Qemu


   bash$ cd ~/run-ovmf
   bash$ . RunQemu.sh


Run the application from the shell
   @size[.7em](@color[yellow](Shell>)  SampleApp) 

Check the contents of the debug.log file

   @size[.7em]( bash$ cat debug.log)

Exit QEMU

Note:

  • Test by Invoking Qemu

  • bash$ cd ~/run-ovmf

  • bash$ . RunQemu.sh

  • Run the application from the shell

  • Shell> SampleApp

  • Check the contents of the debug.log file

  • bash$ cat debug.log

  • Exit QEMU

---?image=assets/images/binary-strings-black2.jpg @title[Changing Compiler & Linker Flags Section]






     Changing Flags

        Changing Compiler & Linker Flags

Note:


@title[Precedence for Debug Flags Hierarchy]

Precedence for Debug Flags Hierarchy

@snap[north span-85 fragment]

@box[bg-green-pp text-white waved ](

Tools_def.txt

 

) @snapend

@snap[north span-70 fragment]



@box[bg-navy text-white waved ](

DSC [BuildOptions] section (platform scope)
 

) @snapend

@snap[north-west span-50 fragment]





@box[bg-purple-pp text-white waved ](

INF [BuildOptions] section
 

) @snapend

@snap[north-east span-50 fragment]





@box[bg-lt-blue-pp text-white waved ](

DSC <BuildOptions> under a specific module
 

) @snapend

@snap[south span-70 fragment] @box[bg-grey-05 text-white rounded my-box-pad2](

   1. Tools_def.txt
   2. DSC [BuildOptions] section (platform scope)
   3. INF [BuildOptions] section (module scope)
   4. DSC <BuildOptions> under a specific module
  

)

@snapend

Note:

  • think of the rules for compiler switches and options as a pyramid

  • Pyramid top overrides middle, middle overrides the bottom

  • Tools_def.txt

    • Baseline set of command line options for compiler and linker
  • INF [BuildOptions] section

    • Append onto existing command line with "="
    • Replace entire existing command line with "=="
  • DSC [BuildOptions] section (platform scope)

    • Same usage
  • DSC under a specific module

    • Same usage

@title[Compiler / Linker Flags]

Compiler / Linker Flags

@snap[north-west span-100]

@color[#A8ff60](Example from Microsoft* compiler to turn off optimization)

  "/02 " to "/01" requires "/0d /01"


@snapend

@snap[north-west span-90 rounded fragment]




@color[yellow](Change common flags in platform DSC)

@box[bg-grey-05 text-white rounded my-box-pad2 ](

  [BuildOptions] 
    DEBUG_*_IA32_CC_FLAGS = /Od /Oy-
  

)
@snapend

@snap[north-west span-90 rounded fragment]








@color[yellow](Change a single module's flags in the DSC)

@box[bg-grey-05 text-white rounded my-box-pad2 ](

  MyPath/MyModule.inf {
  <BuildOptions>
    DEBUG_*_IA32_CC_FLAGS = /Od /Oy-
  }
  

)
@snapend

Note:

  • Change common flags in platform DSC

  • [BuildOptions]

    • DEBUG_*_IA32_CC_FLAGS = /Od
  • Change a single module's flags in DSC

  • MyPath/MyModule.inf {

  • - DEBUG_*_IA32_CC_FLAGS = /Od
  • }

  • Change optimizations, etc. . .

---?image=assets/images/binary-strings-black2.jpg @title[DebugLib Usage Section]






     DebugLib Usage

        

Note:

---?image=/assets/images/slides/Slide26.JPG @title[DebugLib Class]

The DebugLib Class

@snap[north-west span-85]



 

@box[bg-ubuntu text-white my-box-pad2 ](

  MdePkg/Include/Library/DebugLib.h
  

)
@snapend

@snap[north-west span-80 rounded fragment]



Macros
@size[0.65em]((where PCDs ard checked))

@box[bg-grey-05 text-white rounded my-box-pad2 ](

  ASSERT (Expression)
  DEBUG (Expression)
  ASSERT_EFI_ERROR (StatusParameter)
  ASSERT_PROTOCOL_ALREADY_INSTALLED(. . .)
  

)
@snapend

@snap[north-west span-80 rounded fragment]









Advanced Macros

@box[bg-grey-05 text-white rounded my-box-pad2 ](

  DEBUG_CODE (Expression)
  DEBUG_CODE_BEGIN() & DEBUG_CODE_END()
  DEBUG_CLEAR_MEMORY(...)
  

)
@snapend

Note:

  • This is the interface so it will be describing the title of the function and / or Macro not the implementation

  • The interface will describe the parameters needed

  • MdePkg\Include\Library\DebugLib.h

  • Do not call internal worker functions directly

  • Macros are where the PCDs are checked

    • ASSERT (Expression)

    • DEBUG (Expression)

    • ASSERT_EFI_ERROR (StatusParameter)

    • ASSERT_PROTOCOL_ALREADY_INSTALLED(...)

    • Advanced Macros:

    • DEBUG_CODE (Expression)

    • DEBUG_CODE_BEGIN() & DEBUG_CODE_END()

    • DEBUG_CLEAR_MEMORY(...)

---?image=/assets/images/slides/Slide27.JPG @title[DebugLib Instances (1)]

DebugLib Instances (1)

@snap[north-west span-75]






 

@box[bg-ubuntu text-white my-box-pad2 ](

  BaseDebugLibSerialPort
  

)
@snapend

@snap[north-west span-100]





 

@box[bg-blue-pp text-white my-box-pad2 ](

  











  

)
@snapend

@snap[north-west span-90]






 

  • Instance of DebugLib
  • Uses SerialPortLib class to send debug output to serial port
  • Default for many platforms: BaseDebugLibNull
  • OVMF uses it with Switch DEBUG_ON_SERIAL_PORT
@snapend

@snap[south-east span-20] implementation @snapend

@snap[south-east span-20]

@color[black](     1)   

 


@snapend

Note:

  • debugLib library instances

  • The first debug Lib library instance is the BaseDebugLibSerialPort this is a debug Lib that is good for PEI and DXE. It uses the serial Port Lib class and sends all the debug information out the serial port.

  • Every time that you type DEBUG, it prints the information to the serial port such that if there is another PC capturing that information out the serial port, it allows easy viewing of the debug information.

  • This is good because it works early on in the platform. You can run very early and get a lot of debug information.

  • At this point the only serial port library instance that is in the public domain or open source is the DUET version

---?image=/assets/images/slides/Slide27.JPG @title[DebugLib Instances (2)]

DebugLib Instances (2)

@snap[north-west span-80]






 

@box[bg-ubuntu text-white my-box-pad2 ](

  UefiDebugLibConOut   UefiDebugLibStdErr
  

)
@snapend

@snap[north-west span-100]





 

@box[bg-navy text-white my-box-pad2 ](

  











  

)
@snapend

@snap[north-west span-90]






 

  • Instances of DebugLib (for apps and drivers)

  • Send all debug output to console/debug console
@snapend

@snap[south-east span-20] implementation @snapend

@snap[south-east span-20]

@color[black](     2)   

 


@snapend

Note:

  • UefiDebugLibConOut UefiDebugLibStdErr
  • Instances of DebugLib (for Apps and Drivers)
  • Send all debug output out to console/debug console
  • This allows for viewing of debug information
  • Make sure that the console is visible

---?image=/assets/images/slides/Slide27.JPG @title[DebugLib Instances (3)]

DebugLib Instances (3)

@snap[north-west span-75]






 

@box[bg-ubuntu text-white my-box-pad2 ](

  PeiDxeDebugLibReportStatusCode
  

)
@snapend

@snap[north-west span-100]





 

@box[bg-green-pp text-white my-box-pad2 ](

  











  

)
@snapend

@snap[north-west span-90]






 

  • Sends ASCII String specified by Description Value to the ReportStatusCode()
  • May also use the SerialPortLib class to send debug output to serial port
  • BaseDebugLibNull - Resolves references


Default for most platforms

@snapend

@snap[south-east span-20] implementation @snapend

@snap[south-east span-20]

@color[black](     3)   

 


@snapend

Note:

  • So there are a total of 5 open source debug lib instances

  • The ones we did not cover are "DebugLibNull" - does nothing and

  • "PeiDxeDebugLibReportStatusCode " is a form of 'DebugLibReportStatusCode" that wraps into the report status code library the same way that the serial port one does and may send ASCII String specified by Description Value that is sent to ReportStatusCode() function

  • So there may be other instances in your workspace. It is easy to develop a new library instance. There is no requirement that someone tell us that they've done it.

  • So what you want to do is search for the library name equals in the INF file.

  • Example search the INF files in your workspace for the string "LIBRARY_CLASS = DebugLib"

  • the ASCII string specified by Description is also passed to the handler that displays the POST card value. Some implementations of this library function may perform I/O operations directly to a POST card device. Other implementations may send Value to ReportStatusCode(),


@title[Changing Library Instances ]

Changing Library Instances

@snap[north-west span-90 rounded fragment]

@color[yellow](Change common library instances in the platform DSC by Module type)

@box[bg-grey-05 text-white rounded my-box-pad2 ](

  [LibraryClasses.common.IA32] 
    DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
  

)
@snapend

@snap[north-west span-90 rounded fragment]






@color[yellow](Change a single module's library instance in the platform DSC)

@box[bg-grey-05 text-white rounded my-box-pad2 ](

  MyPath/MyModule.inf {
  <LibraryClasses>
    DebugLib|MdePkg/Library/BaseDebugLibSerialPort.inf
  }
  

)
@snapend

Note:

  • Change common library instances in the platform DSC by module type
  [LibraryClasses.common.IA32]
    DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
  • Change a single module's library instance in the platform DSC
  MyPath/MyModule.inf {
    
     DebugLib|MdePkg/Library/BaseDebugLibSerialPort.inf
  }
  • another Note: Use a different debugging library instance only on the module in question (managing size changes)

---?image=/assets/images/slides/Slide_LabSec.JPG @title[Lab 3: Library Instances for Debugging]

Lab 3: Library Instances for Debugging


In this lab, you'll learn how to add specific debug library instances.
 

Note:


@title[Lab 3: Using Library Instances for Debugging]

Lab 3: Using Library Instances for Debugging


Open ~src/edk2-ws/edk2/OvmfPkg/OvmfPkgX64.dsc
Replace SampleApp/SampleApp.inf { . . .} with the following:
```c SampleApp/SampleApp.inf { DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf } ``` Save and close ~src/edk2-ws/edk2/OvmfPkg/OvmfPkgX64.dsc
Build SampleApp :   bash$ build  
Copy SampleApp.efi to hda-contents ```shell bash$ cd ~/run-ovmf/hda-contents bash$ cp ~/src/edk2-ws/Build/OvmfX64/DEBUG_GCC5/X64/SampleApp.efi . ```

Note:

---?image=/assets/images/slides/Slide33.JPG @title[Lab 3: Run Qemu Script]

Lab 3: Run the Qemu Script

@snap[north-west span-50 ]







@box[bg-black text-white rounded my-box-pad2 ](


 

)



@box[bg-black text-white rounded my-box-pad2 ](

 

)










@box[bg-black text-white rounded my-box-pad2 ](

 

)

@snapend

@snap[north-west span-50 ]

Test by Invoking Qemu


   bash$ cd ~/run-ovmf
   bash$ . RunQemu.sh


Run the application from the shell
   @size[.7em](@color[yellow](Shell>)  SampleApp) 

See that the output from the Debug statements now goes to the QEMU console

   @size[.7em]( bash$ cat debug.log)

Exit QEMU

Note:

  • Test by Invoking Qemu

  • bash$ cd ~/run-ovmf

  • bash$ . RunQemu.sh

  • Run the application from the shell

  • Shell> SampleApp

  • See that the output from the Debug statements now goes to the QEMU console

  • bash$ cat debug.log

  • Exit QEMU

---?image=/assets/images/slides/Slide_LabSec.JPG @title[Lab 4: Serial port Instance of DebugLib]

Lab 4: Serial port Instance of DebugLib


In this lab, you'll change the DebugLib to the Serial port instance.
 

Note:

The DEBUG output for SampleApp is redirected to the serial.log file. This debug library instance only applies to SampleApp and does not alter the general debug behavior of other modules. To change the entire debug to Serial.log the switch "-D DEBUG_ON_SERIAL_PORT" can be used with the Build command.


@title[Lab 4: Using Serial port Library Instances]

Lab 4: Using Serial port Library Instances


Open ~src/edk2-ws/edk2/OvmfPkg/OvmfPkgX64.dsc
Replace SampleApp/SampleApp.inf { . . .} with the following:
```c SampleApp/SampleApp.inf { DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf } ``` Save and close ~src/edk2-ws/edk2/OvmfPkg/OvmfPkgX64.dsc
Build SampleApp :   bash$ build  
Copy SampleApp.efi to hda-contents ```shell bash$ cd ~/run-ovmf/hda-contents bash$ cp ~/src/edk2-ws/Build/OvmfX64/DEBUG_GCC5/X64/SampleApp.efi . ```

Note:

---?image=/assets/images/slides/Slide36.JPG @title[Lab 4: Run Qemu Script]

Lab 4: Run the Qemu Script

@snap[north-west span-50 ]







@box[bg-black text-white rounded my-box-pad2 ](


 

)



@box[bg-black text-white rounded my-box-pad2 ](

 

)





@box[bg-black text-white rounded my-box-pad2 ](

 

)

@snapend

@snap[north-west span-50 ]

Test by Invoking Qemu


   bash$ cd ~/run-ovmf
   bash$ . RunQemu.sh


Run the application from the shell
   @size[.7em](@color[yellow](Shell>)  SampleApp) 

Check the contents of the serial.log file

   @size[.7em]( bash$ cat serial.log)

Exit QEMU

Note:

  • Test by Invoking Qemu

  • bash$ cd ~/run-ovmf

  • bash$ . RunQemu.sh

  • Run the application from the shell

  • Shell> SampleApp

  • Check the contents of the serial.log file

  • bash$ cat serial.log

  • Exit QEMU

---?image=/assets/images/slides/Slide_LabSec.JPG @title[Lab 5: Debugging EDK II with GDB]

Lab 5: Debugging EDK II with GDB


In this lab, you'll learn how setup the Linux GDB to use with EDK II and Qemu
See also the tianocore.org wiki page:
How to use GDB with QEMU
 

Note:


@title[Lab 5.1: Update the Qemu Script]

Lab 5.1: Update the Qemu Script


Edit the Linux shell script to run the QEMU from the run-ovmf directory and add the option for GDB "@color[yellow](-s)" to generate a symbol file and also use IA32 instead of x86_64

```shell bash$ cd ~/run-ovmf bash$ gedit RunQemu.sh ``` Add the following to RunQemu.sh ```shell qemu-system-i386 -s -pflash bios.bin -hda fat:rw:hda-contents -net none -debugcon file:debug.log -global isa-debugcon.iobase=0x402 ``` Save and Exit

Note:

  • Lab 5.1
  • add the following to the script
  qemu-system-i386 -s -pflash bios.bin -hda fat:rw:hda-contents -net none     -debugcon file:debug.log -global isa-debugcon.iobase=0x402  -serial file:serial.log

@title[Lab 5.2: Build Ovmf for IA32]

Lab 5.2: Build Ovmf for IA32


Open @size[.8em](~/src/edk2-ws/edk2/OvmfPkg/OvmfPkgIa32.dsc) and add the application to the (using IA32 ) at the end of the @size[.8em]([Components]) section.

```php [Components] # add at the end of the components section OvmfPkgIa32.dsc SampleApp/SampleApp.inf ``` Build OVMF for IA32 : ```shell bash$ build -a IA32 -p OvmfPkg/OvmfPkgIa32.dsc ```

Copy the the OVMF.fd to the run-ovmf directory renaming it bios.bin:

bash$ cd ~/run-ovmf/
bash$ cp ~/src/edk2-ws/Build/OvmfIa32/DEBUG_GCC5/FV/OVMF.fd  bios.bin

Note:

  • lab 5.2

@title[Lab 5.3: Build Ovmf for IA32 03]

Lab 5.3: Build Ovmf for IA32


Copy the output of SampleApp to the hda-contents directory: ```shell bash$ cd ~/run-ovmf/hda-contents bash$ cp ~/src/edk2-ws/Build/OvmfIa32/DEBUG_GCC5/IA32/SampleApp . ``` The following will be in the ~/run-ovmf/hda-contents/ ```shell SampleApp.efi SampleApp.debug SampleApp (Directory) ``` Open a Terminal(1) Prompt and Invoke Qemu ```shell bash$ cd ~/run-ovmf bash$ . RunQemu.sh ``` Run the application from the shell
 @color[yellow](Shell>) SampleApp 

Note:

  • lab 5.3

@title[Lab 5.4: Check debug.log ]

Lab 5.4: Check debug.log


Open another Terminal(2) Prompt in the run-ovmf directory and check the debug.log file.

```shell bash$ cd ~/run-ovmf bash$ cat debug.log ```

See the line: Loading driver at 0x00006AEE000 is the memory location where your UEFI Application is loaded.

```shell InstallProtocolInterface: 5B1B31A1-9562-11D2-8E3F-00A0C969723B 6F0F028 Loading driver at 0x00006AEE000 EntryPoint=0x00006AEE756 SampleApp.efi InstallProtocolInterface: BC62157E-3E33-4FEC-9920-2D3B36D750DF 6F0FF10 ```

Note:

  • lab 5.4

@title[Lab 5.5: Add a Debug Print]

Lab 5.5: Add a Debug Print

Add a DEBUG statement to your SampleApp.c application to get the entry point of your code.
Add the following DEBUG line just before the DEBUG statements from the previous lab:

```C UefiMain ( // . . . EFI_INPUT_KEY Key; // ADD the following line DEBUG ((EFI_D_INFO, "My Entry point: 0x%p\r\n", (CHAR16*)UefiMain ) ); ```

When you print out the debug.log again, the exact entry point for your code will show.
This is useful to double check symbols are fixed up to the correct line numbers in the source file.

```shell Loading driver at 0x00006AEE000 EntryPoint=0x00006AEE756 SampleApp.efi InstallProtocolInterface: BC62157E-3E33-4FEC-9920-2D3B36D750DF 6F0FF10 ProtectUefiImageCommon - 0x6F0F028 - 0x0000000006AEE000 - 0x0000000000002B00 InstallProtocolInterface: 752F3136-4E16-4FDC-A22A-E5F46812F4CA 7EA4B00 My Entry point: 0x06AEE496 ```

Note:

  • lab 5.5

@title[Lab 5.6: Invoking GDB]

Lab 5.6: Invoking GDB

In the terminal(2) prompt Invoke GDB(note - at first there will be nothing in the source window) ```shell bash$ cd ~/run-ovmf/hda-contents bash$ gdb --tui ``` Load your UEFI Application SampleApp.efi with the "file" command. ```shell (gdb) file SampleApp.efi Reading symbols from SampleApp.efi...(no debugging symbols found)...done. ```

Check where GDB has for ".text" and ".data" offsets with "info files" command.

```shell (gdb) info files Symbols from "/home/u-mypc/run-ovmf/hda-contents/SampleApp.efi". Local exec file: `/home/u-mypc/run-ovmf/hda-contents/SampleApp.efi', file type pei-i386. Entry point: 0x756 0x00000240 - 0x000028c0 is .text 0x000028c0 - 0x00002980 is .data 0x00002980 - 0x00002b00 is .reloc ```

Note:

  • Lab 5.6
  • For the GDB commands, only type what is after the "(gdb)" prompt

@title[Lab 5.7: Calculate Addresses]

Lab 5.7: Calculate Addresses


We need to calculate our addresses for ".text" and ".data" section.
The application is loaded under 0x00006AEE000 (loading driver point - NOT Entrypoint) and we know text and data offsets.

```shell text = 0x00006AEE000 + 0x00000240 = 0x06AEE240 data = 0x00006AEE000 + 0x00000240 + 0x000028c0 = 0x06AF0B00 ``` Unload the .efi file ```shell (gdb) file No executable file now. No symbol file now. ```

Note:

  • Lab 5.7
  • For the GDB commands, only type what is after the "(gdb)" prompt

@title[Lab 5.8: Load the Symbols for SampleApp]

Lab 5.8: Load the Symbols for SampleApp


Load the symbols with the fixed up address using SampleApp output .debug file using the "add-symbol-file" command:

```shell (gdb) add-symbol-file SampleApp.debug 0x06AEE240 -s .data 0x06AF0B00 add symbol table from file "SampleApp.debug" at
    .text_addr = 0x6aee240
    .data_addr = 0x6af0b00

(y or n) y Reading symbols from SampleApp.debug...done.

<span style="font-size:0.7em" >Set a break point at UefiMain</span>
```shell
(gdb) break UefiMain
Breakpoint 1 at 0x6aee496: file /home/u-uefi/src/edk2-ws/edk2/SampleApp/SampleApp.c, line 40.

Note:

  • Lab 5.8
  • For the GDB commands, only type what is after the "(gdb)" prompt

@title[Lab 5.9: Attach GDB to QEMU]

Lab 5.9: Attach GDB to QEMU

Attach the GDB debugger to QEMU

(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x07df6ba4 in ?? ()

Continue in GDB

(gdb) c
Continuing.

In the QEMU Window Invoke your application again

Fs0:\> SampleApp.efi

The GDB will hit your break point in your UEFI application's entry point and you can begin to debug with source code debugging.

Note:

  • Lab 5.9
  • For the GDB commands, only type what is after the "(gdb)" prompt

---?image=/assets/images/slides/Slide47.JPG @title[Lab 5: GBD and QEMU Windows]

Lab 5: GBD and QEMU Windows

The GDB window will look similar to this

Note:

  • Lab 5.10

@title[Summary]

Summary


  • @fa[certificate gp-bullet-green]  Define DebugLib and its attributes
  • @fa[certificate gp-bullet-cyan]  List the ways to debug
  • @fa[certificate gp-bullet-gold]  Using PCDs to Configure DebugLib - LAB
  • @fa[certificate gp-bullet-ltgreen]  Change Compiler & Linker Flags for debugging
  • @fa[certificate gp-bullet-yellow]  Change the DebugLib instance to modify the debug
            output - LAB
  • @fa[certificate gp-bullet-magenta]  Debug EDK II using GDB - LAB

---?image=assets/images/gitpitch-audience.jpg @title[Questions]
Questions


@title[return to main]

@size[1.2em](Return to Main Training Page)






Return to Training Table of contents for next presentation link

@snap[north span-30 ]


trainingLogo @snapend

---?image=assets/images/gitpitch-audience.jpg @title[Logo Slide]


![Logo Slide](/assets/images/TianocoreLogo.png =10x)


@title[Acknowledgements]

Acknowledgements

/**
Redistribution and use in source (original document form) and 'compiled' forms (converted
to PDF, epub, HTML and other formats) with or without modification, are permitted provided
that the following conditions are met:

Redistributions of source code (original document form) must retain the above copyright 
notice, this list of conditions and the following disclaimer as the first lines of this 
file unmodified.

Redistributions in compiled form (transformed to other DTDs, converted to PDF, epub, HTML
and other formats) must reproduce the above copyright notice, this list of conditions and 
the following disclaimer in the documentation and/or other materials provided with the 
distribution.

THIS DOCUMENTATION IS PROVIDED BY TIANOCORE PROJECT "AS IS" AND ANY EXPRESS OR IMPLIED 
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TIANOCORE PROJECT BE 
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.

Copyright (c) 2019, Intel Corporation. All rights reserved.
**/