Step to UEFI (57) ----- 只在一个有显示?

之前的很多实验都有一个奇怪的显现,开出了2个模拟窗口,只有一个上面有显示。琢磨了一下,猜测是因为只打开了一个设备上面的Protocol,于是用命令查看了一下有Graphics 的 Protocol,发现有三个(模拟环境下)

handle

之前我们的代码都是用 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;
  
}

 

运行结果:

gfxtest6

可以看到现在两个窗口都会有显示。

完整代码下载:

GFXTest6

参考:

1.http://www.cppblog.com/djxzh/archive/2012/03/06/167106.html UEFI 实战(4) protocol

发表评论

电子邮件地址不会被公开。 必填项已用*标注