그런 다음 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 에서도 그 구현을 확인할 수 있다.
이렇게 하면 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 값에 대응하는 텍스트로 대체시켜 가독성을 높일 수 있다.
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)