alder_lake_bios/Insyde/InsydeModulePkg/Universal/BdsDxe/BdsHotKeyDesc.c

2336 lines
78 KiB
C

/** @file
Process BDS hot key description.
;******************************************************************************
;* Copyright (c) 2016 - 2019, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "Bds.h"
H2O_HOT_KEY_DESCRIPTION mDefaultHotKeyDescPosn = {0, 0,
{0xFF, 0xFF, 0xFF, 0x00}, {0x00, 0x00, 0x00, 0x00},
NULL, EFI_GLYPH_HEIGHT, 0,
0, H2O_BDS_DISPLAY_UNIT_CHAR, H2O_BDS_DISPLAY_ORIGIN_X_LEFT,
0, H2O_BDS_DISPLAY_UNIT_CHAR, H2O_BDS_DISPLAY_ORIGIN_Y_BOTTOM
};
H2O_HOT_KEY_DESCRIPTION mDefaultHotKeyDescQuietPosn = {0, 0,
{0xFF, 0xFF, 0xFF, 0x00}, {0x00, 0x00, 0x00, 0x00},
NULL, EFI_GLYPH_HEIGHT, 0,
0, H2O_BDS_DISPLAY_UNIT_CHAR, H2O_BDS_DISPLAY_ORIGIN_X_LEFT,
0, H2O_BDS_DISPLAY_UNIT_CHAR, H2O_BDS_DISPLAY_ORIGIN_Y_BOTTOM
};
STATIC EFI_HII_FONT_PROTOCOL *mHiiFont = NULL;
STATIC BOOLEAN mIsConOutConnectAfterTriggered = FALSE;
STATIC EFI_GUID mDisplayHotKeyAfterSelectGuid = { 0x3d21409e, 0x77b6, 0x4a47, { 0xbf, 0x0b, 0xcb, 0x05, 0xc2, 0x04, 0x65, 0x97 } };
typedef struct {
EFI_GUID *TokenSpaceGuid;
H2O_HOT_KEY_DESCRIPTION *DefaultHotKeyDesc;
UINTN HotKeyOptionOffset;
} PCD_HOT_KEY_DESC_INFO;
STATIC PCD_HOT_KEY_DESC_INFO mPcdHotKeyDescInfoList[] = {
{&gH2OBdsHotKeyDescGuid , &mDefaultHotKeyDescPosn , OFFSET_OF(H2O_HOT_KEY_OPTION, Description) },
{&gH2OBdsHotKeyDescQuietGuid, &mDefaultHotKeyDescQuietPosn, OFFSET_OF(H2O_HOT_KEY_OPTION, QuietDescription)},
};
typedef
EFI_STATUS
(*DESCRIPTION_ATTRIBUTE_FUNCTION) (
IN CHAR8 *NameAsciiStr,
IN CHAR8 *ValueAsciiStr,
OUT H2O_HOT_KEY_DESCRIPTION *HotKeyDesc
);
typedef struct {
CHAR8 *AttributeName;
DESCRIPTION_ATTRIBUTE_FUNCTION AttributeFn;
} DESCRIPTION_ATTRIBUTE_TABLE;
/**
Check if system is in text mode or not.
@retval TRUE System is in text mode.
@retval FALSE System is not in text mode.
**/
BOOLEAN
IsTextMode (
VOID
)
{
EFI_STATUS Status;
KERNEL_CONFIGURATION KernelConfig;
UINT8 *DisableQuietBoot;
Status = GetKernelConfiguration (&KernelConfig);
if (EFI_ERROR (Status) || KernelConfig.QuietBoot == 0) {
return TRUE;
}
Status = gBS->LocateProtocol (
&gEndOfDisableQuietBootGuid,
NULL,
(VOID **) &DisableQuietBoot
);
if (!EFI_ERROR (Status)) {
return TRUE;
}
return FALSE;
}
/**
Check if input token number is exist in the input token number list.
@param[in] TokenList Pointer to token number list
@param[in] TokenListCount The count of token number list
@param[in] TokenNum Target token number
@retval TRUE Input ascii string is valid value string.
@retval FALSE Input ascii string is not valid value string.
**/
STATIC
BOOLEAN
IsTokenInList (
IN UINTN *TokenList,
IN UINTN TokenListCount,
IN UINTN TokenNum
)
{
UINTN Index;
if (TokenList == NULL) {
return FALSE;
}
for (Index = 0; Index < TokenListCount; Index++) {
if (TokenList[Index] == TokenNum) {
return TRUE;
}
}
return FALSE;
}
/**
Check if boot display mode is valid or not.
@param[in] BootDisplayMode Boot display mode value
@retval TRUE Boot display mode is valid.
@retval FALSE Boot display mode is not valid.
**/
STATIC
BOOLEAN
IsValidBootDisplayMode (
IN UINT8 BootDisplayMode
)
{
if (BootDisplayMode == H2O_BDS_BOOT_DISPLAY_MODE_NORMAL ||
BootDisplayMode == H2O_BDS_BOOT_DISPLAY_MODE_QUIET ||
BootDisplayMode == H2O_BDS_BOOT_DISPLAY_MODE_ALL) {
return TRUE;
}
return FALSE;
}
/**
Check if input value is valid position value.
@param[in] Value Position value
@param[in] ValueUnit Position value unit
@retval TRUE Input value is valid position.
@retval FALSE Input value is valid position.
**/
STATIC
BOOLEAN
IsValidPosn (
IN INT32 Value,
IN UINT32 ValueUnit
)
{
switch (ValueUnit) {
case H2O_BDS_DISPLAY_UNIT_CHAR:
case H2O_BDS_DISPLAY_UNIT_PIXEL:
break;
case H2O_BDS_DISPLAY_UNIT_PERCENT:
if (Value > 100 || Value < -100) {
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
/**
Check if it is valid XOrigin value.
@param[in] XOriginValue XOrigin value
@retval TRUE It is valid XOrigin value.
@retval FALSE It is not valid XOrigin value.
**/
STATIC
BOOLEAN
IsValidXOriginPosn (
IN UINT32 XOriginValue
)
{
switch (XOriginValue & ORIGIN_ACTION_MASK) {
case H2O_BDS_DISPLAY_ORIGIN_X_DEFAULT_POSN:
case H2O_BDS_DISPLAY_ORIGIN_X_CENTER:
case H2O_BDS_DISPLAY_ORIGIN_X_DEFAULT:
if ((XOriginValue & ORIGIN_VALUE_MASK) != 0) {
return FALSE;
}
break;
case H2O_BDS_DISPLAY_ORIGIN_X_LEFT:
case H2O_BDS_DISPLAY_ORIGIN_X_RIGHT:
if ((XOriginValue & ORIGIN_VALUE_MASK) > 100) {
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
/**
Check if it is valid YOrigin value.
@param[in] XOriginValue YOrigin value
@retval TRUE It is valid YOrigin value.
@retval FALSE It is not valid YOrigin value.
**/
STATIC
BOOLEAN
IsValidYOriginPosn (
IN UINT32 YOriginValue
)
{
switch (YOriginValue & ORIGIN_ACTION_MASK) {
case H2O_BDS_DISPLAY_ORIGIN_Y_DEFAULT_POSN:
case H2O_BDS_DISPLAY_ORIGIN_Y_CENTER:
case H2O_BDS_DISPLAY_ORIGIN_Y_DEFAULT:
if ((YOriginValue & ORIGIN_VALUE_MASK) != 0) {
return FALSE;
}
break;
case H2O_BDS_DISPLAY_ORIGIN_Y_TOP:
case H2O_BDS_DISPLAY_ORIGIN_Y_BOTTOM:
if ((YOriginValue & ORIGIN_VALUE_MASK) > 100) {
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
/**
Check if input ascii string is valid value string.
@param[in] AsciiStr Pointer to ascii string
@param[in] IsHex A Boolean that specifies string is hex or not
@retval TRUE Input ascii string is valid value string.
@retval FALSE Input ascii string is not valid value string.
**/
STATIC
BOOLEAN
IsValidValueAsciiStr (
IN CHAR8 *AsciiStr,
IN BOOLEAN IsHex
)
{
CHAR8 *AsciiStrPtr;
if (AsciiStr == NULL || *AsciiStr == CHAR_NULL) {
return FALSE;
}
AsciiStrPtr = AsciiStr;
while (*AsciiStrPtr != CHAR_NULL) {
if ((*AsciiStrPtr >= '0' && *AsciiStrPtr <= '9') ||
(IsHex && ((*AsciiStrPtr >= 'a' && *AsciiStrPtr <= 'f') ||
(*AsciiStrPtr >= 'A' && *AsciiStrPtr <= 'F')))) {
AsciiStrPtr++;
continue;
}
return FALSE;
}
return TRUE;
}
/**
Transfer ascii string to lower case.
@param[in, out] AsciiStr Pointer to ascii string
**/
STATIC
VOID
AsciiStrToLower (
IN OUT CHAR8 *AsciiStr
)
{
while (*AsciiStr != CHAR_NULL) {
if (*AsciiStr >= 'A' && *AsciiStr <= 'Z') {
*AsciiStr = (CHAR8) (*AsciiStr - 'A' + 'a');
}
AsciiStr++;
}
}
/**
Transfer GOP Blt color to simple text output color attribute.
@param[in] GopForegroundColor Pointer to GOP Blt foreground color
@param[in] GopBackgroundColor Pointer to GOP Blt background color
@return Simple text output color attribute.
**/
STATIC
UINTN
GopColorToTextOutColor (
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopForegroundColor,
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBackgroundColor
)
{
UINT8 TextOutForegroundColor;
UINT8 TextOutBackgroundColor;
//
// Refer from DisplayUpdateProgress() in MdeModulePkg.
//
TextOutForegroundColor = EFI_BLACK;
if (GopForegroundColor->Blue >= 0x40) {
TextOutForegroundColor |= EFI_BLUE;
}
if (GopForegroundColor->Green >= 0x40) {
TextOutForegroundColor |= EFI_GREEN;
}
if (GopForegroundColor->Red >= 0x40) {
TextOutForegroundColor |= EFI_RED;
}
if (GopForegroundColor->Blue >= 0xC0 || GopForegroundColor->Green >= 0xC0 || GopForegroundColor->Red >= 0xC0) {
TextOutForegroundColor |= EFI_BRIGHT;
}
TextOutBackgroundColor = EFI_BLACK;
if (GopBackgroundColor->Blue >= 0x40) {
TextOutBackgroundColor |= EFI_BLUE;
}
if (GopBackgroundColor->Green >= 0x40) {
TextOutBackgroundColor |= EFI_GREEN;
}
if (GopBackgroundColor->Red >= 0x40) {
TextOutBackgroundColor |= EFI_RED;
}
return EFI_TEXT_ATTR (TextOutForegroundColor, TextOutBackgroundColor);
}
/**
Transfer GOP Blt position to simple text output position.
@param[in] GopPosn GOP Blt position
@param[in] GopResolution GOP Blt resolution
@param[in] TextOutResolution Simple text output resolution
@return Simple text output position.
**/
STATIC
UINTN
GopPosnToTextOutPosn (
IN UINTN GopPosn,
IN UINTN GopResolution,
IN UINTN TextOutResolution
)
{
UINTN Delta;
if (GopResolution == 0 || TextOutResolution == 0) {
return 0;
}
Delta = (GopResolution % TextOutResolution) / 2;
if (GopPosn < Delta) {
return 0;
} else if (GopPosn >= (GopResolution - Delta)) {
return TextOutResolution - 1;
} else {
return ((GopPosn - Delta) * TextOutResolution) / GopResolution;
}
}
/**
Normalize ascii string to remove prefix and suffix space characters and transfer character to lower case.
@param[in, out] AsciiStr Pointer to ascii string
**/
STATIC
VOID
NormalizeAsciiStr (
IN OUT CHAR8 *AsciiStr
)
{
UINTN Length;
if (AsciiStr == NULL) {
return;
}
Length = AsciiStrLen (AsciiStr);
while (Length > 0 && AsciiStr[0] == ' ') {
CopyMem (&AsciiStr[0], &AsciiStr[1], Length - 1);
AsciiStr[Length - 1] = CHAR_NULL;
Length--;
}
while (Length > 0 && AsciiStr[Length - 1] == ' ') {
AsciiStr[Length - 1] = CHAR_NULL;
Length--;
}
AsciiStrToLower (AsciiStr);
}
/**
Get value by parsing ascii string.
@param[in] AsciiStr Pointer to value ascii string
@param[in] UnitAsciiStr Pointer to unit ascii string
@param[out] Value Pointer to value
@retval EFI_SUCCESS Get value successfully.
@retval EFI_INVALID_PARAMETER Input paramter in NULL.
@retval EFI_ABORTED Unit ascii string can not find in value ascii string or value ascii string is invalid.
**/
STATIC
EFI_STATUS
GetValueFromAsciiStr (
IN CHAR8 *AsciiStr,
IN CHAR8 *UnitAsciiStr OPTIONAL,
OUT INT64 *Value
)
{
CHAR8 *AsciiStrPtr;
BOOLEAN IsPositive;
BOOLEAN IsHex;
CHAR8 *UnitAsciiStrPtr;
CHAR8 *ValueAsciiStr;
CHAR8 Buffer[30];
UINTN ValueAsciiStrLen;
UINTN ResultValue;
if (AsciiStr == NULL || Value == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Syntax of string is ::== <signed-integer>[<UnitStr>]
// For example: Return value should be 10 when String is "10%" and UnitStr is "%".
//
AsciiStrPtr = AsciiStr;
if (*AsciiStrPtr == '-') {
AsciiStrPtr++;
IsPositive = FALSE;
} else {
IsPositive = TRUE;
}
if (AsciiStrPtr[0] == '0' && (AsciiStrPtr[1] == 'x' || AsciiStrPtr[1] == 'X')) {
AsciiStrPtr += 2;
IsHex = TRUE;
} else {
IsHex = FALSE;
}
if (UnitAsciiStr == NULL) {
ValueAsciiStr = AsciiStrPtr;
} else {
UnitAsciiStrPtr = AsciiStrStr (AsciiStrPtr, UnitAsciiStr);
if (UnitAsciiStrPtr == NULL || AsciiStrCmp (UnitAsciiStrPtr, UnitAsciiStr) != 0) {
return EFI_ABORTED;
}
ValueAsciiStrLen = (UINTN) (UnitAsciiStrPtr - AsciiStrPtr);
if (ValueAsciiStrLen + 1 > sizeof(Buffer)) {
return EFI_ABORTED;
}
CopyMem (Buffer, AsciiStrPtr, ValueAsciiStrLen);
Buffer[ValueAsciiStrLen] = CHAR_NULL;
ValueAsciiStr = Buffer;
}
if (!IsValidValueAsciiStr (ValueAsciiStr, IsHex)) {
return EFI_ABORTED;
}
ResultValue = IsHex ? AsciiStrHexToUintn (ValueAsciiStr) : AsciiStrDecimalToUintn (ValueAsciiStr);
*Value = IsPositive ? (INT64) ResultValue : -((INT64) ResultValue);
return EFI_SUCCESS;
}
/**
Get font display information.
@param[in] HotKeyDesc Pointer to hot key description
@return Pointer to font display information or NULL if input parameter is NULL or allocate memory failed.
**/
EFI_FONT_DISPLAY_INFO *
GetFontDisplayInfo (
IN H2O_HOT_KEY_DESCRIPTION *HotKeyDesc
)
{
EFI_FONT_DISPLAY_INFO *FontDisplayInfo;
UINTN FontNameAsciiStrLen;
if (HotKeyDesc == NULL) {
return NULL;
}
FontNameAsciiStrLen = (HotKeyDesc->FontName != NULL) ? AsciiStrLen (HotKeyDesc->FontName) : 0;
FontDisplayInfo = AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO) + (FontNameAsciiStrLen * sizeof (CHAR16)));
if (FontDisplayInfo == NULL) {
return NULL;
}
CopyMem (&FontDisplayInfo->ForegroundColor, &HotKeyDesc->ForegroundColor, sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
CopyMem (&FontDisplayInfo->BackgroundColor, &HotKeyDesc->BackgroundColor, sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
FontDisplayInfo->FontInfoMask = 0;
FontDisplayInfo->FontInfo.FontSize = HotKeyDesc->FontSize;
FontDisplayInfo->FontInfo.FontStyle = HotKeyDesc->FontStyle;
if (HotKeyDesc->FontName != NULL) {
AsciiStrToUnicodeStrS (HotKeyDesc->FontName, FontDisplayInfo->FontInfo.FontName, FontNameAsciiStrLen + 1);
}
return FontDisplayInfo;
}
/**
Get current screen resolution.
@param[out] HorizontalResolution Pointer to horizontal resolution
@param[out] VerticalResolution Pointer to vertical resolution
@retval EFI_SUCCESS Get resolution successfully.
@retval EFI_INVALID_PARAMETER Input paramter in NULL.
@retval Other Get resolution failed.
**/
STATIC
EFI_STATUS
GetScreenResolution (
OUT UINT32 *HorizontalResolution,
OUT UINT32 *VerticalResolution
)
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
EFI_UGA_DRAW_PROTOCOL *UgaDraw;
UINT32 ColorDepth;
UINT32 RefreshRate;
if (HorizontalResolution == NULL || VerticalResolution == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = gBS->HandleProtocol (
gST->ConsoleOutHandle,
&gEfiGraphicsOutputProtocolGuid,
(VOID **) &GraphicsOutput
);
if (!EFI_ERROR (Status)) {
*HorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
*VerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;
return EFI_SUCCESS;
}
if (FeaturePcdGet (PcdUgaConsumeSupport)) {
Status = gBS->HandleProtocol (
gST->ConsoleOutHandle,
&gEfiUgaDrawProtocolGuid,
(VOID **) &UgaDraw
);
if (!EFI_ERROR (Status)) {
return UgaDraw->GetMode (UgaDraw, HorizontalResolution, VerticalResolution, &ColorDepth, &RefreshRate);
}
}
return Status;
}
/**
Based on font information, calculate the display area of input string.
@param[in] DisplayString Pointer to display string
@param[in] FontInfo Pointer to font information
@param[out] DisplayWidth Pointer to the width of display area
@param[out] DisplayHeight Pointer to the height of display area
@retval EFI_SUCCESS Get resolution successfully.
@retval EFI_INVALID_PARAMETER Input paramter in NULL.
@retval Other Get resolution failed.
**/
EFI_STATUS
GetDisplayArea (
IN CHAR16 *DisplayString,
IN EFI_FONT_DISPLAY_INFO *FontInfo,
OUT UINT32 *DisplayWidth,
OUT UINT32 *DisplayHeight
)
{
EFI_STATUS Status;
UINT32 HorizontalResolution;
UINT32 VerticalResolution;
EFI_IMAGE_OUTPUT *Blt;
EFI_HII_ROW_INFO *RowInfoArray;
UINTN RowInfoArraySize;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
UINTN Index;
UINTN Width;
UINTN Height;
if (FontInfo == NULL || DisplayString == NULL || DisplayWidth == NULL || DisplayHeight == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
if (EFI_ERROR (Status)) {
return Status;
}
HorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
VerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;
Blt = AllocateZeroPool (sizeof(EFI_IMAGE_OUTPUT));
if (Blt == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Blt->Width = (UINT16) HorizontalResolution;
Blt->Height = (UINT16) VerticalResolution;
Blt->Image.Bitmap = AllocateZeroPool (HorizontalResolution * VerticalResolution * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
if (Blt->Image.Bitmap == NULL) {
FreePool (Blt);
return EFI_OUT_OF_RESOURCES;
}
RowInfoArray = NULL;
RowInfoArraySize = 0;
Status = mHiiFont->StringToImage (
mHiiFont,
EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_OUT_FLAG_CLIP |
EFI_HII_OUT_FLAG_CLIP_CLEAN_X | EFI_HII_OUT_FLAG_CLIP_CLEAN_Y,
DisplayString,
FontInfo,
&Blt,
0,
0,
&RowInfoArray,
&RowInfoArraySize,
NULL
);
FreePool (Blt->Image.Bitmap);
FreePool (Blt);
if (EFI_ERROR (Status)) {
return Status;
}
if (RowInfoArray == NULL) {
return EFI_NOT_FOUND;
}
Height = 0;
Width = 0;
for (Index = 0; Index < RowInfoArraySize; Index++) {
Height += RowInfoArray[Index].LineHeight;
Width = MAX (Width, RowInfoArray[Index].LineWidth);
}
*DisplayWidth = (UINT32) Width;
*DisplayHeight = (UINT32) Height;
FreePool (RowInfoArray);
return Status;
}
/**
Get screen display region of input string.
@param[in] DisplayString Pointer to display string
@param[in] HotKeyDesc Pointer to hot key description
@param[out] DisplayHeight Pointer to screen region
@retval EFI_SUCCESS Get resolution successfully.
@retval EFI_INVALID_PARAMETER Input paramter in NULL.
@retval EFI_ABORTED Get font display info failed.
@retval EFI_UNSUPPORTED One of descrition attribute value is invalid.
@retval Other Get resolution failed.
**/
STATIC
EFI_STATUS
GetDisplayRegion (
IN H2O_HOT_KEY_DESCRIPTION *HotKeyDesc,
IN CHAR16 *DisplayString,
OUT RECT *Region
)
{
EFI_STATUS Status;
UINT32 StrDisplayWidth;
UINT32 StrDisplayHeight;
INT32 Offset;
INT32 ResultX;
INT32 ResultY;
UINT32 HorizontalResolution;
UINT32 VerticalResolution;
UINT32 Percentage;
UINT32 OriginAction;
EFI_FONT_DISPLAY_INFO *FontDisplayInfo;
if (HotKeyDesc == NULL || DisplayString == NULL || Region == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = GetScreenResolution (&HorizontalResolution, &VerticalResolution);
if (EFI_ERROR (Status)) {
return Status;
}
FontDisplayInfo = GetFontDisplayInfo (HotKeyDesc);
if (FontDisplayInfo == NULL) {
return EFI_ABORTED;
}
//
// Get X position
//
switch (HotKeyDesc->XUnit) {
case H2O_BDS_DISPLAY_UNIT_CHAR:
GetDisplayArea (L"M", FontDisplayInfo, &StrDisplayWidth, &StrDisplayHeight);
ResultX = HotKeyDesc->X * ((INT32) (UINTN) StrDisplayWidth);
break;
case H2O_BDS_DISPLAY_UNIT_PIXEL:
ResultX = HotKeyDesc->X;
break;
case H2O_BDS_DISPLAY_UNIT_PERCENT:
ResultX = (INT32) (DivU64x32 (MultU64x32 ((UINT64) HorizontalResolution, (UINT32) HotKeyDesc->X), 100));
break;
default:
FreePool (FontDisplayInfo);
return EFI_UNSUPPORTED;
}
GetDisplayArea (DisplayString, FontDisplayInfo, &StrDisplayWidth, &StrDisplayHeight);
FreePool (FontDisplayInfo);
OriginAction = HotKeyDesc->XOrigin & ORIGIN_ACTION_MASK;
Percentage = HotKeyDesc->XOrigin & ORIGIN_VALUE_MASK;
switch (OriginAction) {
case H2O_BDS_DISPLAY_ORIGIN_X_LEFT:
if (!IS_VALID_PERCENTAGE(Percentage)) {
return EFI_UNSUPPORTED;
}
Offset = (INT32) (DivU64x32 (MultU64x32 ((UINT64) HorizontalResolution, Percentage), 100));
break;
case H2O_BDS_DISPLAY_ORIGIN_X_CENTER:
if (Percentage != 0) {
return EFI_UNSUPPORTED;
}
Offset = (INT32) (DivU64x32 ((UINT64) HorizontalResolution, 2));
Offset -= (StrDisplayWidth / 2);
break;
case H2O_BDS_DISPLAY_ORIGIN_X_RIGHT:
if (!IS_VALID_PERCENTAGE(Percentage)) {
return EFI_UNSUPPORTED;
}
Offset = HorizontalResolution - (INT32) (DivU64x32 (MultU64x32 ((UINT64) HorizontalResolution, Percentage), 100));
Offset -= StrDisplayWidth;
break;
default:
return EFI_UNSUPPORTED;
}
ResultX += Offset;
if (ResultX + StrDisplayWidth > (INT32) HorizontalResolution) {
ResultX = HorizontalResolution - StrDisplayWidth;
}
if (ResultX < 0) {
ResultX = 0;
}
//
// Get Y position
//
switch (HotKeyDesc->YUnit) {
case H2O_BDS_DISPLAY_UNIT_CHAR:
ResultY = (HotKeyDesc->Y * HotKeyDesc->FontSize);
break;
case H2O_BDS_DISPLAY_UNIT_PIXEL:
ResultY = HotKeyDesc->Y;
break;
case H2O_BDS_DISPLAY_UNIT_PERCENT:
ResultY = (INT32) (DivU64x32 (MultU64x32 ((UINT64) HotKeyDesc->Y, VerticalResolution), 100));
break;
default:
return EFI_UNSUPPORTED;
}
OriginAction = HotKeyDesc->YOrigin & ORIGIN_ACTION_MASK;
Percentage = HotKeyDesc->YOrigin & ORIGIN_VALUE_MASK;
switch (OriginAction) {
case H2O_BDS_DISPLAY_ORIGIN_Y_TOP:
if (!IS_VALID_PERCENTAGE(Percentage)) {
return EFI_UNSUPPORTED;
}
Offset = (INT32) (DivU64x32 (MultU64x32 ((UINT64) VerticalResolution, Percentage), 100));
break;
case H2O_BDS_DISPLAY_ORIGIN_Y_CENTER:
if (Percentage != 0) {
return EFI_UNSUPPORTED;
}
Offset = (INT32) (DivU64x32 ((UINT64) VerticalResolution, 2));
break;
case H2O_BDS_DISPLAY_ORIGIN_Y_BOTTOM:
if (!IS_VALID_PERCENTAGE(Percentage)) {
return EFI_UNSUPPORTED;
}
Offset = VerticalResolution - (INT32) (DivU64x32 (MultU64x32 ((UINT64) VerticalResolution, Percentage), 100));
Offset -= HotKeyDesc->FontSize;
break;
default:
return EFI_UNSUPPORTED;
}
ResultY += Offset;
if (ResultY + HotKeyDesc->FontSize > (INT32) VerticalResolution) {
ResultY = VerticalResolution - HotKeyDesc->FontSize;
}
if (ResultY < 0) {
ResultY = 0;
}
Region->left = (INT32) ResultX;
Region->top = (INT32) ResultY;
Region->right = (INT32) (ResultX + StrDisplayWidth);
Region->bottom = (INT32) (ResultY + StrDisplayHeight);
return EFI_SUCCESS;
}
/**
Get the hot key description of specific display mode by handle.
@param[in] HotKeyHandle Hot key description handle
@param[in] BootDisplayMode Boot display mode
@return Pointer to hot key description or NULL if input parameter is NULL or handle is invalid.
**/
STATIC
H2O_HOT_KEY_DESCRIPTION *
GetHotKeyDesc (
IN EFI_HANDLE HotKeyHandle,
IN UINT8 BootDisplayMode
)
{
H2O_HOT_KEY_OPTION *HotKeyOption;
if (HotKeyHandle == NULL) {
return NULL;
}
HotKeyOption = GetHotKeyOption (HotKeyHandle);
if (HotKeyOption == NULL) {
return NULL;
}
switch (BootDisplayMode) {
case H2O_BDS_BOOT_DISPLAY_MODE_NORMAL:
return &HotKeyOption->Description;
case H2O_BDS_BOOT_DISPLAY_MODE_QUIET:
return &HotKeyOption->QuietDescription;
}
return NULL;
}
/**
Attribute X Y process function to update (X, XUnit) or (Y, Yunit) value in hot key description.
@param[in] NameAsciiStr Pointer to attribute name ascii string
@param[in] ValueAsciiStr Pointer to attribute value ascii string
@param[out] HotKeyDesc Pointer to hot key description
@retval EFI_SUCCESS Update attribute successfully.
@retval EFI_ABORTED Value ascii string is invalid.
**/
STATIC
EFI_STATUS
DescAttributeFnXY (
IN CHAR8 *NameAsciiStr,
IN CHAR8 *ValueAsciiStr,
OUT H2O_HOT_KEY_DESCRIPTION *HotKeyDesc
)
{
INT64 Value;
UINT32 DisplayUnit;
ASSERT (NameAsciiStr != NULL);
ASSERT (ValueAsciiStr != NULL);
ASSERT (HotKeyDesc != NULL);
if (GetValueFromAsciiStr (ValueAsciiStr, "em", &Value) == EFI_SUCCESS) {
DisplayUnit = H2O_BDS_DISPLAY_UNIT_CHAR;
} else if (GetValueFromAsciiStr (ValueAsciiStr, "px", &Value) == EFI_SUCCESS) {
DisplayUnit = H2O_BDS_DISPLAY_UNIT_PIXEL;
} else if (GetValueFromAsciiStr (ValueAsciiStr, "%", &Value) == EFI_SUCCESS) {
DisplayUnit = H2O_BDS_DISPLAY_UNIT_PERCENT;
} else {
return EFI_ABORTED;
}
if (NameAsciiStr[0] == 'x') {
HotKeyDesc->X = (INT32) Value;
HotKeyDesc->XUnit = DisplayUnit;
} else {
HotKeyDesc->Y = (INT32) Value;
HotKeyDesc->YUnit = DisplayUnit;
}
return EFI_SUCCESS;
}
/**
Attribute XOrigin process function to update value in hot key description.
@param[in] NameAsciiStr Pointer to attribute name ascii string
@param[in] ValueAsciiStr Pointer to attribute value ascii string
@param[out] HotKeyDesc Pointer to hot key description
@retval EFI_SUCCESS Update attribute successfully.
@retval EFI_ABORTED Value ascii string is invalid.
**/
STATIC
EFI_STATUS
DescAttributeFnXOrigin (
IN CHAR8 *NameAsciiStr,
IN CHAR8 *ValueAsciiStr,
OUT H2O_HOT_KEY_DESCRIPTION *HotKeyDesc
)
{
INT64 Value;
EFI_STATUS Status;
ASSERT (NameAsciiStr != NULL);
ASSERT (ValueAsciiStr != NULL);
ASSERT (HotKeyDesc != NULL);
if (AsciiStrCmp (ValueAsciiStr, "left") == 0) {
Value = H2O_BDS_DISPLAY_ORIGIN_X_LEFT;
} else if (AsciiStrCmp (ValueAsciiStr, "center") == 0) {
Value = H2O_BDS_DISPLAY_ORIGIN_X_CENTER;
} else if (AsciiStrCmp (ValueAsciiStr, "right") == 0) {
Value = H2O_BDS_DISPLAY_ORIGIN_X_RIGHT;
} else if (AsciiStrnCmp (ValueAsciiStr, "left(", (sizeof("left(") - 1)) == 0) {
Status = GetValueFromAsciiStr (&ValueAsciiStr[5], "%)", &Value);
if (EFI_ERROR (Status) || !IS_VALID_PERCENTAGE(Value)) {
return EFI_ABORTED;
}
Value = H2O_BDS_DISPLAY_ORIGIN_X_LEFT_PERCENT(Value);
} else if (AsciiStrnCmp (ValueAsciiStr, "right(", (sizeof("right(") - 1)) == 0) {
Status = GetValueFromAsciiStr (&ValueAsciiStr[6], "%)", &Value);
if (EFI_ERROR (Status) || !IS_VALID_PERCENTAGE(Value)) {
return EFI_ABORTED;
}
Value = H2O_BDS_DISPLAY_ORIGIN_X_RIGHT_PERCENT(Value);
} else {
Status = GetValueFromAsciiStr (ValueAsciiStr, "%", &Value);
if (EFI_ERROR (Status) || !IS_VALID_PERCENTAGE(Value)) {
return EFI_ABORTED;
}
Value = H2O_BDS_DISPLAY_ORIGIN_X_LEFT_PERCENT(Value);
}
HotKeyDesc->XOrigin = (UINT32) Value;
return EFI_SUCCESS;
}
/**
Attribute YOrigin process function to update value in hot key description.
@param[in] NameAsciiStr Pointer to attribute name ascii string
@param[in] ValueAsciiStr Pointer to attribute value ascii string
@param[out] HotKeyDesc Pointer to hot key description
@retval EFI_SUCCESS Update attribute successfully.
@retval EFI_ABORTED Value ascii string is invalid.
**/
STATIC
EFI_STATUS
DescAttributeFnYOrigin (
IN CHAR8 *NameAsciiStr,
IN CHAR8 *ValueAsciiStr,
OUT H2O_HOT_KEY_DESCRIPTION *HotKeyDesc
)
{
INT64 Value;
EFI_STATUS Status;
ASSERT (NameAsciiStr != NULL);
ASSERT (ValueAsciiStr != NULL);
ASSERT (HotKeyDesc != NULL);
if (AsciiStrCmp (ValueAsciiStr, "top") == 0) {
Value = H2O_BDS_DISPLAY_ORIGIN_Y_TOP;
} else if (AsciiStrCmp (ValueAsciiStr, "center") == 0) {
Value = H2O_BDS_DISPLAY_ORIGIN_Y_CENTER;
} else if (AsciiStrCmp (ValueAsciiStr, "bottom") == 0) {
Value = H2O_BDS_DISPLAY_ORIGIN_Y_BOTTOM;
} else if (AsciiStrnCmp (ValueAsciiStr, "top(", (sizeof("top(") - 1)) == 0) {
Status = GetValueFromAsciiStr (&ValueAsciiStr[4], "%)", &Value);
if (EFI_ERROR (Status) || !IS_VALID_PERCENTAGE(Value)) {
return EFI_ABORTED;
}
Value = H2O_BDS_DISPLAY_ORIGIN_Y_TOP_PERCENT(Value);
} else if (AsciiStrnCmp (ValueAsciiStr, "bottom(", (sizeof("bottom(") - 1)) == 0) {
Status = GetValueFromAsciiStr (&ValueAsciiStr[7], "%)", &Value);
if (EFI_ERROR (Status) || !IS_VALID_PERCENTAGE(Value)) {
return EFI_ABORTED;
}
Value = H2O_BDS_DISPLAY_ORIGIN_Y_BOTTOM_PERCENT(Value);
} else {
Status = GetValueFromAsciiStr (ValueAsciiStr, "%", &Value);
if (EFI_ERROR (Status) || !IS_VALID_PERCENTAGE(Value)) {
return EFI_ABORTED;
}
Value = H2O_BDS_DISPLAY_ORIGIN_Y_TOP_PERCENT(Value);
}
HotKeyDesc->YOrigin = (UINT32) Value;
return EFI_SUCCESS;
}
/**
Attribute FontName process function to update value in hot key description.
@param[in] NameAsciiStr Pointer to attribute name ascii string
@param[in] ValueAsciiStr Pointer to attribute value ascii string
@param[out] HotKeyDesc Pointer to hot key description
@retval EFI_SUCCESS Update attribute successfully.
**/
STATIC
EFI_STATUS
DescAttributeFnFont (
IN CHAR8 *NameAsciiStr,
IN CHAR8 *ValueAsciiStr,
OUT H2O_HOT_KEY_DESCRIPTION *HotKeyDesc
)
{
ASSERT (NameAsciiStr != NULL);
ASSERT (ValueAsciiStr != NULL);
ASSERT (HotKeyDesc != NULL);
HotKeyDesc->FontName = AllocateCopyPool (AsciiStrSize (ValueAsciiStr), ValueAsciiStr);
return EFI_SUCCESS;
}
/**
Attribute FontSize process function to update value in hot key description.
@param[in] NameAsciiStr Pointer to attribute name ascii string
@param[in] ValueAsciiStr Pointer to attribute value ascii string
@param[out] HotKeyDesc Pointer to hot key description
@retval EFI_SUCCESS Update attribute successfully.
@retval EFI_ABORTED Value ascii string is invalid.
**/
STATIC
EFI_STATUS
DescAttributeFnFontSize (
IN CHAR8 *NameAsciiStr,
IN CHAR8 *ValueAsciiStr,
OUT H2O_HOT_KEY_DESCRIPTION *HotKeyDesc
)
{
EFI_STATUS Status;
INT64 Value;
ASSERT (NameAsciiStr != NULL);
ASSERT (ValueAsciiStr != NULL);
ASSERT (HotKeyDesc != NULL);
Status = GetValueFromAsciiStr (ValueAsciiStr, NULL, &Value);
if (EFI_ERROR (Status) || Value <= 0) {
return EFI_ABORTED;
}
HotKeyDesc->FontSize = (UINT16) (UINTN) Value;
return EFI_SUCCESS;
}
/**
Attribute FontStyle process function to update value in hot key description.
@param[in] NameAsciiStr Pointer to attribute name ascii string
@param[in] ValueAsciiStr Pointer to attribute value ascii string
@param[out] HotKeyDesc Pointer to hot key description
@retval EFI_SUCCESS Update attribute successfully.
@retval EFI_ABORTED Value ascii string is invalid.
**/
STATIC
EFI_STATUS
DescAttributeFnFontStyle (
IN CHAR8 *NameAsciiStr,
IN CHAR8 *ValueAsciiStr,
OUT H2O_HOT_KEY_DESCRIPTION *HotKeyDesc
)
{
EFI_HII_FONT_STYLE FontStyle;
ASSERT (NameAsciiStr != NULL);
ASSERT (ValueAsciiStr != NULL);
ASSERT (HotKeyDesc != NULL);
if (AsciiStrCmp (ValueAsciiStr, "bold") == 0) {
FontStyle = EFI_HII_FONT_STYLE_BOLD;
} else if (AsciiStrCmp (ValueAsciiStr, "italic") == 0) {
FontStyle = EFI_HII_FONT_STYLE_ITALIC;
} else if (AsciiStrCmp (ValueAsciiStr, "normal") == 0) {
FontStyle = EFI_HII_FONT_STYLE_NORMAL;
} else if (AsciiStrCmp (ValueAsciiStr, "underline") == 0) {
FontStyle = EFI_HII_FONT_STYLE_UNDERLINE;
} else {
return EFI_ABORTED;
}
HotKeyDesc->FontStyle |= FontStyle;
return EFI_SUCCESS;
}
/**
Attribute ForegroundColor BackgroundColor process function to update value in hot key description.
@param[in] NameAsciiStr Pointer to attribute name ascii string
@param[in] ValueAsciiStr Pointer to attribute value ascii string
@param[out] HotKeyDesc Pointer to hot key description
@retval EFI_SUCCESS Update attribute successfully.
@retval EFI_ABORTED Value ascii string is invalid.
**/
STATIC
EFI_STATUS
DescAttributeFnForeBackColor (
IN CHAR8 *NameAsciiStr,
IN CHAR8 *ValueAsciiStr,
OUT H2O_HOT_KEY_DESCRIPTION *HotKeyDesc
)
{
EFI_STATUS Status;
INT64 Value;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Color;
ASSERT (NameAsciiStr != NULL);
ASSERT (ValueAsciiStr != NULL);
ASSERT (HotKeyDesc != NULL);
Status = GetValueFromAsciiStr (ValueAsciiStr, NULL, &Value);
if (EFI_ERROR (Status) || Value < 0) {
return EFI_ABORTED;
}
Color = (NameAsciiStr[0] == 'f') ? &HotKeyDesc->ForegroundColor : &HotKeyDesc->BackgroundColor;
Color->Blue = (UINT8) (Value & 0xFF);
Color->Green = (UINT8) ((Value >> 8) & 0xFF);
Color->Red = (UINT8) ((Value >> 16) & 0xFF);
Color->Reserved = (UINT8) ((Value >> 24) & 0xFF);
return EFI_SUCCESS;
}
DESCRIPTION_ATTRIBUTE_TABLE mDescAttributeTable[] = {{"x" , DescAttributeFnXY },
{"y" , DescAttributeFnXY },
{"xorigin" , DescAttributeFnXOrigin },
{"yorigin" , DescAttributeFnYOrigin },
{"font" , DescAttributeFnFont },
{"fontsize" , DescAttributeFnFontSize },
{"fontstyle", DescAttributeFnFontStyle },
{"forecolor", DescAttributeFnForeBackColor},
{"backcolor", DescAttributeFnForeBackColor},
};
/**
Update attribute into hot key description by parsing attribute ascii string.
@param[in] AttributeAsciiStr Pointer to attribute ascii string
@param[out] HotKeyDesc Pointer to hot key description
@retval EFI_SUCCESS Update attribute successfully.
@retval EFI_INVALID_PARAMETER Input parameter is NULL.
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.
**/
STATIC
EFI_STATUS
HotKeyDescUpdateAttributes (
IN CHAR8 *AttributeAsciiStr,
OUT H2O_HOT_KEY_DESCRIPTION *HotKeyDesc
)
{
CHAR8 *AsciiStrBuffer;
CHAR8 *CurrAttrAsciiStr;
CHAR8 *NextAttrAsciiStr;
CHAR8 *NameAsciiStr;
CHAR8 *ValueAsciiStr;
UINTN Index;
if (AttributeAsciiStr == NULL || HotKeyDesc == NULL) {
return EFI_INVALID_PARAMETER;
}
AsciiStrBuffer = AllocateCopyPool (AsciiStrSize (AttributeAsciiStr), AttributeAsciiStr);
if (AsciiStrBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Extract attributes by parsing description string in format L"name1=value1;name2=value2;..."
//
NextAttrAsciiStr = AsciiStrBuffer;
while (NextAttrAsciiStr != NULL) {
CurrAttrAsciiStr = NextAttrAsciiStr;
NextAttrAsciiStr = AsciiStrStr (NextAttrAsciiStr, ";");
if (NextAttrAsciiStr != NULL) {
*NextAttrAsciiStr = CHAR_NULL;
NextAttrAsciiStr++;
}
NameAsciiStr = CurrAttrAsciiStr;
ValueAsciiStr = AsciiStrStr (NameAsciiStr, "=");
if (ValueAsciiStr == NULL) {
continue;
}
*ValueAsciiStr = CHAR_NULL;
ValueAsciiStr++;
NormalizeAsciiStr (NameAsciiStr);
NormalizeAsciiStr (ValueAsciiStr);
for (Index = 0; Index < sizeof(mDescAttributeTable) / sizeof(DESCRIPTION_ATTRIBUTE_TABLE); Index++) {
if (AsciiStrCmp (mDescAttributeTable[Index].AttributeName, NameAsciiStr) == 0) {
mDescAttributeTable[Index].AttributeFn (NameAsciiStr, ValueAsciiStr, HotKeyDesc);
break;
}
}
}
FreePool (AsciiStrBuffer);
return EFI_SUCCESS;
}
/**
Print string at specific position in text only console output device.
@param[in] GopX GOP position X value
@param[in] GopY GOP position Y value
@param[in] GopResolutionX GOP resolution X value
@param[in] GopResolutionY GOP resolution Y value
@param[in] String Pointer to display string
@param[in] FontDisplayInfo Pointer to font information
**/
STATIC
VOID
PrintStrAtTextOnlyConOutDev (
IN UINTN GopX,
IN UINTN GopY,
IN UINTN GopResolutionX,
IN UINTN GopResolutionY,
IN CHAR16 *String,
IN EFI_FONT_DISPLAY_INFO *FontDisplayInfo
)
{
EFI_STATUS Status;
EFI_HANDLE *HandleBuf;
UINTN NoHandles;
UINTN Index;
VOID *Instance;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
UINTN TextOutResolutionX;
UINTN TextOutResolutionY;
UINTN TextOutX;
UINTN TextOutY;
UINTN Attribute;
EFI_SIMPLE_TEXT_OUTPUT_MODE OrgMode;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiConsoleOutDeviceGuid,
NULL,
&NoHandles,
&HandleBuf
);
if (EFI_ERROR (Status)) {
return;
}
for (Index = 0; Index < NoHandles; Index++) {
Status = gBS->HandleProtocol (HandleBuf[Index], &gEfiGraphicsOutputProtocolGuid, &Instance);
if (!EFI_ERROR (Status)) {
continue;
}
Status = gBS->HandleProtocol (HandleBuf[Index], &gEfiDevicePathProtocolGuid, &Instance);
if (EFI_ERROR (Status)) {
continue;
}
Status = gBS->HandleProtocol (HandleBuf[Index], &gEfiSimpleTextOutProtocolGuid, (VOID **) &SimpleTextOut);
if (EFI_ERROR (Status)) {
continue;
}
Status = SimpleTextOut->QueryMode (SimpleTextOut, (UINTN) SimpleTextOut->Mode->Mode, &TextOutResolutionX, &TextOutResolutionY);
if (EFI_ERROR (Status)) {
continue;
}
CopyMem (&OrgMode, SimpleTextOut->Mode, sizeof(EFI_SIMPLE_TEXT_OUTPUT_MODE));
Attribute = GopColorToTextOutColor (&FontDisplayInfo->ForegroundColor, &FontDisplayInfo->BackgroundColor);
TextOutX = GopPosnToTextOutPosn (GopX + EFI_GLYPH_WIDTH / 2 , GopResolutionX, TextOutResolutionX);
TextOutY = GopPosnToTextOutPosn (GopY + FontDisplayInfo->FontInfo.FontSize / 2, GopResolutionY, TextOutResolutionY);
if (OrgMode.CursorVisible) {
SimpleTextOut->EnableCursor (SimpleTextOut, FALSE);
}
SimpleTextOut->SetCursorPosition (SimpleTextOut, TextOutX, TextOutY);
SimpleTextOut->SetAttribute (SimpleTextOut, Attribute);
SimpleTextOut->OutputString (SimpleTextOut, String);
SimpleTextOut->SetAttribute (SimpleTextOut, (UINTN) OrgMode.Attribute);
SimpleTextOut->SetCursorPosition (SimpleTextOut, (UINTN) OrgMode.CursorColumn, (UINTN) OrgMode.CursorRow);
if (OrgMode.CursorVisible) {
SimpleTextOut->EnableCursor (SimpleTextOut, TRUE);
}
}
FreePool (HandleBuf);
}
/**
Print string at specific position.
@param[in] X Position X value
@param[in] Y Position Y value
@param[in] String Pointer to display string
@param[in] FontDisplayInfo Pointer to font information
@retval EFI_SUCCESS Print string successfully.
@retval EFI_INVALID_PARAMETER Input paramter in NULL.
@retval Other Locate graphics output protocol failed or display function return failed.
**/
STATIC
EFI_STATUS
PrintStrAt (
IN UINTN X,
IN UINTN Y,
IN CHAR16 *String,
IN EFI_FONT_DISPLAY_INFO *FontDisplayInfo
)
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
UINT32 HorizontalResolution;
UINT32 VerticalResolution;
EFI_IMAGE_OUTPUT *Blt;
EFI_HII_ROW_INFO *RowInfoArray;
UINTN RowInfoArraySize;
if (String == NULL || FontDisplayInfo == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
if (EFI_ERROR (Status)) {
return Status;
}
HorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
VerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution;
Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof(EFI_IMAGE_OUTPUT));
if (Blt == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Blt->Width = (UINT16) (HorizontalResolution);
Blt->Height = (UINT16) (VerticalResolution);
Blt->Image.Screen = GraphicsOutput;
RowInfoArray = NULL;
RowInfoArraySize = 0;
Status = mHiiFont->StringToImage (
mHiiFont,
EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_OUT_FLAG_CLIP |
EFI_HII_OUT_FLAG_CLIP_CLEAN_X | EFI_HII_OUT_FLAG_CLIP_CLEAN_Y | EFI_HII_DIRECT_TO_SCREEN,
String,
FontDisplayInfo,
&Blt,
X,
Y,
&RowInfoArray,
&RowInfoArraySize,
NULL
);
FreePool (Blt);
if (EFI_ERROR (Status)) {
return Status;
}
if (RowInfoArray != NULL) {
FreePool (RowInfoArray);
}
PrintStrAtTextOnlyConOutDev (X, Y, HorizontalResolution, VerticalResolution, String, FontDisplayInfo);
return EFI_SUCCESS;
}
/**
Record specific screen region in blt buffer.
@param[in] Region Pointer to specific screen region
@param[out] Bitmap Pointer to blt buffer
@retval EFI_SUCCESS Record screen successfully.
@retval EFI_INVALID_PARAMETER Input paramter in NULL.
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.
@retval Other Locate graphics output protocol failed or blt function return failed.
**/
STATIC
EFI_STATUS
RecordScreen (
IN RECT *Region,
OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **Bitmap
)
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuf;
UINTN Width;
UINTN Height;
if (Region == NULL || Bitmap == NULL || IsRectEmpty (Region)) {
return EFI_INVALID_PARAMETER;
}
Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
if (EFI_ERROR (Status)) {
return Status;
}
Width = Region->right - Region->left;
Height = Region->bottom - Region->top;
BltBuf = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocateZeroPool (Width * Height * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
if (BltBuf == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = GraphicsOutput->Blt (
GraphicsOutput,
BltBuf,
EfiBltVideoToBltBuffer,
Region->left,
Region->top,
0,
0,
Width,
Height,
0
);
if (EFI_ERROR (Status)) {
FreePool (BltBuf);
return Status;
}
*Bitmap = BltBuf;
return EFI_SUCCESS;
}
/**
Restore specific screen region from input blt buffer.
@param[in] Region Pointer to specific screen region
@param[in] Bitmap Pointer to blt buffer
@retval EFI_SUCCESS Record screen successfully.
@retval EFI_INVALID_PARAMETER Input paramter in NULL.
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.
@retval Other Locate graphics output protocol failed or blt function return failed.
**/
EFI_STATUS
RestoreScreen (
IN RECT *Region,
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Bitmap
)
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
if (Region == NULL || Bitmap == NULL || IsRectEmpty (Region)) {
return EFI_INVALID_PARAMETER;
}
Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
if (EFI_ERROR (Status)) {
return Status;
}
return GraphicsOutput->Blt (
GraphicsOutput,
Bitmap,
EfiBltBufferToVideo,
0,
0,
(UINTN) Region->left,
(UINTN) Region->top,
(UINTN) (Region->right - Region->left),
(UINTN) (Region->bottom - Region->top),
0
);
}
/**
Clear hot key description strings at ready to boot.
@param[in] Event A pointer to the Event that triggered the callback
@param[in] Context A pointer to event context
**/
VOID
EFIAPI
ReadyToBootEventFn (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
UINT8 BootDisplayMode;
LIST_ENTRY *Link;
H2O_HOT_KEY_OPTION *HotKeyOption;
H2O_HOT_KEY_DESCRIPTION *HotKeyDesc;
gBS->CloseEvent (Event);
if (!IsGopReady ()) {
return;
}
Status = gBdsServices->GetBootDisplayMode (gBdsServices, &BootDisplayMode);
if (EFI_ERROR (Status)) {
BootDisplayMode = H2O_BDS_BOOT_DISPLAY_MODE_QUIET;
}
Link = GetFirstNode (&mBdsHotKeyList);
while (!IsNull (&mBdsHotKeyList, Link)) {
HotKeyOption = H2O_HOT_KEY_OPTION_FROM_LINK (Link);
Link = GetNextNode (&mBdsHotKeyList, Link);
HotKeyDesc = (BootDisplayMode == H2O_BDS_BOOT_DISPLAY_MODE_QUIET) ? &HotKeyOption->QuietDescription : &HotKeyOption->Description;
if (HotKeyDesc == NULL) {
continue;
}
if (HotKeyDesc->OrgBltBuffer != NULL) {
RestoreScreen (&HotKeyDesc->DisplayRegion, HotKeyDesc->OrgBltBuffer);
FreePool (HotKeyDesc->OrgBltBuffer);
HotKeyDesc->OrgBltBuffer = NULL;
SetRectEmpty (&HotKeyDesc->DisplayRegion);
}
}
}
/**
Display hot key strings after user press hot key.
@param[in] Event The event that is signaled.
@param[in] Context Pointer to the context data.
**/
STATIC
VOID
DisplayHotKeyAfterUserSelectionNotifyFn (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
UINT8 *Instance;
UINT8 BootDisplayMode;
LIST_ENTRY *Link;
H2O_HOT_KEY_OPTION *HotKeyOption;
H2O_HOT_KEY_DESCRIPTION *HotKeyDesc;
CHAR16 *String;
EFI_FONT_DISPLAY_INFO *FontDisplayInfo;
Status = gBS->LocateProtocol (&mDisplayHotKeyAfterSelectGuid, NULL, (VOID **) &Instance);
if (EFI_ERROR (Status)) {
return;
}
if (!IsGopReady ()) {
return;
}
Status = gBdsServices->GetBootDisplayMode (gBdsServices, &BootDisplayMode);
if (EFI_ERROR (Status)) {
BootDisplayMode = H2O_BDS_BOOT_DISPLAY_MODE_QUIET;
}
Link = GetFirstNode (&mBdsHotKeyList);
while (!IsNull (&mBdsHotKeyList, Link)) {
HotKeyOption = H2O_HOT_KEY_OPTION_FROM_LINK (Link);
Link = GetNextNode (&mBdsHotKeyList, Link);
HotKeyDesc = (BootDisplayMode == H2O_BDS_BOOT_DISPLAY_MODE_QUIET) ? &HotKeyOption->QuietDescription : &HotKeyOption->Description;
if (HotKeyDesc == NULL) {
continue;
}
if (HotKeyDesc->OrgBltBuffer != NULL) {
RestoreScreen (&HotKeyDesc->DisplayRegion, HotKeyDesc->OrgBltBuffer);
FreePool (HotKeyDesc->OrgBltBuffer);
HotKeyDesc->OrgBltBuffer = NULL;
SetRectEmpty (&HotKeyDesc->DisplayRegion);
}
if (HotKeyOption != mSelectedHotKeyOption) {
continue;
}
if (HotKeyDesc->AfterDescStrId == 0) {
continue;
}
FontDisplayInfo = GetFontDisplayInfo (HotKeyDesc);
if (FontDisplayInfo == NULL) {
continue;
}
String = GetStringById (HotKeyDesc->AfterDescStrId);
if (String == NULL) {
continue;
}
if (*String == CHAR_NULL) {
FreePool (String);
continue;
}
Status = GetDisplayRegion (HotKeyDesc, String, &HotKeyDesc->DisplayRegion);
if (EFI_ERROR (Status)) {
FreePool (String);
continue;
}
PrintStrAt (
HotKeyDesc->DisplayRegion.left,
HotKeyDesc->DisplayRegion.top,
String,
FontDisplayInfo
);
FreePool (String);
FreePool (FontDisplayInfo);
}
}
/**
ConOut connect after handler to trigger DisplayStringBefore checkpoint if hot key is detected before this checkpoint.
@param[in] Event A pointer to the Event that triggered the callback.
@param[in] Handle Checkpoint handle.
**/
STATIC
VOID
EFIAPI
ConOutConnectAfterHandler (
IN EFI_EVENT Event,
IN H2O_CP_HANDLE Handle
)
{
H2OCpUnregisterHandler (Handle);
mIsConOutConnectAfterTriggered = TRUE;
if (mSelectedHotKeyOption != NULL) {
//
// Hot key is detected before ConOutConnectAfter checkpoint, delay to trigger DisplayStringBefore checkpoint here.
//
TriggerCpDisplayStringBefore (NULL, TRUE, 0);
}
}
/**
Install protocol to trigger display hot key strings after user press hot key.
**/
VOID
DisplayHotKeyAfterUserSelection (
VOID
)
{
if (mIsConOutConnectAfterTriggered) {
TriggerCpDisplayStringBefore (NULL, TRUE, 0);
}
}
/**
Display hot key strings before user press hot key.
**/
STATIC
VOID
EFIAPI
DisplayHotKeyBeforeUserSelection (
VOID
)
{
EFI_STATUS Status;
UINT8 BootDisplayMode;
LIST_ENTRY *Link;
H2O_HOT_KEY_OPTION *HotKeyOption;
H2O_HOT_KEY_DESCRIPTION *HotKeyDesc;
CHAR16 *String;
EFI_FONT_DISPLAY_INFO *FontDisplayInfo;
KERNEL_CONFIGURATION KernelConfig;
if (!IsGopReady ()) {
return;
}
GetKernelConfiguration (&KernelConfig);
if (!FeaturePcdGet (PcdDisplayOemHotkeyString) && (KernelConfig.QuietBoot) && (H2OGetBootType () == EFI_BOOT_TYPE)) {
return;
}
Status = gBdsServices->GetBootDisplayMode (gBdsServices, &BootDisplayMode);
if (EFI_ERROR (Status)) {
BootDisplayMode = H2O_BDS_BOOT_DISPLAY_MODE_QUIET;
}
Link = GetFirstNode (&mBdsHotKeyList);
while (!IsNull (&mBdsHotKeyList, Link)) {
HotKeyOption = H2O_HOT_KEY_OPTION_FROM_LINK (Link);
Link = GetNextNode (&mBdsHotKeyList, Link);
HotKeyDesc = (BootDisplayMode == H2O_BDS_BOOT_DISPLAY_MODE_QUIET) ? &HotKeyOption->QuietDescription : &HotKeyOption->Description;
if (HotKeyDesc == NULL) {
continue;
}
if (HotKeyDesc->BeforeDescStrId == 0) {
continue;
}
FontDisplayInfo = GetFontDisplayInfo (HotKeyDesc);
if (FontDisplayInfo == NULL) {
continue;
}
String = GetStringById (HotKeyDesc->BeforeDescStrId);
if (String == NULL) {
continue;
}
if (*String == CHAR_NULL) {
FreePool (String);
continue;
}
Status = GetDisplayRegion (HotKeyDesc, String, &HotKeyDesc->DisplayRegion);
if (EFI_ERROR (Status)) {
FreePool (String);
continue;
}
RecordScreen (&HotKeyDesc->DisplayRegion, &HotKeyDesc->OrgBltBuffer);
PrintStrAt (
HotKeyDesc->DisplayRegion.left,
HotKeyDesc->DisplayRegion.top,
String,
FontDisplayInfo
);
FreePool (String);
FreePool (FontDisplayInfo);
}
}
/**
Display strings before handler to display before/after string based on H2O_BDS_CP_DISPLAY_STRING_BEFORE_DATA.AfterSelect.
@param[in] Event A pointer to the Event that triggered the callback.
@param[in] Handle Checkpoint handle.
**/
STATIC
VOID
EFIAPI
DisplayStringBeforeHandler (
IN EFI_EVENT Event,
IN H2O_CP_HANDLE Handle
)
{
EFI_STATUS Status;
H2O_BDS_CP_DISPLAY_STRING_BEFORE_DATA *BdsDisplayStringBeforeData;
EFI_GUID BdsDisplayStringBeforeGuid;
EFI_HANDLE ProtocolHandle;
Status = H2OCpLookup (Handle, (VOID **) &BdsDisplayStringBeforeData, &BdsDisplayStringBeforeGuid);
if (EFI_ERROR (Status)) {
DEBUG_CP ((DEBUG_ERROR, "Checkpoint Data Not Found: %x (%r)\n", Handle, Status));
DEBUG_CP ((DEBUG_ERROR, " %a\n", __FUNCTION__));
return;
}
if (BdsDisplayStringBeforeData->Status == H2O_BDS_TASK_SKIP) {
return;
}
if (BdsDisplayStringBeforeData->AfterSelect) {
ProtocolHandle = NULL;
gBS->InstallProtocolInterface (
&ProtocolHandle,
&mDisplayHotKeyAfterSelectGuid,
EFI_NATIVE_INTERFACE,
NULL
);
} else {
DisplayHotKeyBeforeUserSelection ();
}
}
/**
Enumerate PCD hot key description.
**/
VOID
PcdHotKeyDescEnumeration (
VOID
)
{
UINTN Index;
EFI_GUID *TokenSpaceGuid;
EFI_STATUS Status;
UINTN *TokenNumList;
UINTN TokenNumCount;
LIST_ENTRY *Link;
CHAR8 *PcdAsciiStr;
UINTN PcdAsciiStrSize;
UINTN Size;
H2O_HOT_KEY_OPTION *HotKeyOption;
H2O_HOT_KEY_DESCRIPTION *HotKeyDesc;
//
// Enumeratie hot key description from the PCD of token space GUID for every boot display mode.
//
for (Index = 0; Index < sizeof(mPcdHotKeyDescInfoList) / sizeof(PCD_HOT_KEY_DESC_INFO); Index++) {
TokenSpaceGuid = mPcdHotKeyDescInfoList[Index].TokenSpaceGuid;
Status = GetTokenNumList (TokenSpaceGuid, &TokenNumList, &TokenNumCount);
if (EFI_ERROR (Status) || TokenNumList == NULL) {
continue;
}
Link = GetFirstNode (&mBdsHotKeyList);
while (!IsNull (&mBdsHotKeyList, Link)) {
HotKeyOption = H2O_HOT_KEY_OPTION_FROM_LINK (Link);
Link = GetNextNode (&mBdsHotKeyList, Link);
if (HotKeyOption->Type != PCD_HOT_KEY) {
continue;
}
HotKeyDesc = (H2O_HOT_KEY_DESCRIPTION *) (((UINT8 *) HotKeyOption) + mPcdHotKeyDescInfoList[Index].HotKeyOptionOffset);
CopyMem (
HotKeyDesc,
mPcdHotKeyDescInfoList[Index].DefaultHotKeyDesc,
sizeof(H2O_HOT_KEY_DESCRIPTION)
);
if (!IsTokenInList (TokenNumList, TokenNumCount, HotKeyOption->PcdTokenNum)) {
continue;
}
PcdAsciiStr = (CHAR8 *) LibPcdGetExPtr (TokenSpaceGuid, HotKeyOption->PcdTokenNum);
PcdAsciiStrSize = LibPcdGetExSize (TokenSpaceGuid, HotKeyOption->PcdTokenNum);
if (PcdAsciiStr == NULL || PcdAsciiStrSize == 0) {
continue;
}
//
// PCD data is in following format "BEFORE_STRING_TOKEN\0AFTER_STRING_TOKEN\0Attribute ASCII Strings\0".
// So, update data in following order before string ID, after string ID and attributes.
//
HiiGetStringIdByName (BdsDxeStringsToIds, PcdAsciiStr, &HotKeyDesc->BeforeDescStrId);
Size = AsciiStrSize (PcdAsciiStr);
if (PcdAsciiStrSize <= Size) {
continue;
}
PcdAsciiStr += Size;
PcdAsciiStrSize -= Size;
HiiGetStringIdByName (BdsDxeStringsToIds, PcdAsciiStr, &HotKeyDesc->AfterDescStrId);
Size = AsciiStrSize (PcdAsciiStr);
if (PcdAsciiStrSize <= Size) {
continue;
}
PcdAsciiStr += Size;
HotKeyDescUpdateAttributes (PcdAsciiStr, HotKeyDesc);
}
FreePool (TokenNumList);
}
}
/**
Initialize BDS hot key description.
@retval EFI_SUCCESS Initialize BDS hot key description successfully.
@retval Other Locate protocol failed.
**/
EFI_STATUS
BdsHotKeyDescInit (
VOID
)
{
EFI_STATUS Status;
EFI_EVENT Event;
VOID *Registration;
H2O_CP_HANDLE CpHandle;
Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, (VOID **) &mHiiFont);
if (EFI_ERROR (Status)) {
return Status;
}
HotKeyDescUpdateAttributes ((CHAR8 *) PcdGetPtr (PcdH2OBdsDefaultHotKeyDescPosn) , &mDefaultHotKeyDescPosn);
HotKeyDescUpdateAttributes ((CHAR8 *) PcdGetPtr (PcdH2OBdsDefaultHotKeyDescQuietPosn), &mDefaultHotKeyDescQuietPosn);
PcdHotKeyDescEnumeration ();
//
// Register protocol notify to clear hot key description strings.
//
EfiCreateEventReadyToBootEx (
TPL_CALLBACK,
ReadyToBootEventFn,
NULL,
&Event
);
//
// To prevent from gH2OBdsCpDisplayStringBeforeGuid checkpoint doesn't work properly.
// (will be called in TPL_NOTIFY TPL).
// Register a callback function using 5 TPL to make sure the checkpoint can work properly.
//
EfiCreateProtocolNotifyEvent (
&mDisplayHotKeyAfterSelectGuid,
TPL_APPLICATION + 1,
DisplayHotKeyAfterUserSelectionNotifyFn,
NULL,
&Registration
);
if (FeaturePcdGet (PcdH2OBdsCpDisplayStringBeforeSupported)) {
Status = H2OCpRegisterHandler (
&gH2OBdsCpDisplayStringBeforeGuid,
DisplayStringBeforeHandler,
H2O_CP_LOW,
&CpHandle
);
if (EFI_ERROR (Status)) {
DEBUG_CP ((DEBUG_ERROR, "Checkpoint Register Fail: %g (%r)\n", &gH2OBdsCpDisplayStringBeforeGuid, Status));
return Status;
}
DEBUG_CP ((DEBUG_INFO, "Checkpoint Registered: %g (%r)\n", &gH2OBdsCpDisplayStringBeforeGuid, Status));
}
if (FeaturePcdGet (PcdH2OBdsCpConOutConnectAfterSupported)) {
Status = H2OCpRegisterHandler (
&gH2OBdsCpConOutConnectAfterGuid,
ConOutConnectAfterHandler,
H2O_CP_LOW,
&CpHandle
);
if (EFI_ERROR (Status)) {
DEBUG_CP ((DEBUG_ERROR, "Checkpoint Register Fail: %g (%r)\n", &gH2OBdsCpConOutConnectAfterGuid, Status));
return Status;
}
DEBUG_CP ((DEBUG_INFO, "Checkpoint Registered: %g (%r)\n", &gH2OBdsCpConOutConnectAfterGuid, Status));
}
return EFI_SUCCESS;
}
/**
Get the current boot display mode, either normal or quiet.
@param[in] This A pointer to the current instance of this protocol.
@param[out] BootDisplayMode On exit, returns whether the boot display is in
text mode (H2O_BDS_BOOT_DISPLAY_NORMAL) or graphics mode (H2O_BDS_BOOT_DISPLAY_QUIET).
@retval EFI_SUCCESS Function completed successfully.
@retval EFI_INVALID_PARAMETER This or BootDisplayMode is NULL.
**/
EFI_STATUS
EFIAPI
BdsServicesGetBootDisplayMode (
IN H2O_BDS_SERVICES_PROTOCOL *This,
OUT UINT8 *BootDisplayMode
)
{
if (This == NULL || BootDisplayMode == NULL) {
return EFI_INVALID_PARAMETER;
}
*BootDisplayMode = IsTextMode () ? H2O_BDS_BOOT_DISPLAY_MODE_NORMAL : H2O_BDS_BOOT_DISPLAY_MODE_QUIET;
return EFI_SUCCESS;
}
/**
Change the hot key description for a specific hot key.
@param[in] This A pointer to the current instance of this protocol.
@param[in] HotKeyHandle Handle of a previously registered hot key.
@param[in] BootDisplayMode Enumerated value that specifies the boot display mode for which these descriptions are
valid. Valid values are: H2O_BDS_BOOT_DISPLAY_MODE_NORMAL - Text
H2O_BDS_BOOT_DISPLAY_MODE_QUIET - Graphics
H2O_BDS_BOOT_DISPLAY_MODE_ALL - Text & Graphics
@param[in] BeforeDescText Pointer to an optional null-terminated string that specifies the text that will be
displayed before the hot key has been detected. A NULL specifies that nothing will
be displayed.
@param[in] AfterDescText Pointer to an optional null-terminated string that specifies the text that will be
displayed after the hot key has been detected. A NULL specifies that nothing will be
displayed.
@retval EFI_SUCCESS Function completed successfully.
@retval EFI_INVALID_PARAMETER HotKeyHandle specifies an invalid handle or BootDisplayMode specifies an invalid boot
display mode for this platform.
@retval EFI_NOT_FOUND Hot key option is not found for HotKeyHandle.
**/
EFI_STATUS
EFIAPI
BdsServicesSetHotKeyDescText (
IN H2O_BDS_SERVICES_PROTOCOL *This,
IN EFI_HANDLE HotKeyHandle,
IN UINT8 BootDisplayMode,
IN CONST CHAR16 *BeforeDescText OPTIONAL,
IN CONST CHAR16 *AfterDescText OPTIONAL
)
{
EFI_STATUS Status1;
EFI_STATUS Status2;
H2O_HOT_KEY_DESCRIPTION *HotKeyDesc;
if (This == NULL || HotKeyHandle == NULL || !IsValidBootDisplayMode (BootDisplayMode)) {
return EFI_INVALID_PARAMETER;
}
if (BootDisplayMode == H2O_BDS_BOOT_DISPLAY_MODE_ALL) {
Status1 = BdsServicesSetHotKeyDescText (This, HotKeyHandle, H2O_BDS_BOOT_DISPLAY_MODE_NORMAL, BeforeDescText, AfterDescText);
Status2 = BdsServicesSetHotKeyDescText (This, HotKeyHandle, H2O_BDS_BOOT_DISPLAY_MODE_QUIET , BeforeDescText, AfterDescText);
return EFI_ERROR (Status1) ? Status1 : Status2;
}
HotKeyDesc = GetHotKeyDesc (HotKeyHandle, BootDisplayMode);
if (HotKeyDesc == NULL) {
return EFI_NOT_FOUND;
}
if (BeforeDescText != NULL) {
HotKeyDesc->BeforeDescStrId = HiiSetString (gStringPackHandle, HotKeyDesc->BeforeDescStrId, (CONST EFI_STRING) BeforeDescText, NULL);
}
if (AfterDescText != NULL) {
HotKeyDesc->AfterDescStrId = HiiSetString (gStringPackHandle, HotKeyDesc->AfterDescStrId, (CONST EFI_STRING) AfterDescText, NULL);
}
return EFI_SUCCESS;
}
/**
Change the hot key position for a specific hot key.
@param[in] This A pointer to the current instance of this protocol.
@param[in] HotKeyHandle Handle of a previously registered hot key.
@param[in] BootDisplayMode Enumerated value that specifies the boot display mode for which these descriptions are
valid. Valid values are: H2O_BDS_BOOT_DISPLAY_MODE_NORMAL - Text
H2O_BDS_BOOT_DISPLAY_MODE_QUIET - Graphics
H2O_BDS_BOOT_DISPLAY_MODE_ALL - Text & Graphics
@param[in] X Signed integer value that specifies the X offset, relative to the X origin, in unites specified by XUnit.
@param[in] XUnit Enumerated value that specifies the unit of measurement associated with X. Valid values are:
H2O_BDS_DISPLAY_UNIT_CHAR - X is measured in character cells of the display font.
H2O_BDS_DISPLAY_UNIT_PIXEL - X is measured in pixels.
H2O_BDS_DISPLAY_UNIT_PERCENT - X is measured in percentage of the screen width.
@param[in] XOrigin Enumerated value that specifies the horizontal origin location. Associated with the Description
Horizontal Origin and Description Horizontal Origin Offset. Valid values are:
H2O_BDS_DISPLAY_X_ORIGIN_LEFT -X is measured from the left edge.
H2O_BDS_DISPLAY_X_ORIGIN_CENTER - X is measured from the center of the screen, less half of the
width of the string.
H2O_BDS_DISPLAY_X_ORIGIN_RIGHT -X is measured from the right edge, less the width of the string.
H2O_BDS_DISPLAY_X_ORIGIN_DEFAULT -Use the default X origin.
H2O_BDS_DISPLAY_X_ORIGIN_DEFAULT_POSN -Use the default X position, unit and origin.
H2O_BDS_DISPLAY_X_ORIGIN_LEFT_PERCENT(percent) - X is measured from the left edge of the screen
+ percent% of the screen width. If percent is
equal to 0, then this is equivalent to
H2O_BDS_DISPLAY_X_ORIGIN_LEFT.
H2O_BDS_DISPLAY_X_ORIGIN_RIGHT_PERCENT(percent) - X is measured from the right edge of the screen,
less the width of the string, less the percent%
of the screen width. If percent is equal to 0,
then this is equivalent to H2O_BDS_DISPLAY_X_ORIGIN_RIGHT.
Signed integer value that specifies the Y offset, relative to the Y origin, in unites specified by YUnit.
@param[in] Y Enumerated value that specifies the unit of measurement associated with Y. Valid values are:
H2O_BDS_DISPLAY_UNIT_CHAR -Y is measured in character cells of the display font.
H2O_BDS_DISPLAY_UNIT_PIXEL -Y is measured in pixels.
H2O_BDS_DISPLAY_UNIT_PERCENT -Y is measured in percentage of the screen width.
@param[in] YUnit Enumerated value that specifies the vertical origin location. Associated with the Description
Vertical Origin and Description Vertical Origin Offset. Valid values are:
H2O_BDS_DISPLAY_Y_ORIGIN_TOP -Y is measured from the top edge.
H2O_BDS_DISPLAY_Y_ORIGIN_CENTER - Y is measured from the center of the screen, less half of the
height of the string.
H2O_BDS_DISPLAY_Y_ORIGIN_RIGHT -Y is measured from the bottom edge, less the height of the string.
H2O_BDS_DISPLAY_Y_ORIGIN_DEFAULT -Use the default Y origin.
H2O_BDS_DISPLAY_Y_ORIGIN_DEFAULT_POSN - Use the default Y position, unit and origin.
H2O_BDS_DISPLAY_X_ORIGIN_TOP_PERCENT(percent) - Y is measured from the top edge of the screen +
percent% of the screen height. If percent is equal
to 0, then this is equivalent to H2O_BDS_DISPLAY_X_ORIGIN_TOP.
H2O_BDS_DISPLAY_X_ORIGIN_BOTTOM_PERCENT(percent) - Y is measured from the bottom edge, less the
height of the string, less the percent% of the
screen height. If percent is equal to 0, then
this is equivalent to H2O_BDS_DISPLAY_X_ORIGIN_RIGHT.
@param[in] YOrigin Enumerated value that specifies the vertical origin location.
@retval EFI_SUCCESS This function has completed successfully.
@retval EFI_INVALID_PARAMETER HotKeyHandle specifies an invalid handle or BootDisplayMode specifies an invalid boot
display mode for this platform.
@retval EFI_NOT_FOUND Hot key option is not found for HotKeyHandle.
**/
EFI_STATUS
EFIAPI
BdsServicesSetHotKeyDescPosn (
IN H2O_BDS_SERVICES_PROTOCOL *This,
IN EFI_HANDLE HotKeyHandle,
IN UINT8 BootDisplayMode,
IN INT32 X,
IN UINT32 XUnit,
IN UINT32 *XOrigin OPTIONAL,
IN INT32 Y,
IN UINT32 YUnit,
IN UINT32 *YOrigin OPTIONAL
)
{
EFI_STATUS Status1;
EFI_STATUS Status2;
H2O_HOT_KEY_DESCRIPTION *HotKeyDesc;
if (This == NULL || HotKeyHandle == NULL || !IsValidBootDisplayMode (BootDisplayMode) ||
!IsValidPosn (X, XUnit) || !IsValidPosn (Y, YUnit)) {
return EFI_INVALID_PARAMETER;
}
if ((XOrigin != NULL && !IsValidXOriginPosn (*XOrigin)) ||
(YOrigin != NULL && !IsValidYOriginPosn (*YOrigin))) {
return EFI_INVALID_PARAMETER;
}
if (BootDisplayMode == H2O_BDS_BOOT_DISPLAY_MODE_ALL) {
Status1 = BdsServicesSetHotKeyDescPosn (This, HotKeyHandle, H2O_BDS_BOOT_DISPLAY_MODE_NORMAL, X, XUnit, XOrigin, Y, YUnit, YOrigin);
Status2 = BdsServicesSetHotKeyDescPosn (This, HotKeyHandle, H2O_BDS_BOOT_DISPLAY_MODE_QUIET , X, XUnit, XOrigin, Y, YUnit, YOrigin);
return EFI_ERROR (Status1) ? Status1 : Status2;
}
HotKeyDesc = GetHotKeyDesc (HotKeyHandle, BootDisplayMode);
if (HotKeyDesc == NULL) {
return EFI_NOT_FOUND;
}
HotKeyDesc->X = X;
HotKeyDesc->XUnit = XUnit;
HotKeyDesc->Y = Y;
HotKeyDesc->YUnit = YUnit;
if (XOrigin != NULL) {
HotKeyDesc->XOrigin = *XOrigin;
}
if (YOrigin != NULL) {
HotKeyDesc->YOrigin = *YOrigin;
}
return EFI_SUCCESS;
}
/**
Change the hot key color for a specific hot key description.
@param[in] This A pointer to the current instance of this protocol.
@param[in] HotKeyHandle Handle of a previously registered hot key.
@param[in] BootDisplayMode Enumerated value that specifies the boot display mode for which these descriptions are
valid. Valid values are: H2O_BDS_BOOT_DISPLAY_MODE_NORMAL - Text
H2O_BDS_BOOT_DISPLAY_MODE_QUIET - Graphics
H2O_BDS_BOOT_DISPLAY_MODE_ALL - Text & Graphics
@param[in] ForegroundColor The color of the "on" pixels in the font characters.
@param[in] BackgroundColor The color of the "off" pixels in the font characters.
@retval EFI_SUCCESS Function completed successfully.
@retval EFI_INVALID_PARAMETER HotKeyHandle specifies an invalid handle.
@retval EFI_NOT_FOUND Hot key option is not found for HotKeyHandle.
**/
EFI_STATUS
EFIAPI
BdsServicesSetHotKeyDescColor (
IN H2O_BDS_SERVICES_PROTOCOL *This,
IN EFI_HANDLE HotKeyHandle,
IN UINT8 BootDisplayMode,
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ForegroundColor,
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL BackgroundColor
)
{
EFI_STATUS Status1;
EFI_STATUS Status2;
H2O_HOT_KEY_DESCRIPTION *HotKeyDesc;
if (This == NULL || HotKeyHandle == NULL || !IsValidBootDisplayMode (BootDisplayMode)) {
return EFI_INVALID_PARAMETER;
}
if (BootDisplayMode == H2O_BDS_BOOT_DISPLAY_MODE_ALL) {
Status1 = BdsServicesSetHotKeyDescColor (This, HotKeyHandle, H2O_BDS_BOOT_DISPLAY_MODE_NORMAL, ForegroundColor, BackgroundColor);
Status2 = BdsServicesSetHotKeyDescColor (This, HotKeyHandle, H2O_BDS_BOOT_DISPLAY_MODE_QUIET , ForegroundColor, BackgroundColor);
return EFI_ERROR (Status1) ? Status1 : Status2;
}
HotKeyDesc = GetHotKeyDesc (HotKeyHandle, BootDisplayMode);
if (HotKeyDesc == NULL) {
return EFI_NOT_FOUND;
}
CopyMem (&HotKeyDesc->ForegroundColor, &ForegroundColor, sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
CopyMem (&HotKeyDesc->BackgroundColor, &BackgroundColor, sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
return EFI_SUCCESS;
}
/**
Change the hot key font for a specific hot key description.
@param[in] This A pointer to the current instance of this protocol.
@param[in] HotKeyHandle Handle of a previously registered hot key.
@param[in] BootDisplayMode Enumerated value that specifies the boot display mode for which these descriptions are
valid. Valid values are: H2O_BDS_BOOT_DISPLAY_MODE_NORMAL - Text
H2O_BDS_BOOT_DISPLAY_MODE_QUIET - Graphics
H2O_BDS_BOOT_DISPLAY_MODE_ALL - Text & Graphics
@param[in] FontName Pointer to optional null-terminated ASCII string that specifies the name of the font
to use for the display of these strings. A NULL specifies that the default font name,
font size and style will be used.
@param[in] FontSize Unsigned integer that specifies the height of the font to use for the display of these
strings. If FontName is NULL, then this is ignored.
@param[in] FontStyle Bitmask that specifies the style of the font to use for the display of these strings.
If FontName is NULL, then this is ignored
@retval EFI_SUCCESS Function completed successfully.
@retval EFI_INVALID_PARAMETER HotKeyHandle specifies an invalid handle.
@retval EFI_NOT_FOUND Hot key option is not found for HotKeyHandle.
**/
EFI_STATUS
EFIAPI
BdsServicesSetHotKeyDescFont (
IN H2O_BDS_SERVICES_PROTOCOL *This,
IN EFI_HANDLE HotKeyHandle,
IN UINT8 BootDisplayMode,
IN CONST CHAR8 *FontName OPTIONAL,
IN UINT16 FontSize,
IN EFI_HII_FONT_STYLE FontStyle
)
{
EFI_STATUS Status1;
EFI_STATUS Status2;
H2O_HOT_KEY_DESCRIPTION *HotKeyDesc;
if (This == NULL || HotKeyHandle == NULL || !IsValidBootDisplayMode (BootDisplayMode)) {
return EFI_INVALID_PARAMETER;
}
if (BootDisplayMode == H2O_BDS_BOOT_DISPLAY_MODE_ALL) {
Status1 = BdsServicesSetHotKeyDescFont (This, HotKeyHandle, H2O_BDS_BOOT_DISPLAY_MODE_NORMAL, FontName, FontSize, FontStyle);
Status2 = BdsServicesSetHotKeyDescFont (This, HotKeyHandle, H2O_BDS_BOOT_DISPLAY_MODE_QUIET , FontName, FontSize, FontStyle);
return EFI_ERROR (Status1) ? Status1 : Status2;
}
HotKeyDesc = GetHotKeyDesc (HotKeyHandle, BootDisplayMode);
if (HotKeyDesc == NULL) {
return EFI_NOT_FOUND;
}
if (HotKeyDesc->FontName != NULL) {
FreePool (HotKeyDesc->FontName);
}
if (FontName == NULL) {
HotKeyDesc->FontName = NULL;
HotKeyDesc->FontSize = EFI_GLYPH_HEIGHT;
HotKeyDesc->FontStyle = 0;
} else {
HotKeyDesc->FontName = AllocateCopyPool (AsciiStrSize (FontName), FontName);
HotKeyDesc->FontSize = FontSize;
HotKeyDesc->FontStyle = FontStyle;
}
return EFI_SUCCESS;
}