# 41. DEBUG 출력문 내부 구조와 DEBUG 문 제어를 위한 PCD 분석, 그리고 OVMF 부트 로그 가져오기

이번 장에서는 EDKII 코드 베이스에 존재하는 `DEBUG` 매크로와 관련된 정보를 학습한다. 다음은 그 예시이다.

```
DEBUG ((EFI_D_ERROR, "Hello Debug! Check this variable: %d\n", MyVar));
```

일반적인 출력 형식과 유사하지만 다른 기능이 존재한다.

* 로그 레벨을 이용하여 로그 메세지를 분류할 수 있다. PCD를 통한 구성으로 type별 디버그 메세지를 쉽게 켜고 끌 수 있다.
* 서로 다른 UEFI 단계 및 모듈은 서로 다른 `DEBUG` 구현을 가지기 때문에 여러 `DEBUG` 기능 구현이 존재한다.

사전에 정의된 로그 메세지의 범주는 아래와 같다.\
<https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/DebugLib.h>

```
#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  // Network Io 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
```

DEBUG 매크로 자체 또한 `DebugLib`에 정의되어 있다.\
<https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/DebugLib.h>

모든 전처리 과정을 분할하여 살펴보면 일반적으로 다음과 같다.

```
if (DebugPrintEnabled ()) {
  if (DebugPrintLevelEnabled (PrintLevel)) {
    DebugPrint (PrintLevel, ##__VA_ARGS__);
  }
}
```

