学习了一下如何获得 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
==========================================================
2025年3月17日 额外同一个功能类似的代码
#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Protocol/GraphicsOutput.h>
#include <Library/DebugLib.h>
INTN
EFIAPI
ShellAppMain (
IN UINTN Argc,
IN CHAR16 **Argv
)
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
UINTN Index;
UINT32 ModeIndex;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
UINTN SizeOfInfo;
// Locate the handles that support the Graphics Output Protocol
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiGraphicsOutputProtocolGuid, NULL, &HandleCount, &HandleBuffer);
if (EFI_ERROR(Status)) {
Print(L"Failed to locate handles for Graphics Output Protocol\n");
return Status;
}
// Iterate over all handles
for (Index = 0; Index < HandleCount; Index++) {
// Get the Graphics Output Protocol instance
Status = gBS->HandleProtocol(HandleBuffer[Index], &gEfiGraphicsOutputProtocolGuid, (VOID**)&GraphicsOutput);
if (EFI_ERROR(Status)) {
Print(L"Failed to handle protocol for handle %d\n", Index);
continue;
}
Print(L"Controler [%d]\n", Index);
// Iterate over each mode
for (ModeIndex = 0; ModeIndex < GraphicsOutput->Mode->MaxMode; ModeIndex++) {
// Get mode information
Status = GraphicsOutput->QueryMode(GraphicsOutput, ModeIndex, &SizeOfInfo, &Info);
if (EFI_ERROR(Status)) {
Print(L"Failed to query mode %d\n", ModeIndex);
continue;
}
// Output the resolution and pixel format
Print(L"Mode %d: Resolution: %ux%u, Pixels Per Scanline: %u\n",
ModeIndex,
Info->HorizontalResolution,
Info->VerticalResolution,
Info->PixelsPerScanLine);
// Free the mode information
gBS->FreePool(Info);
}
}
// Free the handle buffer
gBS->FreePool(HandleBuffer);
return EFI_SUCCESS;
}
## @file
# A simple, basic, EDK II native, "hello" application.
#
# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010006
BASE_NAME = gm
FILE_GUID = a912f198-2025-0317-b908-b757b806ec83
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 0.1
ENTRY_POINT = ShellCEntryLib
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
GetModeInfo.c
[Packages]
MdePkg/MdePkg.dec
ShellPkg/ShellPkg.dec
[LibraryClasses]
UefiLib
ShellCEntryLib

請問這個可以抓取到螢幕目前的顯示字串嗎??
可以用来截图,但是无法抓取显示的字符串因为他的参数已经是图形格式了。