Skip to content

Instantly share code, notes, and snippets.

@dakanji
Last active July 17, 2020 12:02
Show Gist options
  • Save dakanji/60f7acf2e1956bb93435777401b9d138 to your computer and use it in GitHub Desktop.
Save dakanji/60f7acf2e1956bb93435777401b9d138 to your computer and use it in GitHub Desktop.
Display TEXT and GRAPHIC screen mode information in UEFI Environment
//
// Copyright (c) 2015 Finnbarr P. Murphy. All rights reserved.
// blog.fpmurphy.com/2015/05/check-available-text-and-graphics-modes-from-uefi-shell.html
// Display TEXT and GRAPHIC screen mode information in UEFI Environment
// License: BSD License
//
// The following code should work with any of the UDK (UEFI Development Kit) releases:
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
#include <Library/ShellLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/PrintLib.h>
#include <Protocol/EfiShell.h>
#include <Protocol/LoadedImage.h>
#include <Protocol/SimpleFileSystem.h>
#include <Protocol/GraphicsOutput.h>
#include "ConsoleControl.h"
#include "UgaDraw.h"
static int
memcmp(const void *s1, const void *s2, UINTN n)
{
const unsigned char *c1 = s1, *c2 = s2;
int d = 0;
if (!s1 && !s2)
return 0;
if (s1 && !s2)
return 1;
if (!s1 && s2)
return -1;
while (n--) {
d = (int)*c1++ - (int)*c2++;
if (d)
break;
}
return d;
}
EFI_STATUS
PrintUGA(EFI_UGA_DRAW_PROTOCOL *Uga)
{
EFI_STATUS Status = EFI_SUCCESS;
UINT32 HorzResolution = 0;
UINT32 VertResolution = 0;
UINT32 ColorDepth = 0;
UINT32 RefreshRate = 0;
Status = Uga->GetMode( Uga, &HorzResolution, &VertResolution,
&ColorDepth, &RefreshRate);
if (EFI_ERROR (Status)) {
Print(L"ERROR: UGA GetMode failed [%d]\n", Status );
} else {
Print(L"Horizontal Resolution: %d\n", HorzResolution);
Print(L"Vertical Resolution: %d\n", VertResolution);
Print(L"Color Depth: %d\n", ColorDepth);
Print(L"Refresh Rate: %d\n", RefreshRate);
Print(L"\n");
}
return Status;
}
EFI_STATUS
CheckUGA(BOOLEAN Verbose)
{
EFI_HANDLE *HandleBuffer = NULL;
UINTN HandleCount = 0;
EFI_STATUS Status = EFI_SUCCESS;
EFI_UGA_DRAW_PROTOCOL *Uga;
// get from ConsoleOutHandle?
Status = gBS->HandleProtocol( gST->ConsoleOutHandle,
&gEfiUgaDrawProtocolGuid,
(VOID **) &Uga);
if (EFI_ERROR (Status)) {
Print(L"No UGA handle found via HandleProtocol\n");
} else {
Print(L"UGA handle found via HandleProtocol\n");
if (Verbose)
PrintUGA(Uga);
}
// try locating directly
Status = gBS->LocateProtocol( &gEfiUgaDrawProtocolGuid,
NULL,
(VOID **) &Uga);
if (EFI_ERROR(Status) || Uga == NULL) {
Print(L"No UGA handle found via LocateProtocol\n");
} else {
Print(L"Found UGA handle via LocateProtocol\n");
if (Verbose)
PrintUGA(Uga);
}
// try locating by handle
Status = gBS->LocateHandleBuffer( ByProtocol,
&gEfiUgaDrawProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer);
if (EFI_ERROR (Status)) {
Print(L"No UGA handles found via LocateHandleBuffer\n");
} else {
Print(L"Found %d UGA handles via LocateHandleBuffer\n", HandleCount);
for (int i = 0; i < HandleCount; i++) {
Status = gBS->HandleProtocol( HandleBuffer[i],
&gEfiUgaDrawProtocolGuid,
(VOID*) &Uga);
if (!EFI_ERROR (Status)) {
if (Verbose)
PrintUGA(Uga);
}
}
FreePool(HandleBuffer);
}
Print(L"\n");
return Status;
}
EFI_STATUS
PrintGOP(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
{
int i, imax;
EFI_STATUS Status;
imax = gop->Mode->MaxMode;
Print(L"GOP reports MaxMode %d\n", imax);
for (i = 0; i < imax; i++) {
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
UINTN SizeOfInfo;
Status = gop->QueryMode(gop, i, &SizeOfInfo, &Info);
if (EFI_ERROR(Status) && Status == EFI_NOT_STARTED) {
gop->SetMode(gop, gop->Mode->Mode);
Status = gop->QueryMode(gop, i, &SizeOfInfo, &Info);
}
if (EFI_ERROR(Status)) {
Print(L"ERROR: Bad response from QueryMode: %d\n", Status);
continue;
}
Print(L"%c%d: %dx%d ", memcmp(Info,gop->Mode->Info,sizeof(*Info)) == 0 ? '*' : ' ', i,
Info->HorizontalResolution,
Info->VerticalResolution);
switch(Info->PixelFormat) {
case PixelRedGreenBlueReserved8BitPerColor:
Print(L"RGBRerserved");
break;
case PixelBlueGreenRedReserved8BitPerColor:
Print(L"BGRReserved");
break;
case PixelBitMask:
Print(L"Red:%08x Green:%08x Blue:%08x Reserved:%08x",
Info->PixelInformation.RedMask,
Info->PixelInformation.GreenMask,
Info->PixelInformation.BlueMask,
Info->PixelInformation.ReservedMask);
break;
case PixelBltOnly:
Print(L"(blt only)");
break;
default:
Print(L"(Invalid pixel format)");
break;
}
Print(L" Pixels %d\n", Info->PixelsPerScanLine);
}
Print(L"\n");
return EFI_SUCCESS;
}
EFI_STATUS
CheckGOP(BOOLEAN Verbose)
{
EFI_HANDLE *HandleBuffer = NULL;
UINTN HandleCount = 0;
EFI_STATUS Status = EFI_SUCCESS;
EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
// get from ConsoleOutHandle?
Status = gBS->HandleProtocol( gST->ConsoleOutHandle,
&gEfiGraphicsOutputProtocolGuid,
(VOID **) &Gop);
if (EFI_ERROR (Status)) {
Print(L"No GOP handle found via HandleProtocol\n");
} else {
Print(L"GOP handle found via HandleProtocol\n");
if (Verbose)
PrintGOP(Gop);
}
// try locating directly
Status = gBS->LocateProtocol( &gEfiGraphicsOutputProtocolGuid,
NULL,
(VOID **) &Gop);
if (EFI_ERROR(Status) || Gop == NULL) {
Print(L"No GOP handle found via LocateProtocol\n");
} else {
Print(L"Found GOP handle via LocateProtocol\n");
if (Verbose)
PrintGOP(Gop);
}
// try locating by handle
Status = gBS->LocateHandleBuffer( ByProtocol,
&gEfiGraphicsOutputProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer);
if (EFI_ERROR (Status)) {
Print(L"No GOP handles found via LocateHandleBuffer\n");
} else {
Print(L"Found %d GOP handles via LocateHandleBuffer\n", HandleCount);
for (int i = 0; i < HandleCount; i++) {
Status = gBS->HandleProtocol( HandleBuffer[i],
&gEfiGraphicsOutputProtocolGuid,
(VOID*) &Gop);
if (!EFI_ERROR (Status)) {
if (Verbose)
PrintGOP(Gop);
}
}
FreePool(HandleBuffer);
}
Print(L"\n");
return Status;
}
EFI_STATUS
PrintCCP(EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl)
{
EFI_STATUS Status = EFI_SUCCESS;
EFI_CONSOLE_CONTROL_SCREEN_MODE Mode;
BOOLEAN GopUgaExists;
BOOLEAN StdInLocked;
Status = ConsoleControl->GetMode(ConsoleControl, &Mode, &GopUgaExists, &StdInLocked);
if (EFI_ERROR (Status)) {
Print(L"ERROR: ConsoleControl GetMode failed [%d]\n", Status );
return Status;
}
Print(L"Screen mode: ");
switch (Mode) {
case EfiConsoleControlScreenText:
Print(L"Text");
break;
case EfiConsoleControlScreenGraphics:
Print(L"Graphics");
break;
case EfiConsoleControlScreenMaxValue:
Print(L"MaxValue");
break;
}
Print(L"\n");
Print(L"Graphics Support Avalaiable: ");
if (GopUgaExists)
Print(L"Yes");
else
Print(L"No");
Print(L"\n");
Print(L"\n");
return EFI_SUCCESS;
}
EFI_STATUS
CheckCCP(BOOLEAN Verbose)
{
EFI_GUID gEfiConsoleControlProtocolGuid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
EFI_HANDLE *HandleBuffer = NULL;
UINTN HandleCount = 0;
EFI_STATUS Status = EFI_SUCCESS;
// get from ConsoleOutHandle?
Status = gBS->HandleProtocol( gST->ConsoleOutHandle,
&gEfiConsoleControlProtocolGuid,
(VOID **) &ConsoleControl);
if (EFI_ERROR (Status)) {
Print(L"No ConsoleControl handle found via HandleProtocol\n");
} else {
Print(L"ConsoleControl handle found via HandleProtocol\n");
if (Verbose)
PrintCCP(ConsoleControl);
}
// try locating directly
Status = gBS->LocateProtocol( &gEfiConsoleControlProtocolGuid,
NULL,
(VOID **) &ConsoleControl);
if (EFI_ERROR(Status) || ConsoleControl == NULL) {
Print(L"No ConsoleControl handle found via LocateProtocol\n");
} else {
Print(L"Found ConsoleControl handle via LocateProtocol\n");
if (Verbose)
PrintCCP(ConsoleControl);
}
// try locating by handle
Status = gBS->LocateHandleBuffer( ByProtocol,
&gEfiConsoleControlProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer);
if (EFI_ERROR (Status)) {
Print(L"No ConsoleControl handles found via LocateHandleBuffer\n");
} else {
Print(L"Found %d ConsoleControl handles via LocateHandleBuffer\n", HandleCount);
for (int i = 0; i < HandleCount; i++) {
Status = gBS->HandleProtocol( HandleBuffer[i],
&gEfiConsoleControlProtocolGuid,
(VOID*) &ConsoleControl);
if (!EFI_ERROR (Status))
if (Verbose)
PrintCCP(ConsoleControl);
}
FreePool(HandleBuffer);
}
Print(L"\n");
return Status;
}
static void
Usage(void)
{
Print(L"Usage: screenmodes [-v|--verbose]\n");
}
INTN
EFIAPI
ShellAppMain(UINTN Argc, CHAR16 **Argv)
{
EFI_STATUS Status = EFI_SUCCESS;
BOOLEAN Verbose = FALSE;
if (Argc == 2) {
if (!StrCmp(Argv[1], L"--verbose") ||
!StrCmp(Argv[1], L"-v")) {
Verbose = TRUE;
}
if (!StrCmp(Argv[1], L"--help") ||
!StrCmp(Argv[1], L"-h") ||
!StrCmp(Argv[1], L"-?")) {
Usage();
return Status;
}
}
// First check for older EDK ConsoleControl protocol support
CheckCCP(Verbose);
// Next check for UGA support (probably none)
CheckUGA(Verbose);
// Finally check for GOP support
CheckGOP(Verbose);
return Status;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment