UEFI 실전-DEBUG

17837 단어 UEFI 개발 기반

약술


UEFI 개발에서 가장 중요한 부분은 직렬 디버깅 정보 인쇄를 추가하는 것입니다. 이것은 DEBUG 매크로를 통해 완성됩니다.
UEFI 코드에서는 다음과 같은 매우 많은 DEBUG 코드를 볼 수 있습니다.
  DEBUG ((EFI_D_INFO, "PlatformBootManagerBeforeConsole
"));

주의해야 할 사항은 다음과 같습니다.
1. 괄호는 이중이고 아래는 첫 번째 파라미터, 두 번째 파라미터로 각각 EFI 라고 부른다.D_xx와 문자열이지만 실제로는 약간의 문제가 있습니다.
2. 두 번째 매개 변수는 문자열입니다. 이 문자열 안에는 포맷 로고도 사용할 수 있습니다. 다음은 DEBUG에서 자주 사용하는 로고입니다.
  • %a: ASCII 문자열을 나타냅니다.
  • %c: ASCII 문자를 나타냅니다.
  • %d: 10진법을 나타내는데%02d와 같은 용법이 있을 수 있다.
  • %g: GUID를 나타냅니다.
  • %p: 지침을 나타낸다.
  • %r: 함수의 반환 상태 문자열을 나타내는 유형은 EFISTATUS;
  • x: 16진법을 나타내고%016lx와 같은 용법이 있을 수 있으며 이렇게 부족한 전치위는 0으로 보충할 수 있다.
  • %lx: 64비트의 16진수를 나타낸다.
  • %ld: 64비트의 10진수를 나타낸다.
  • %s/%S: 넓은 문자열을 나타내는 것은 L''와 유사한 문자열이고 유형은CHAR16이다.

  • 3. 첫 번째 매개변수는 플롯 레벨을 나타내고 다음 매개변수는 플롯 레벨을 나타냅니다.
    //
    // Declare bits for PcdDebugPrintErrorLevel and the ErrorLevel parameter of DebugPrint()
    //
    #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 (pool)
    #define DEBUG_PAGE      0x00000020  // Alloc & Free (page)
    #define DEBUG_INFO      0x00000040  // Informational debug messages
    #define DEBUG_DISPATCH  0x00000080  // PEI/DXE/SMM Dispatchers
    #define DEBUG_VARIABLE  0x00000100  // Variable
    #define DEBUG_BM        0x00000400  // Boot Manager
    #define DEBUG_BLKIO     0x00001000  // BlkIo Driver
    #define DEBUG_NET       0x00004000  // SNP Driver
    #define DEBUG_UNDI      0x00010000  // UNDI Driver
    #define DEBUG_LOADFILE  0x00020000  // LoadFile
    #define DEBUG_EVENT     0x00080000  // Event messages
    #define DEBUG_GCD       0x00100000  // Global Coherency Database changes
    #define DEBUG_CACHE     0x00200000  // Memory range cachability changes
    #define DEBUG_VERBOSE   0x00400000  // Detailed debug messages that may
                                        // significantly impact boot performance
    #define DEBUG_ERROR     0x80000000  // Error
    
    //
    // Aliases of debug message mask bits
    //
    #define EFI_D_INIT      DEBUG_INIT
    #define EFI_D_WARN      DEBUG_WARN
    #define EFI_D_LOAD      DEBUG_LOAD
    #define EFI_D_FS        DEBUG_FS
    #define EFI_D_POOL      DEBUG_POOL
    #define EFI_D_PAGE      DEBUG_PAGE
    #define EFI_D_INFO      DEBUG_INFO
    #define EFI_D_DISPATCH  DEBUG_DISPATCH
    #define EFI_D_VARIABLE  DEBUG_VARIABLE
    #define EFI_D_BM        DEBUG_BM
    #define EFI_D_BLKIO     DEBUG_BLKIO
    #define EFI_D_NET       DEBUG_NET
    #define EFI_D_UNDI      DEBUG_UNDI
    #define EFI_D_LOADFILE  DEBUG_LOADFILE
    #define EFI_D_EVENT     DEBUG_EVENT
    #define EFI_D_VERBOSE   DEBUG_VERBOSE
    #define EFI_D_ERROR     DEBUG_ERROR

    위의 매크로 정의에 대해서도 다음과 같이 설명할 수 있습니다.
    1) 먼저 여기에 두 층을 정의했는데 이것은 EDK와 EDKII의 호환 관계이기 때문에 일반적으로EFI로 시작하는 버전이 비교적 좋다.
    2) 특이한 것이 하나 있는데 EFID_ERROR, 이것은 가장 높은 1로 표시된 오류입니다.
    글로벌 PCD 변수의 구성에 따라 인쇄되는 레벨이 결정됩니다. 이 레벨은 다음에 설명합니다.
    4. DEBUG에서 인쇄 문자의 길이는 제한되어 있으며 최대 200자까지 가능합니다.
     

    큰 실현


    1. DEBUG 매크로의 위치는 MdePkg\Include\Library\DebugLib입니다.h 파일:
    /**  
      Macro that calls DebugPrint().
    
      If MDEPKG_NDEBUG is not defined and the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED 
      bit of PcdDebugProperyMask is set, then this macro passes Expression to 
      DebugPrint().
    
      @param  Expression  Expression containing an error level, a format string, 
                          and a variable argument list based on the format string.
      
    
    **/
    #if !defined(MDEPKG_NDEBUG)      
      #define DEBUG(Expression)        \
        do {                           \
          if (DebugPrintEnabled ()) {  \
            _DEBUG (Expression);       \
          }                            \
        } while (FALSE)
    #else
      #define DEBUG(Expression)
    #endif

    여기 MDEPKG 주의해야 돼요.NDEBUG 매크로, 이 매크로를 켜면 모든 DEBUG 정보가 인쇄되지 않을 것입니다. #else 분기가 갔기 때문입니다.
    MDEPKGNDEBUG 이 매크로는 일반적으로 dsc 파일에 정의됩니다. 여기는OvmfPkgX64입니다.dsc의 예:
    [BuildOptions]
      GCC:*_UNIXGCC_*_CC_FLAGS             = -DMDEPKG_NDEBUG
      GCC:RELEASE_*_*_CC_FLAGS             = -DMDEPKG_NDEBUG
      INTEL:RELEASE_*_*_CC_FLAGS           = /D MDEPKG_NDEBUG
      MSFT:RELEASE_*_*_CC_FLAGS            = /D MDEPKG_NDEBUG

    Release 버전에서는 디버깅 인쇄를 결정하기 위해 일반적으로 정의되는 것을 볼 수 있습니다. 이것도 이해할 수 있습니다.
    2. MDEPKG를 제외하고는NDEBUG 이 매크로는 Debug PrintEnabled ()
    이 함수는 DebugLib에 정의되어 있으며, 서로 다른 Pkg은 서로 다른 실현이 있을 수 있으며,OvmfPkgX64로 정의될 수 있습니다.dsc의 예:
    !ifdef $(DEBUG_ON_SERIAL_PORT)
      DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
    !else
      DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
    !endif

    Base Debug LibSerial Port를 살펴보겠습니다.inf의 구현:
    BOOLEAN
    EFIAPI
    DebugPrintEnabled (
      VOID
      )
    {
      return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0);
    }

    PcdDebugPropertyMask라는 PCD 변수의 값을 판단하는 것을 볼 수 있으며, 이것은OvmfPkgX64에 정의되어 있습니다.dsc:
    !ifdef $(SOURCE_DEBUG_ENABLE)
      gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
    !else
      gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
    !endif

    또 다른 매크로 DEBUGPROPERTY_DEBUG_PRINT_ENABLED는 다음과 같이 정의됩니다.
    //
    // Declare bits for PcdDebugPropertyMask
    //
    #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
    

    그래서 OvmfPkgX64에 대해 확인할 수 있습니다.dsc, 함수 DebugPrintEnabled()가 TRUE를 반환합니다.
    3. 그 다음에 주목해야 할 것은DEBUG 매크로:
    /**
      Internal worker macro that calls DebugPrint().
    
      This macro calls DebugPrint() passing in the debug error level, a format
      string, and a variable argument list.
      __VA_ARGS__ is not supported by EBC compiler, Microsoft Visual Studio .NET 2003
      and Microsoft Windows Server 2003 Driver Development Kit (Microsoft WINDDK) version 3790.1830.
    
      @param  Expression  Expression containing an error level, a format string,
                          and a variable argument list based on the format string.
    
    **/
    
    #if !defined(MDE_CPU_EBC) && (!defined (_MSC_VER) || _MSC_VER > 1400)
      #define _DEBUG_PRINT(PrintLevel, ...)              \
        do {                                             \
          if (DebugPrintLevelEnabled (PrintLevel)) {     \
            DebugPrint (PrintLevel, ##__VA_ARGS__);      \
          }                                              \
        } while (FALSE)
      #define _DEBUG(Expression)   _DEBUG_PRINT Expression
    #else
    #define _DEBUG(Expression)   DebugPrint Expression
    #endif

    여기에는 또 몇 가지 판단 조건이 관련되어 있다.
    우선 컴파일러의 지원 상황입니다. 이것은 주석에 설명되어 있습니다.
    또 하나는 DebugPrintLevelEnabled () 함수입니다. 이 함수에는 PrintLevel이라는 매개 변수가 있습니다. 이것은 DEBUG 함수의 첫 번째 매개 변수입니다.
    이 함수도 DebugLib 라이브러리에 정의되어 있으며, 우리도BaseDebugLibSerialPort를 사용합니다.inf의 구현:
    /**
      Returns TRUE if any one of the bit is set both in ErrorLevel and PcdFixedDebugPrintErrorLevel.
    
      This function compares the bit mask of ErrorLevel and PcdFixedDebugPrintErrorLevel.
    
      @retval  TRUE    Current ErrorLevel is supported.
      @retval  FALSE   Current ErrorLevel is not supported.
    
    **/
    BOOLEAN
    EFIAPI
    DebugPrintLevelEnabled (
      IN  CONST UINTN        ErrorLevel
      )
    {
      return (BOOLEAN) ((ErrorLevel & PcdGet32(PcdFixedDebugPrintErrorLevel)) != 0);
    }

    여기에는 MdePkg에 정의된 PCD 변수도 포함됩니다.dec 파일:
      ## This flag is used to control build time optimization based on debug print level.
      #  Its default value is 0xFFFFFFFF to expose all debug print level.
      #  BIT0  - Initialization message.
    # BIT1 - Warning message.
    # BIT2 - Load Event message.
    # BIT3 - File System message.
    # BIT4 - Allocate or Free Pool message.
    # BIT5 - Allocate or Free Page message.
    # BIT6 - Information message.
    # BIT7 - Dispatcher message.
    # BIT8 - Variable message.
    # BIT10 - Boot Manager message.
    # BIT12 - BlockIo Driver message.
    # BIT14 - Network Driver message.
    # BIT16 - UNDI Driver message.
    # BIT17 - LoadFile message.
    # BIT19 - Event message.
    # BIT20 - Global Coherency Database changes message.
    # BIT21 - Memory range cachability changes message.
    # BIT22 - Detailed debug message.
    # BIT31 - Error message.
    # @Prompt Fixed Debug Message Print Level. gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel|0xFFFFFFFF|UINT32|0x30001016

    그것의 값은 전체 FF이기 때문에 이 함수는 반드시 TRUE로 되돌아옵니다. DEBUG 매크로의 첫 번째 인자가 여기에 쓸모가 없기 때문입니다.
    4.1. 그 다음에 진정한 함수인 Debug Print () 가 언급되었는데, Debug Lib에 정의되었는지,Base Debug LibSerial Port에 정의되었는지.inf의 예:
    VOID
    EFIAPI
    DebugPrint (
      IN  UINTN        ErrorLevel,
      IN  CONST CHAR8  *Format,
      ...
      )
    {
      CHAR8    Buffer[MAX_DEBUG_MESSAGE_LENGTH];
      VA_LIST  Marker;
    
      //
      // If Format is NULL, then ASSERT().
      //
      ASSERT (Format != NULL);
    
      //
      // Check driver debug mask value and global mask
      //
      if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {
        return;
      }
    
      //
      // Convert the DEBUG() message to an ASCII String
      //
      VA_START (Marker, Format);
      AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
      VA_END (Marker);
    
      //
      // Send the print string to a Serial Port 
      //
      SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
    }

    함수도 비교적 간단하다. 몇 가지 설명이 있다.
    1) 버퍼는 크기가 있는 그룹으로 DEBUG가 출력할 수 있는 정보는 크기 제한이 있음을 나타낸다.
    2)GetDebugPrintErrorLevel() 함수는 PCD 변수를 가져오고 DEBUG의 첫 번째 인자와 비교하여 출력이 필요한지 확인합니다.
    여기에 사용된 PCD 변수는 PCdDebugPrintErrorLevel이며 값은 dsc 파일에 정의되어 있습니다.
      # DEBUG_INIT      0x00000001  // Initialization
      # DEBUG_WARN      0x00000002  // Warnings
      # DEBUG_LOAD      0x00000004  // Load events
      # DEBUG_FS        0x00000008  // EFI File system
      # DEBUG_POOL      0x00000010  // Alloc & Free (pool)
      # DEBUG_PAGE      0x00000020  // Alloc & Free (page)
      # DEBUG_INFO      0x00000040  // Informational debug messages
      # DEBUG_DISPATCH  0x00000080  // PEI/DXE/SMM Dispatchers
      # DEBUG_VARIABLE  0x00000100  // Variable
      # DEBUG_BM        0x00000400  // Boot Manager
      # DEBUG_BLKIO     0x00001000  // BlkIo Driver
      # DEBUG_NET       0x00004000  // SNP Driver
      # DEBUG_UNDI      0x00010000  // UNDI Driver
      # DEBUG_LOADFILE  0x00020000  // LoadFile
      # DEBUG_EVENT     0x00080000  // Event messages
      # DEBUG_GCD       0x00100000  // Global Coherency Database changes
      # DEBUG_CACHE     0x00200000  // Memory range cachability changes
      # DEBUG_VERBOSE   0x00400000  // Detailed debug messages that may
      #                             // significantly impact boot performance
      # DEBUG_ERROR     0x80000000  // Error
      # jw_debug, change 0x8000004F to 0x80000040
      gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000040

    5.1. 그 다음은 SerialPortWrite () 함수로 특정한 매체에 출력된 것이다.
    4.2. BaseDebugLibSerialPort 말고는ff라는 실현 방식 외에 (OVMF는 이런 방식을 사용했다) 더욱 보편적인 실현이 있다. 그것이 바로 PeiDxe Debug Lib Report Status Code이다.inf의 실현 방식은 다음과 같다.
      //
      // Send the DebugInfo record
      //
      REPORT_STATUS_CODE_EX (
        EFI_DEBUG_CODE,
        (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_DC_UNSPECIFIED),
        0,
        NULL,
        &gEfiStatusCodeDataTypeDebugGuid,
        DebugInfo,
        TotalSize
        );

    여기에 또 하나의 매크로 리포트를 사용했습니다STATUS_CODE_EX의 구현은 다음과 같습니다.
    #define REPORT_STATUS_CODE_EX(Type,Value,Instance,CallerId,ExtendedDataGuid,ExtendedData,ExtendedDataSize)  \
      (ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE)             ?  \
      ReportStatusCodeEx(Type,Value,Instance,CallerId,ExtendedDataGuid,ExtendedData,ExtendedDataSize)        :  \
      (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE)                   ?  \
      ReportStatusCodeEx(Type,Value,Instance,CallerId,ExtendedDataGuid,ExtendedData,ExtendedDataSize)        :  \
      (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE)                   ?  \
      ReportStatusCodeEx(Type,Value,Instance,CallerId,ExtendedDataGuid,ExtendedData,ExtendedDataSize)        :  \
      EFI_UNSUPPORTED

    xxxEnabled () 와 type 매개 변수에 따라 함수 ReportStatusCodeEx () 실행 여부를 결정합니다.
    여기서 Enabled는 dsc 파일의 PCD 변수에 따라 지정됩니다. ReportDebugCodeEnabled()의 경우
    /**
      Returns TRUE if status codes of type EFI_DEBUG_CODE are enabled
    
      This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED
      bit of PcdReportStatusCodeProperyMask is set.  Otherwise FALSE is returned.
    
      @retval  TRUE   The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of
                      PcdReportStatusCodeProperyMask is set.
      @retval  FALSE  The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of
                      PcdReportStatusCodeProperyMask is clear.
    
    **/
    BOOLEAN
    EFIAPI
    ReportDebugCodeEnabled (
      VOID
      )
    {
      return (BOOLEAN) ((PcdGet8 (PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED) != 0);
    }

    PCD 변수는 PcdReportStatusCodePropertyMask를 가리키며 그 값은
    //
    // Declare bits for PcdReportStatusCodePropertyMask
    //
    #define REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED          0x00000001
    #define REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED             0x00000002
    #define REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED             0x00000004

    여기 있는 3개의 값이 딱 REPORTSTATUS_CODE_EX宏 안에 있는 것들은 일일이 대응한다.
    REPORT 정보STATUS_CODE_EX의 첫 번째 매개변수 type 에는
    ///
    /// Definition of code types. All other values masked by
    /// EFI_STATUS_CODE_TYPE_MASK are reserved for use by
    /// this specification.
    ///
    ///@{
    #define EFI_PROGRESS_CODE             0x00000001
    #define EFI_ERROR_CODE                0x00000002
    #define EFI_DEBUG_CODE                0x00000003
    ///@}

    Dell DEBUG 매크로에 EFI 사용DEBUG_CODE 유형입니다.
    사실 REPORTSTATUS_CODE_EX 매크로는 단독으로 꺼내서 사용할 수 있으며, 예를 들어 BdsEntry와 같은 다른 type 유형을 사용할 수 있다.c 에는 다음과 같은 내용이 있습니다.
          REPORT_STATUS_CODE_EX (
            EFI_ERROR_CODE,
            PcdGet32 (PcdErrorCodeSetVariable),
            0,
            NULL,
            &gEdkiiStatusCodeDataTypeVariableGuid,
            SetVariableStatus,
            sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize
            );

    5.2. 그 다음은 함수 ReportStatus CodeEx () 와 관련이 있습니다.
    그것의 실현은 매우 많은데 PEI 단계, DXE 단계, SMM 모듈, RUNTIME 모듈 등은 모두 서로 다른 실현을 가지고 있다.
    다음은 DXE 단계를 예로 들면 Mde Module Pkg/Library/Dxe Report Status CodeLib/Dxe Report Status CodeLib에 있습니다.inf.
    그것의 실현은 결코 복잡하지 않지만, 그 중에서 우선순위의 변화가 있다는 것을 주의해야 한다. 이것은 실제 응용에서 일부 문제를 초래할 수 있다.
    ReportStatus CodeEx () 함수는 인터넷 ReportStatus Code () 함수를 호출했고, 후자는 gEfiStatus CodeRuntime Protocol Guid에 대응하는 Protocol을 통해 출력했다.
    6. gEfiStatus CodeRuntime Protocol Guid의 경우 Intel Framework Module Pkg/Universal/Status Code/Runtime Dxe/Status CodeRuntime Dxe.ff에 설치된 (Coreboot에 대해 말하자면) 이 Protocol은 하나의 함수만 포함합니다: ReportDispatcher. 인터넷 ReportStatusCode () 함수에서 이 함수를 호출했습니다.
    7. ReportDispatcher() 함수에서 주목해야 할 주요 코드는 다음과 같습니다.
      if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
        SerialStatusCodeReportWorker (
          CodeType,
          Value,
          Instance,
          CallerId,
          Data
          );
      }
      if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
        RtMemoryStatusCodeReportWorker (
          CodeType,
          Value,
          Instance
          );
      }
      if (FeaturePcdGet (PcdStatusCodeUseDataHub)) {
        DataHubStatusCodeReportWorker (
          CodeType,
          Value,
          Instance,
          CallerId,
          Data
          );
      }
      if (FeaturePcdGet (PcdStatusCodeUseOEM)) {
        //
        // Call OEM hook status code library API to report status code to OEM device
        //
        OemHookStatusCodeReport (
          CodeType,
          Value,
          Instance,
          CallerId,
          Data
          );
      }
    

    서로 다른 PCD 변수에 따라 서로 다른 인쇄 출력을 선택할 수 있고 심지어 사용자 정의 방식도 선택할 수 있다.
    Serial Status CodeReportWorker () 의 경우, 마지막까지 Serial PortWrite () 를 호출했는데, 이것은 OVMF의 실현과 대응한다.
    OVMF 버전과 달리 여기에는 더 많은 확장이 가능합니다. 
    지금까지 DEBUG의 성취였습니다.
    또한 DEBUG와 동일한 수준의 디버그 코드인 ASSERT를 추가하면 다음과 같은 코드가 적용됩니다.
    VOID
    EFIAPI
    DebugAssert (
      IN CONST CHAR8  *FileName,
      IN UINTN        LineNumber,
      IN CONST CHAR8  *Description
      )

    ASSERT를 사용할 때는 ASSERT 이후 코드가 CPU Dead Loop에 들어갈 수 있을 때 코드가 계속 실행되지 않도록 주의해야 한다.
    일반적으로 발행판의 UEFI에서는 이런 상황을 발생시키지 않는다. 이 사용은 DSC(또는 DEC)의 PCD를 설정해야 한다. PCdDebugPropertyMask는 서로 다른 값을 설정할 수 있다. 각 BIT는 다음과 같은 의미를 가진다.
    //
    // Declare bits for PcdDebugPropertyMask
    //
    #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

    DEBUG를 설정하면PROPERTY_ASSERT_DEADLOOP_ENABLED가 Dead Loop으로 이동합니다.
      //
      // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings
      //
      if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {
        CpuBreakpoint ();
      } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {
        CpuDeadLoop ();
      }

    ASSERT 사용에 대해서는 언급하지 않았습니다. 예를 들면 다음과 같습니다.
    ASSERT (FileHandle != NULL);

    특히 여기()의 조건은 우리가 원하는 것이기 때문에 ASSERT(FALSE)야말로 진정한 잘못된 상황이다.
     
    사실 ASSERT도 있어요. ASSERT.EFI_ERROR (Status);
    즉, Status가 잘못된 반환 값이면 ASSERT입니다.

    좋은 웹페이지 즐겨찾기