DEBUG 매크로 인터페이스는 `DebugLib` 헤더에 정의되어 있지만 실제 구현을 위해서는 사용되는 특정 라이브러리의 인터페이스를 살펴봐야 한다[https://github.com/tianocore/edk2/blob/master/OvmfPkg/OvmfPkgX64.dsc ](https://github.com/tianocore/edk2/blob/master/OvmfPkg/OvmfPkgX64.dsc)를 살펴보자

* `DebugLib` 은 각 UEFI 단계에서 각기 다른 구현을 가지고 있다.
* `DebugLib`은 `DEBUG_ON_SERAIL_PORT` 정의에 따라 다른 구현이 있다.

```
[LibraryClasses.common.SEC]
!ifdef $(DEBUG_ON_SERIAL_PORT)
  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
!else
  DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
!endif
```

```
[LibraryClasses.common.PEI_CORE]
# [LibraryClasses.common.PEIM]
# [LibraryClasses.common.DXE_CORE]
# [LibraryClasses.common.DXE_RUNTIME_DRIVER]
# [LibraryClasses.common.UEFI_DRIVER]
# [LibraryClasses.common.DXE_DRIVER]
# [LibraryClasses.common.UEFI_APPLICATION]
# [LibraryClasses.common.DXE_SMM_DRIVER]
# [LibraryClasses.common.SMM_CORE]
!ifdef $(DEBUG_ON_SERIAL_PORT)
  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
!else
  DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
!endif
```

기본적으로 `DEBUG_ON_SERIAL_PORT`가 정의되어 있지 않은 경우 `PlatformDebugLibIoPort` 가 기본 라이브러리이다.\
<https://github.com/tianocore/edk2/tree/master/OvmfPkg/Library/PlatformDebugLibIoPort>

```
DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
```

`DEBUG` 매크로는 다음과 같이 번역된다.

```
if (DebugPrintEnabled ()) {
  if (DebugPrintLevelEnabled (PrintLevel)) {
    DebugPrint (PrintLevel, ##__VA_ARGS__);
  }
}
```

아래를 통해`DebugPrintEnabled`,`DebugPrintLevelEnabled` ,`DebugPrint` 정보를 살펴보자. <https://github.com/tianocore/edk2/blob/master/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c>

#### DebugPrintEnabled

`DEBUG` 매크로는 먼저 `DebugPrintEnabled` 결과를 확인한다. 이 함수는 PCD의 `PcdDebugPropertyMask`에 `DEBUG_PROPERTY_DEBUG_PRINT_ENABLED`가 설정되어 있는지 확인한다.

```
BOOLEAN
EFIAPI
DebugPrintEnabled (
  VOID
  )
{
  return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0);
}
```

#### DebugPrintLevelEnabled

그리고 `DebugPrintLevelEnabled` 함수는 전달된 `ErrorLevel` 이 PCD의 `PcdFixedDebugPrintErrorLevel` 에 있는지 확인한다.

```
BOOLEAN
EFIAPI
DebugPrintLevelEnabled (
  IN  CONST UINTN        ErrorLevel
  )
{
  return (BOOLEAN) ((ErrorLevel & PcdGet32(PcdFixedDebugPrintErrorLevel)) != 0);
}
```

**DebugPrint**

그런 다음 `DebugPrint` 함수가 실행되며 단순히 제어를 `DebugVPrint`로 전달한다.

```
VOID
EFIAPI
DebugPrint (
  IN  UINTN        ErrorLevel,
  IN  CONST CHAR8  *Format,
  ...
  )
{
  VA_LIST         Marker;

  VA_START (Marker, Format);
  DebugVPrint (ErrorLevel, Format, Marker);
  VA_END (Marker);
}
```

그리고 `DebugVPrint` 는 `DebugPrintMarker`로 제어를 전달한다.

```
VOID
EFIAPI
DebugVPrint (
  IN  UINTN         ErrorLevel,
  IN  CONST CHAR8   *Format,
  IN  VA_LIST       VaListMarker
  )
{
  DebugPrintMarker (ErrorLevel, Format, VaListMarker, NULL);
}
```

`DebugPrintMarker` 는 주요 디버그 기능으로, 전달된 `ErrorLevel` 이 `GetDebugPrintErrorLevel()` 출력에 있는지 확인한다. 최종적으로는 PCD의 `PcdDebugIoPort` 에 의해 정의된 입출력 포트에 디버그 문자열 쓰기를 수행한다.

```
VOID
DebugPrintMarker (
  IN  UINTN         ErrorLevel,
  IN  CONST CHAR8   *Format,
  IN  VA_LIST       VaListMarker,
  IN  BASE_LIST     BaseListMarker
  )
{
  CHAR8    Buffer[MAX_DEBUG_MESSAGE_LENGTH];
  UINTN    Length;

  //
  // If Format is NULL, then ASSERT().
  //
  ASSERT (Format != NULL);

  //
  // Check if the global mask disables this message or the device is inactive
  //
  if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0 ||
      !PlatformDebugLibIoPortFound ()) {
    return;
  }

  //
  // Convert the DEBUG() message to an ASCII String
  //
  if (BaseListMarker == NULL) {
    Length = AsciiVSPrint (Buffer, sizeof (Buffer), Format, VaListMarker);
  } else {
    Length = AsciiBSPrint (Buffer, sizeof (Buffer), Format, BaseListMarker);
  }

  //
  // Send the print string to the debug I/O port
  //
  IoWriteFifo8 (PcdGet16 (PcdDebugIoPort), Length, Buffer);
}
```

`GetDebugPrintErrorLevel()` 는 `DebugPrintErrorLevelLib` 라이브러리에 정의된 함수로 `OvmfPkgX64.dsc` 에서도 그 구현을 확인할 수 있다.

```
[LibraryClasses]
  ...
  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
```

소스를 보면 단순히 다른 PCD를 확인하는 것을 볼 수 있다.\
<https://github.com/tianocore/edk2/blob/master/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.c>

```
UINT32
EFIAPI
GetDebugPrintErrorLevel (
  VOID
  )
{
  //
  // Retrieve the current debug print error level mask from PcdDebugPrintErrorLevel.
  //
  return PcdGet32 (PcdDebugPrintErrorLevel);
}
```

### 요약

`DEBUG (( ErrorLevel, String, ... ))` 와 같은 형태의 코드를 정리하자면 다음과 같다.

1. `PcdDebugPropertyMask` 에 `DEBUG_PROPERTY_DEBUG_PRINT_ENABLED`가 있는지 확인한다.
2. 전달된 `ErrorLevel` 이 `PcdFixedDebugPrintErrorLevel` 에 설정되어 있는지 확인한다.
3. 전달된 `ErrorLevel` 이 `PcdDebugPrintErrorLevel` 에 설정되어 있는지 확인한다.
4. 지정된 형식 문자열을 `PcdDebugIoPort` 에 정의된 입출력 포트에 작성한다.

## Check if `PcdDebugPropertyMask` has `DEBUG_PROPERTY_DEBUG_PRINT_ENABLED`

OVMF의 DSC 파일에서는 PCD `PcdDebugPropertyMask` 를 다음과 같이 정의한다.\
[https://github.com/tianocore/edk2/blob/master/OvmfPkg/OvmfPkgX64.dsc](https://github.com/tianocore/edk2/blob/master/OvmfPkg/OvmfPkgX64.dsc:)

```
[PcdsFixedAtBuild]
!if $(SOURCE_DEBUG_ENABLE) == TRUE
  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
!else
  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
!endif
```

그리고 이 PCD는 Shell용으로 재정의 된다.

```
[Components]
  ShellPkg/Application/Shell/Shell.inf {
    ...
    <PcdsFixedAtBuild>
    ...
    gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF
  }
```

이 PCD에 대한 비트 정의는 다음에서 확인할 수 있다.\
<https://github.com/tianocore/edk2/blob/master/MdePkg/MdePkg.dec>

```
## The mask is used to control DebugLib behavior.<BR><BR>
#  BIT0 - Enable Debug Assert.<BR>
#  BIT1 - Enable Debug Print.<BR>
#  BIT2 - Enable Debug Code.<BR>
#  BIT3 - Enable Clear Memory.<BR>
#  BIT4 - Enable BreakPoint as ASSERT.<BR>
#  BIT5 - Enable DeadLoop as ASSERT.<BR>
# @Prompt Debug Property.
# @Expression  0x80000002 | (gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask & 0xC0) == 0
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0|UINT8|0x00000005
```

`SOURCE_DEBUG_ENABLE` 의 설정 값

* TRUE(17h): Debug Assert(1h)/Debug Print(2h)/Debug Code(4h)/BreakPoint(10h) 활성화
* FALSE(2Fh): Debug Assert(1h)/Debug Print(2h)/Debug Code(4h)/Clear Memory(8h)/DeadLoop(20h) 활성화

`DEBUG` 매크로에서 이 `PCD` 를 `DEBUG_PROPERTY_DEBUG_PRINT_ENABLED` 와 비교해보자.\
<https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/DebugLib.h>

```
//
// 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
```

보다시피 해당 검사는 `SOURCE_DEBUG_ENABLE` 와 관계없이 통과된다.

## Checks if passed `ErrorLevel` is set in `PcdFixedDebugPrintErrorLevel`

해당 PCD는 `MdePkg.dsc` 에 정의되었다.\
[https://github.com/tianocore/edk2/blob/master/MdePkg/MdePkg.dec](https://github.com/tianocore/edk2/blob/master/MdePkg/MdePkg.dec:)

```
[PcdsFixedAtBuild]
  gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel|0xFFFFFFFF|UINT32|0x30001016
```

이 PCD 정보는 OVMF의 DSC 파일에서 재정의 되지 않기 때문에 빌드에 포함되는 값이다. `0xFFFFFFFF` 는 디버그 메세지가 `EFI_D_*` 출력 레벨에 관계없이 이 검사를 통과함을 의미한다.

## Checks if passed `ErrorLevel` is set in `PcdDebugPrintErrorLevel`

해당 PCD는 `MdePkg.dec` 에 정의되었다.\
<https://github.com/tianocore/edk2/blob/master/MdePkg/MdePkg.dec>

```
[PcdsFixedAtBuild]
  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000|UINT32|0x00000006
```

기본적으로 `MdePkg.dec` 및 `MdePkg.dsc` 에서 `0x80000000` 으로 정의된다.\
[https://github.com/tianocore/edk2/blob/master/MdePkg/MdePkg.dsc](https://github.com/tianocore/edk2/blob/master/MdePkg/MdePkg.dsc:)

```
[PcdsFixedAtBuild]
  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000
```

`0x80000000` 이라는 값은 오류 메시지(`EFI_D_ERROR`) 만 출력함을 의미한다.

빌드하는 OVMF의 DSC 파일에서는 해당 PCD를 재정의하고 있다.

```
[PcdsFixedAtBuild]
  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
```

`0x8000004F` - `EFI_D_ERROR` | `EFI_D_INFO` | `EFI_D_FS` | `EFI_D_LOAD` | `EFI_D_WARN` | `EFI_D_INIT`

만약 DEBUG 가 활성화된다면 위 범주의 메세지가 출력된다.

## Writes formatted String to I/O port defined by `PcdDebugIoPort`

`PcdDebugIoPort` 에 대한 정의는 `OvmfPkg.dec` 에 존재한다.\
<https://github.com/tianocore/edk2/blob/master/OvmfPkg/OvmfPkg.dec>

```
[PcdsFixedAtBuild]
  gUefiOvmfPkgTokenSpaceGuid.PcdDebugIoPort|0x402|UINT16|4
```

해당 PCD는 `PlatformDebugLibIoPort` 의 디버그 메세지에 대한 대상 입출력 포트를 제어한다.

##

## DEBUG 테스트

디버그 메세지를 보기 위해서는 디버그 모드에서 OVMF를 다시 컴파일 해야 한다.

먼저 다음과 같이 DEBUG 모드로 빌드를 진행한다.

```
build --platform=OvmfPkg/OvmfPkgX64.dsc --arch=X64 --buildtarget=DEBUG --tagname=GCC5
```

결과에 대한 경로는`Build/OvmfX64/DEBUG_GCC5` 이다.

QEMU를 다음과 같은 옵션으로 실행한다.

```
qemu-system-x86_64 \
  -drive if=pflash,format=raw,readonly,file=Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd \
  -drive format=raw,file=fat:rw:~/UEFI_disk \
  -net none \
  -nographic \
  -global isa-debugcon.iobase=0x402 \
  -debugcon file:debug.log
```

이렇게 하면 OVMF의 모든 DEBUG 로그 메세지가 `debug.log` 파일에 포함되어 생성된다. 해당 파일은 매 실행마다 생성된다.

## 로그파일에서 GUID 치환하기

`debug.log` 파일을 확인해보면 다음과 같은 GUID 값을 확인할 수 있다.

```
$ head debug.log
SecCoreStartupWithStack(0xFFFCC000, 0x820000)
Register PPI Notify: DCD0BE23-9586-40F4-B643-06522CED4EDE
Install PPI: 8C8CE578-8A3D-4F1C-9935-896185C32DD3
Install PPI: 5473C07A-3DCB-4DCA-BD6F-1E9689E7349A
The 0th FV start address is 0x00000820000, size is 0x000E0000, handle is 0x820000
Register PPI Notify: 49EDB1C1-BF21-4761-BB12-EB0031AABB39
Register PPI Notify: EA7CA24B-DED5-4DAD-A389-BF827E8F9B38
Install PPI: B9E0ABFE-5979-4914-977F-6DEE78C278A6
Install PPI: DBE23AA9-A345-4B97-85B6-B226F1617389
DiscoverPeimsAndOrderWithApriori(): Found 0x7 PEI FFS files in the 0th FV
```

edk2 빌드 시스템이 GUID의 이름을 가진 파일을 만들기 때문에 이를 이용하면 GUID 값에 대응하는 텍스트로 대체시켜 가독성을 높일 수 있다.

```
$ head Build/OvmfX64/DEBUG_GCC5/FV/Guid.xref
8c1a6b71-0c4b-4497-aaad-07404edf142c PCDLesson
1BA0062E-C779-4582-8566-336AE8F78F09 ResetVector
df1ccef6-f301-4a63-9661-fc6030dcc880 SecMain
52C05B14-0B98-496c-BC3B-04B50211D680 PeiCore
9B3ADA4F-AE56-4c24-8DEA-F03B7558AE50 PcdPeim
A3610442-E69F-4DF3-82CA-2360C4031A23 ReportStatusCodeRouterPei
9D225237-FA01-464C-A949-BAABC02D31D0 StatusCodeHandlerPei
86D70125-BAA3-4296-A62F-602BEBBB9081 DxeIpl
222c386d-5abc-4fb4-b124-fbb82488acf4 PlatformPei
89E549B0-7CFE-449d-9BA3-10D8B2312D71 S3Resume2Pei
```

다음과 같은 파이썬 코드를 작성하자.

```
from shutil import copyfile

GUIDS_FILE_PATH = "Build/OvmfX64/DEBUG_GCC5/FV/Guid.xref"
EXTRA_GUIDS_FILE_PATH = "Guid_extra.xref"
LOG_IN_FILE_PATH = "debug.log"
LOG_OUT_FILE_PATH = "debug_parsed.log"

guids = {}

with open(GUIDS_FILE_PATH) as p:
    for line in p:
        l = line.split(" ")
        if len(l)==2:
            guids[l[0].upper()] = l[1][:-1]

if EXTRA_GUIDS_FILE_PATH:
    with open(EXTRA_GUIDS_FILE_PATH) as p:
        for line in p:
            l = line.split(" ")
            if len(l)==2:
                guids[l[0].upper()] = l[1][:-1]

copyfile(LOG_IN_FILE_PATH, LOG_OUT_FILE_PATH)

f = open(LOG_OUT_FILE_PATH, 'r')
filedata = f.read()
f.close()

for key,val in guids.items():
    filedata = filedata.replace(key, val)

f = open(LOG_OUT_FILE_PATH, 'w')
f.write(filedata)
f.close()
```

결과물은 `debug_parsed.log` 에 저장되며 추가적인GUID 값이 존재하는 경우 `EXTRA_GUIDS_FILE_PATH` 경로에 지정하여 추가할 수 있다.

```
$ python replace_guids.py
$ head debug_parsed.log
SecCoreStartupWithStack(0xFFFCC000, 0x820000)
Register PPI Notify: gEfiPeiSecurity2PpiGuid
Install PPI: gEfiFirmwareFileSystem2Guid
Install PPI: gEfiFirmwareFileSystem3Guid
The 0th FV start address is 0x00000820000, size is 0x000E0000, handle is 0x820000
Register PPI Notify: gEfiPeiFirmwareVolumeInfoPpiGuid
Register PPI Notify: gEfiPeiFirmwareVolumeInfo2PpiGuid
Install PPI: gEfiPeiLoadFilePpiGuid
Install PPI: gEfiTemporaryRamSupportPpiGuid
DiscoverPeimsAndOrderWithApriori(): Found 0x7 PEI FFS files in the 0th FV
```

추가적으로 해당 스크립트를 범용적으로 이용하기 위해서 아래와 같이 작성해볼 수 있다.

```
from argparse import ArgumentParser

parser = ArgumentParser(description="Convert GUIDs to text identifiers in UEFI firmware boot log")
parser.add_argument('-g', '--guids', help="Guid.xref file location", required=True)
parser.add_argument('-e', '--guids_extra', help="additional Guid.xref file location")
parser.add_argument('-i', '--log_input', help="input log file location", required=True)
parser.add_argument('-o', '--log_output', help="output log file location (by default input file is changed in place)")
args = parser.parse_args()

GUIDS_FILE_PATH = args.guids
EXTRA_GUIDS_FILE_PATH = args.guids_extra

LOG_IN_FILE_PATH = args.log_input
if args.log_output:
    LOG_OUT_FILE_PATH = args.log_output
else:
    LOG_OUT_FILE_PATH = args.log_input

...

if LOG_IN_FILE_PATH != LOG_OUT_FILE_PATH:
    copyfile(LOG_IN_FILE_PATH, LOG_OUT_FILE_PATH)

...
```

```
$ python replace_guids.py -g Build/OvmfX64/DEBUG_GCC5/FV/Guid.xref -e Guid_extra.xref -i debug.log -o debug_parsed.log
$ python replace_guids.py --help
usage: replace_guids.py [-h] -g GUIDS [-e GUIDS_EXTRA] -i LOG_INPUT [-o LOG_OUTPUT]

Convert GUIDs to text identifiers in UEFI firmware boot log

optional arguments:
  -h, --help            show this help message and exit
  -g GUIDS, --guids GUIDS
                        Guid.xref file location
  -e GUIDS_EXTRA, --guids_extra GUIDS_EXTRA
                        additional Guid.xref file location
  -i LOG_INPUT, --log_input LOG_INPUT
                        input log file location
  -o LOG_OUTPUT, --log_output LOG_OUTPUT
                        output log file location (by default input file is changed in place)
```

## DEBUG 메세지 출력길이 제한

DEBUg 문으로 출력할 수 있는 최대 문자열의 길이가 제한되어 있다.\
[https://github.com/tianocore/edk2/blob/master/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c](https://github.com/tianocore/edk2/blob/master/OvmfPkg/Library/PlatformDebugLibIoPort/DebugLib.c:)

```
#define MAX_DEBUG_MESSAGE_LENGTH  0x100
```

정의에 따라 0x100보다 긴 출력이 발생할 수 있으므로 해당 값을 변경하여 빌드함으로써 그 제한을 늘릴 수 있다.

```
build --platform=OvmfPkg/OvmfPkgX64.dsc --arch=X64 --buildtarget=DEBUG --tagname=GCC5
```

\\


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bob-mcd-team.gitbook.io/uefi/uefi-development/debug/41.debug.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
