最近在查看EDKII代码的时候忽然有一个奇怪的想法:在运行模拟器的时候(Build Run),我们可以在编译窗口看到很多输出的Debug 信息,那么我们是否可以在自己编写的Application中输出这样的信息?
最直接的想法是在 Application中调用 gWinNt ,但是如果要用这个东西,需要定义很多文件头,最麻烦的是这些头文件最后都要使用 Windows.h ,编译的时候总是无法通过。另外的方法是,在 Application 中调用诸如 WinNtThunkDxe 或者 WinNtSerialIoDxe 这样的Protocol,但是在编译使同样会遇到有上面的问题。我尝试了很多次都没有成功,最后只好放弃。
换一种思路,我们可以在NT32Pkg中留下可供调用的函数,然后在 Application 中Call这个函数。
最简单的功能就是用于系统重启的 gST->Reset 。经过查找,模拟器中实现这个功能的代码在 \Nt32Pkg\ResetRuntimeDxe\reset.c 。头定义如下
VOID EFIAPI WinNtResetSystem ( IN EFI_RESET_TYPE ResetType, IN EFI_STATUS ResetStatus, IN UINTN DataSize, IN VOID *ResetData OPTIONAL ) /*++ Routine Description: TODO: Add function description Arguments: ResetType - TODO: add argument description ResetStatus - TODO: add argument description DataSize - TODO: add argument description ResetData - TODO: add argument description Returns: EFI_SUCCESS - TODO: Add description for return value --*/
实现功能的代码只有一行 gWinNt->ExitProcess (0)。只要把这些语句注释掉,替换为我们的输出代码即可。参考 \Nt32Pkg\Library\PeiNt32OemHookStatusCodeLib\Nt32OemHookStatusCodeLib.c
,对编译窗口输出的语句如下:
//
// Callout to standard output.
//
mWinNt->WriteFile (
mStdOut,
Buffer,
(DWORD)CharCount,
(LPDWORD)&CharCount,
NULL
);
搬过来,写成下面的形式:
VOID
EFIAPI
WinNtResetSystem (
IN EFI_RESET_TYPE ResetType,
IN EFI_STATUS ResetStatus,
IN UINTN DataSize,
IN VOID *ResetData OPTIONAL
)
/*++
Routine Description:
TODO: Add function description
Arguments:
ResetType - TODO: add argument description
ResetStatus - TODO: add argument description
DataSize - TODO: add argument description
ResetData - TODO: add argument description
Returns:
EFI_SUCCESS - TODO: Add description for return value
--*/
{
CHAR8 *R="www.lab-z.com \n\r";
UINTN CharCount=AsciiStrLen(R);
//
// Cache of standard output handle .
//
HANDLE mStdOut;
//
// Cache standard output handle.
//
mStdOut = gWinNt->GetStdHandle (STD_OUTPUT_HANDLE);
//
// Callout to standard output.
//
gWinNt->WriteFile (
mStdOut,
R,
(DWORD)CharCount,
(LPDWORD)&CharCount,
NULL
);
//
// BUGBUG Need to kill all console windows later
//
//
// Discard ResetType, always return 0 as exit code
//
//gWinNt->ExitProcess (0);
//
// Should never go here
//
//ASSERT (FALSE);
}
特别注意:字符串是 Ascii 定义的,末尾必须是 \r\n ,否则不会立即显示。
最后运行结果,只要在模拟器中输入 reset 即可看到字符串,正常的动作应该是退出模拟器。
因为我修改掉了退出的方法,每次需要在编译窗口用 ctrl+c来结束模拟器了。
这里只是一个Demo,最好还是重新在EDKII代码中定义一个用来直接输出的接口。


我有一个绕过找不到windows.h问题的方法供参考。不知啥原理,但基本每次都成功。
先把干净的nt32模拟器编译好,编译窗口不要关,然后在dsc加上要添加的application的inf和!include StdLib/StdLib.inc。再编译一次,不会遇到windows.h的问题。
要输出DEBUG MESSAGE的话,只要用DEBUG((…))宏就可以了。也可以用VS来调试。
好的,谢谢,有机会我试试