最近在查看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来调试。
好的,谢谢,有机会我试试