学习了一下如何获得 Shell 下当前的显示信息。通过 GraphicsOutputProtocol 来完成这个功能。这个 Protocol 在【参考1】 中有描述。
头定义在 \MdePkg\Include\Protocol\GraphicsOutput.h
typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL EFI_GRAPHICS_OUTPUT_PROTOCOL; /// /// Provides a basic abstraction to set video modes and copy pixels to and from /// the graphics controller's frame buffer. The linear address of the hardware /// frame buffer is also exposed so software can write directly to the video hardware. /// struct _EFI_GRAPHICS_OUTPUT_PROTOCOL { EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode; EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode; EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt; /// /// Pointer to EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE data. /// EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; };
从名称上来看,这个 Protocol 能够实现的功能是:查询/设置当前显示模式,将屏幕内容和内存互copy等。
这次实验的是查询功能。
查询的结果输出是 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE 结构体
typedef struct { /// /// The number of modes supported by QueryMode() and SetMode(). /// UINT32 MaxMode; /// /// Current Mode of the graphics device. Valid mode numbers are 0 to MaxMode -1. /// UINT32 Mode; /// /// Pointer to read-only EFI_GRAPHICS_OUTPUT_MODE_INFORMATION data. /// EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; /// /// Size of Info structure in bytes. /// UINTN SizeOfInfo; /// /// Base address of graphics linear frame buffer. /// Offset zero in FrameBufferBase represents the upper left pixel of the display. /// EFI_PHYSICAL_ADDRESS FrameBufferBase; /// /// Amount of frame buffer needed to support the active mode as defined by /// PixelsPerScanLine xVerticalResolution x PixelElementSize. /// UINTN FrameBufferSize; } EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE;
可以看到能够获得当前显示模式,屏幕分辨率和格式信息等。根据上面的信息,编写程序如下
#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; int EFIAPI main ( IN int Argc, IN char **Argv ) { EFI_STATUS Status; Status = gBS->LocateProtocol(&GraphicsOutputProtocolGuid, NULL, (VOID **) &GraphicsOutput); if (EFI_ERROR(Status)) { GraphicsOutput = NULL; Print(L"Loading Graphics_Output_Protocol error!\n"); return EFI_SUCCESS; } Print(L"Max mode =[%d] \n",GraphicsOutput->Mode->MaxMode); Print(L"Current mode =[%d] \n",GraphicsOutput->Mode->Mode); Print(L"Version =[%d] \n",GraphicsOutput->Mode->Info->Version); Print(L"Screen Width =[%d] \n",GraphicsOutput->Mode->Info->HorizontalResolution); Print(L"Screen height=[%d] \n",GraphicsOutput->Mode->Info->VerticalResolution); Print(L"Format =[%d] \n",GraphicsOutput->Mode->Info->PixelFormat); Print(L"Num of pixel =[%d] \n",GraphicsOutput->Mode->Info->PixelsPerScanLine); return EFI_SUCCESS; }
运行结果(还是NT32模拟器中)
完整代码下载:
参考:
1.UEFI Spec 2.4 P488 11.9 Graphics Output Protocol
請問這個可以抓取到螢幕目前的顯示字串嗎??
可以用来截图,但是无法抓取显示的字符串因为他的参数已经是图形格式了。