之前的很多实验都有一个奇怪的显现,开出了2个模拟窗口,只有一个上面有显示。琢磨了一下,猜测是因为只打开了一个设备上面的Protocol,于是用命令查看了一下有Graphics 的 Protocol,发现有三个(模拟环境下)
之前我们的代码都是用 gBS->LocateProtocol 打开的,这个函数的意思是“是从内核中找出指定Protocol的第一个实例。”【参考1】
gBS->LocateProtocol(&GraphicsOutputProtocolGuid, NULL, (VOID **) &GraphicsOutput);
我们遇到问题就是【参考1】中提到的:“UEFI内核中某个Protocol的实例可能不止一个,例如每个硬盘及每个分区都有一个EFI_DISK_IO_PROTOCOL实例。LocateProtocol顺序搜索HANDLE链表,返回找到的第一个该Protocol的实例。我们可以用BootServices提供的其它函数处理HANDLE和Protocol。”
编写代码如下,枚举系统中的所有实例,然后逐个打开并且调用:
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <time.h>
#include <Protocol/EfiShell.h>
#include <Library/ShellLib.h>
#include <Protocol/SimpleFileSystem.h>
#include <Protocol/BlockIo.h>
#include <Library/DevicePathLib.h>
#include <Library/HandleParsingLib.h>
#include <Library/SortLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseMemoryLib.h>
#include <Protocol/LoadedImage.h>
extern EFI_BOOT_SERVICES *gBS;
extern EFI_SYSTEM_TABLE *gST;
extern EFI_RUNTIME_SERVICES *gRT;
extern EFI_SHELL_ENVIRONMENT2 *mEfiShellEnvironment2;
extern EFI_HANDLE gImageHandle;
static EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
static EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput = NULL;
//Copied from C\MdePkg\Include\Protocol\UgaDraw.h
typedef struct {
UINT8 Blue;
UINT8 Green;
UINT8 Red;
UINT8 Reserved;
} EFI_UGA_PIXEL;
int
EFIAPI
main (
IN int Argc,
IN char **Argv
)
{
EFI_STATUS Status;
UINTN i;
UINTN HandleIndex;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL FillColor;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
//
// Search for the shell protocol
//
Status = gBS->LocateHandleBuffer(
ByProtocol,
&GraphicsOutputProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
Print(L"[%d] \r\n",HandleCount);
for (HandleIndex=0; HandleIndex<HandleCount;HandleIndex++)
{
Status = gBS -> HandleProtocol (
HandleBuffer[HandleIndex],
&gEfiGraphicsOutputProtocolGuid,
(void **)&GraphicsOutput);
if (!(EFI_ERROR(Status))) {
for (i=0;i<100;i++) {
FillColor.Blue=rand() % 256;
FillColor.Red=rand() % 256;
FillColor.Green=rand() % 256;
GraphicsOutput->Blt(GraphicsOutput, &FillColor, EfiBltVideoFill,
0,
0 ,
rand() % (GraphicsOutput->Mode->Info->HorizontalResolution-100),
rand() % (GraphicsOutput->Mode->Info->VerticalResolution-100),
100, 100, 0);
gBS->Stall(50000);
} // For i
}
else {
Print(L"Error @[%d] \r\n",HandleCount);
}
} // For HandleIndex
return EFI_SUCCESS;
}
运行结果:
可以看到现在两个窗口都会有显示。
完整代码下载:
参考:
1.http://www.cppblog.com/djxzh/archive/2012/03/06/167106.html UEFI 实战(4) protocol

