之前的很多实验都有一个奇怪的显现,开出了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