/** @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 ::== [] // 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; }