From 7c6c064ca8ebb5baf5104e8a4764cd3c19ef8bf1 Mon Sep 17 00:00:00 2001 From: Eric Dong Date: Mon, 12 Aug 2013 02:19:56 +0000 Subject: Update Browser to provide the customization possibilities. Signed-off-by: Eric Dong Reviewed-by: Liming Gao Tested-by: Laszlo Ersek git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14540 6f19259b-4bc3-4df7-8a09-765794883524 --- .../CustomizedDisplayLibInternal.c | 937 +++++++++++++++++++++ 1 file changed, 937 insertions(+) create mode 100644 MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c (limited to 'MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c') diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c new file mode 100644 index 0000000000..9b6ddb517f --- /dev/null +++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c @@ -0,0 +1,937 @@ +/** @file + + This library class defines a set of interfaces to customize Display module + +Copyright (c) 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include "CustomizedDisplayLibInternal.h" + +EFI_SCREEN_DESCRIPTOR gScreenDimensions; +CHAR16 *mLibUnknownString; +extern EFI_HII_HANDLE mCDLStringPackHandle; +CHAR16 *mSpaceBuffer; +#define SPACE_BUFFER_SIZE 1000 + +// +// Browser Global Strings +// +CHAR16 *gEnterString; +CHAR16 *gEnterCommitString; +CHAR16 *gEnterEscapeString; +CHAR16 *gEscapeString; +CHAR16 *gMoveHighlight; +CHAR16 *gDecNumericInput; +CHAR16 *gHexNumericInput; +CHAR16 *gToggleCheckBox; +CHAR16 *gLibEmptyString; +CHAR16 *gAreYouSure; +CHAR16 *gYesResponse; +CHAR16 *gNoResponse; +CHAR16 *gPlusString; +CHAR16 *gMinusString; +CHAR16 *gAdjustNumber; +CHAR16 *gSaveChanges; +CHAR16 *gNvUpdateMessage; +CHAR16 *gInputErrorMessage; + +/** + + Print banner info for front page. + + @param[in] FormData Form Data to be shown in Page + +**/ +VOID +PrintBannerInfo ( + IN FORM_DISPLAY_ENGINE_FORM *FormData + ) +{ + UINT8 Line; + UINT8 Alignment; + CHAR16 *StrFrontPageBanner; + UINT8 RowIdx; + UINT8 ColumnIdx; + + // + // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND); + // + ClearLines ( + gScreenDimensions.LeftColumn, + gScreenDimensions.RightColumn, + gScreenDimensions.TopRow, + FRONT_PAGE_HEADER_HEIGHT - 1 + gScreenDimensions.TopRow, + BANNER_TEXT | BANNER_BACKGROUND + ); + + // + // for (Line = 0; Line < BANNER_HEIGHT; Line++) { + // + for (Line = (UINT8) gScreenDimensions.TopRow; Line < BANNER_HEIGHT + (UINT8) gScreenDimensions.TopRow; Line++) { + // + // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) { + // + for (Alignment = (UINT8) gScreenDimensions.LeftColumn; + Alignment < BANNER_COLUMNS + (UINT8) gScreenDimensions.LeftColumn; + Alignment++ + ) { + RowIdx = (UINT8) (Line - (UINT8) gScreenDimensions.TopRow); + ColumnIdx = (UINT8) (Alignment - (UINT8) gScreenDimensions.LeftColumn); + + ASSERT (RowIdx < BANNER_HEIGHT && ColumnIdx < BANNER_COLUMNS); + + if (gBannerData!= NULL && gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) { + StrFrontPageBanner = LibGetToken (gBannerData->Banner[RowIdx][ColumnIdx], FormData->HiiHandle); + } else { + continue; + } + + switch (Alignment - gScreenDimensions.LeftColumn) { + case 0: + // + // Handle left column + // + PrintStringAt (gScreenDimensions.LeftColumn + BANNER_LEFT_COLUMN_INDENT, Line, StrFrontPageBanner); + break; + + case 1: + // + // Handle center column + // + PrintStringAt ( + gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3, + Line, + StrFrontPageBanner + ); + break; + + case 2: + // + // Handle right column + // + PrintStringAt ( + gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) * 2 / 3, + Line, + StrFrontPageBanner + ); + break; + } + + FreePool (StrFrontPageBanner); + } + } +} + +/** + + Print framework for a page. + +**/ +VOID +PrintFramework ( + VOID + ) +{ + UINTN Index; + CHAR16 Character; + CHAR16 *Buffer; + UINTN Row; + + Buffer = AllocateZeroPool (0x10000); + ASSERT (Buffer != NULL); + Character = BOXDRAW_HORIZONTAL; + for (Index = 0; Index + 2 < (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn); Index++) { + Buffer[Index] = Character; + } + + ClearLines ( + gScreenDimensions.LeftColumn, + gScreenDimensions.RightColumn, + gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, + gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1, + KEYHELP_TEXT | KEYHELP_BACKGROUND + ); + + if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) { + ClearLines ( + gScreenDimensions.LeftColumn, + gScreenDimensions.RightColumn, + gScreenDimensions.TopRow, + gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, + TITLE_TEXT | TITLE_BACKGROUND + ); + // + // Print Top border line + // +------------------------------------------------------------------------------+ + // ? ? + // +------------------------------------------------------------------------------+ + // + Character = BOXDRAW_DOWN_RIGHT; + + PrintCharAt ((UINTN) -1, (UINTN) -1, Character); + PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer); + + Character = BOXDRAW_DOWN_LEFT; + PrintCharAt ((UINTN) -1, (UINTN) -1, Character); + + Character = BOXDRAW_VERTICAL; + for (Row = gScreenDimensions.TopRow + 1; Row <= gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) { + PrintCharAt (gScreenDimensions.LeftColumn, Row, Character); + PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character); + } + + Character = BOXDRAW_UP_RIGHT; + PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character); + PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer); + + Character = BOXDRAW_UP_LEFT; + PrintCharAt ((UINTN) -1, (UINTN) -1, Character); + + // + // Print Bottom border line + // +------------------------------------------------------------------------------+ + // ? ? + // +------------------------------------------------------------------------------+ + // + Character = BOXDRAW_DOWN_RIGHT; + PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, Character); + + PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer); + + Character = BOXDRAW_DOWN_LEFT; + PrintCharAt ((UINTN) -1, (UINTN) -1, Character); + Character = BOXDRAW_VERTICAL; + for (Row = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1; + Row <= gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 2; + Row++ + ) { + PrintCharAt (gScreenDimensions.LeftColumn, Row, Character); + PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character); + } + + Character = BOXDRAW_UP_RIGHT; + PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1, Character); + + PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer); + + Character = BOXDRAW_UP_LEFT; + PrintCharAt ((UINTN) -1, (UINTN) -1, Character); + } + + FreePool (Buffer); +} + +/** + Print the form title. + + @param[in] FormData Form Data to be shown in Page + +**/ +VOID +PrintFormTitle ( + IN FORM_DISPLAY_ENGINE_FORM *FormData + ) +{ + CHAR16 *TitleStr; + + if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) != FORMSET_CLASS_PLATFORM_SETUP) { + // + // Only Setup Page need Title. + // + return; + } + + TitleStr = LibGetToken (FormData->FormTitle, FormData->HiiHandle); + ASSERT (TitleStr != NULL); + + gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND); + + ClearLines ( + gScreenDimensions.LeftColumn + 1, + gScreenDimensions.RightColumn - 1, + gScreenDimensions.TopRow + 1, + gScreenDimensions.TopRow + 1, + TITLE_TEXT | TITLE_BACKGROUND + ); + + PrintStringAt ( + (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - LibGetStringWidth (TitleStr) / 2) / 2, + gScreenDimensions.TopRow + 1, + TitleStr + ); + + FreePool (TitleStr); +} + +/** + Process some op code which is not recognized by browser core. + + @param OpCodeData The pointer to the op code buffer. + + @return EFI_SUCCESS Pass the statement success. + +**/ +VOID +ProcessUserOpcode( + IN EFI_IFR_OP_HEADER *OpCodeData + ) +{ + switch (OpCodeData->OpCode) { + case EFI_IFR_GUID_OP: + if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)((CHAR8*) OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) { + // + // Tiano specific GUIDed opcodes + // + switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) { + case EFI_IFR_EXTEND_OP_LABEL: + // + // just ignore label + // + break; + + case EFI_IFR_EXTEND_OP_BANNER: + // + // Only in front page form set, we care about the banner data. + // + if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) { + // + // Initialize Driver private data + // + if (gBannerData == NULL) { + gBannerData = AllocateZeroPool (sizeof (BANNER_DATA)); + ASSERT (gBannerData != NULL); + } + + CopyMem ( + &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][ + ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment], + &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title, + sizeof (EFI_STRING_ID) + ); + } + break; + + case EFI_IFR_EXTEND_OP_SUBCLASS: + if (((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass == EFI_FRONT_PAGE_SUBCLASS) { + gClassOfVfr = FORMSET_CLASS_FRONT_PAGE; + } + break; + + default: + break; + } + } + break; + + default: + break; + } +} + +/** + Process some op codes which is out side of current form. + + @param FormData Pointer to the form data. + + @return EFI_SUCCESS Pass the statement success. + +**/ +VOID +ProcessExternedOpcode ( + IN FORM_DISPLAY_ENGINE_FORM *FormData + ) +{ + LIST_ENTRY *Link; + FORM_DISPLAY_ENGINE_STATEMENT *Statement; + + Link = GetFirstNode (&FormData->StatementListOSF); + while (!IsNull (&FormData->StatementListOSF, Link)) { + Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link); + Link = GetNextNode (&FormData->StatementListOSF, Link); + + ProcessUserOpcode(Statement->OpCode); + } + + Link = GetFirstNode (&FormData->StatementListHead); + while (!IsNull (&FormData->StatementListHead, Link)) { + Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link); + Link = GetNextNode (&FormData->StatementListHead, Link); + + ProcessUserOpcode(Statement->OpCode); + } +} + +/** + Validate the input screen diemenstion info. + + @param FormData The input form data info. + + @return EFI_SUCCESS The input screen info is acceptable. + @return EFI_INVALID_PARAMETER The input screen info is not acceptable. + +**/ +EFI_STATUS +ScreenDiemensionInfoValidate ( + IN FORM_DISPLAY_ENGINE_FORM *FormData + ) +{ + LIST_ENTRY *Link; + UINTN Index; + + // + // Calculate total number of Register HotKeys. + // + Index = 0; + if (!IsListEmpty (&FormData->HotKeyListHead)){ + Link = GetFirstNode (&FormData->HotKeyListHead); + while (!IsNull (&FormData->HotKeyListHead, Link)) { + Link = GetNextNode (&FormData->HotKeyListHead, Link); + Index ++; + } + } + + // + // Show three HotKeys help information on one row. + // + gFooterHeight = FOOTER_HEIGHT + (Index / 3); + + + ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + gST->ConOut->QueryMode ( + gST->ConOut, + gST->ConOut->Mode->Mode, + &gScreenDimensions.RightColumn, + &gScreenDimensions.BottomRow + ); + + // + // Check local dimension vs. global dimension. + // + if (FormData->ScreenDimensions != NULL) { + if ((gScreenDimensions.RightColumn < FormData->ScreenDimensions->RightColumn) || + (gScreenDimensions.BottomRow < FormData->ScreenDimensions->BottomRow) + ) { + return EFI_INVALID_PARAMETER; + } else { + // + // Local dimension validation. + // + if ((FormData->ScreenDimensions->RightColumn > FormData->ScreenDimensions->LeftColumn) && + (FormData->ScreenDimensions->BottomRow > FormData->ScreenDimensions->TopRow) && + ((FormData->ScreenDimensions->RightColumn - FormData->ScreenDimensions->LeftColumn) > 2) && + ((FormData->ScreenDimensions->BottomRow - FormData->ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT + + FRONT_PAGE_HEADER_HEIGHT + gFooterHeight + 3)) { + CopyMem (&gScreenDimensions, (VOID *) FormData->ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + } else { + return EFI_INVALID_PARAMETER; + } + } + } + + return EFI_SUCCESS; +} + +/** + Get the string based on the StringId and HII Package List Handle. + + @param Token The String's ID. + @param HiiHandle The package list in the HII database to search for + the specified string. + + @return The output string. + +**/ +CHAR16 * +LibGetToken ( + IN EFI_STRING_ID Token, + IN EFI_HII_HANDLE HiiHandle + ) +{ + EFI_STRING String; + + String = HiiGetString (HiiHandle, Token, NULL); + if (String == NULL) { + String = AllocateCopyPool (StrSize (mLibUnknownString), mLibUnknownString); + ASSERT (String != NULL); + } + + return (CHAR16 *) String; +} + + +/** + Count the storage space of a Unicode string. + + This function handles the Unicode string with NARROW_CHAR + and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR + does not count in the resultant output. If a WIDE_CHAR is + hit, then 2 Unicode character will consume an output storage + space with size of CHAR16 till a NARROW_CHAR is hit. + + If String is NULL, then ASSERT (). + + @param String The input string to be counted. + + @return Storage space for the input string. + +**/ +UINTN +LibGetStringWidth ( + IN CHAR16 *String + ) +{ + UINTN Index; + UINTN Count; + UINTN IncrementValue; + + ASSERT (String != NULL); + if (String == NULL) { + return 0; + } + + Index = 0; + Count = 0; + IncrementValue = 1; + + do { + // + // Advance to the null-terminator or to the first width directive + // + for (; + (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0); + Index++, Count = Count + IncrementValue + ) + ; + + // + // We hit the null-terminator, we now have a count + // + if (String[Index] == 0) { + break; + } + // + // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed + // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2) + // + if (String[Index] == NARROW_CHAR) { + // + // Skip to the next character + // + Index++; + IncrementValue = 1; + } else { + // + // Skip to the next character + // + Index++; + IncrementValue = 2; + } + } while (String[Index] != 0); + + // + // Increment by one to include the null-terminator in the size + // + Count++; + + return Count * sizeof (CHAR16); +} + +/** + Show all registered HotKey help strings on bottom Rows. + + @param FormData The curent input form data info. + +**/ +VOID +PrintHotKeyHelpString ( + IN FORM_DISPLAY_ENGINE_FORM *FormData + ) +{ + UINTN CurrentCol; + UINTN CurrentRow; + UINTN BottomRowOfHotKeyHelp; + UINTN ColumnWidth; + UINTN Index; + EFI_SCREEN_DESCRIPTOR LocalScreen; + LIST_ENTRY *Link; + BROWSER_HOT_KEY *HotKey; + + if (IsListEmpty (&FormData->HotKeyListHead)) { + return; + } + + CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3; + BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3; + + // + // Calculate total number of Register HotKeys. + // + Index = 0; + Link = GetFirstNode (&FormData->HotKeyListHead); + while (!IsNull (&FormData->HotKeyListHead, Link)) { + HotKey = BROWSER_HOT_KEY_FROM_LINK (Link); + // + // Help string can't exceed ColumnWidth. One Row will show three Help information. + // + if (StrLen (HotKey->HelpString) > ColumnWidth) { + HotKey->HelpString[ColumnWidth] = L'\0'; + } + // + // Calculate help information Column and Row. + // + if ((Index % 3) != 2) { + CurrentCol = LocalScreen.LeftColumn + (2 - Index % 3) * ColumnWidth; + } else { + CurrentCol = LocalScreen.LeftColumn + 2; + } + CurrentRow = BottomRowOfHotKeyHelp - Index / 3; + // + // Print HotKey help string on bottom Row. + // + PrintStringAt (CurrentCol, CurrentRow, HotKey->HelpString); + + // + // Get Next Hot Key. + // + Link = GetNextNode (&FormData->HotKeyListHead, Link); + Index ++; + } + + return; +} + +/** + Get step info from numeric opcode. + + @param[in] OpCode The input numeric op code. + + @return step info for this opcode. +**/ +UINT64 +LibGetFieldFromNum ( + IN EFI_IFR_OP_HEADER *OpCode + ) +{ + EFI_IFR_NUMERIC *NumericOp; + UINT64 Step; + + NumericOp = (EFI_IFR_NUMERIC *) OpCode; + + switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) { + case EFI_IFR_NUMERIC_SIZE_1: + Step = NumericOp->data.u8.Step; + break; + + case EFI_IFR_NUMERIC_SIZE_2: + Step = NumericOp->data.u16.Step; + break; + + case EFI_IFR_NUMERIC_SIZE_4: + Step = NumericOp->data.u32.Step; + break; + + case EFI_IFR_NUMERIC_SIZE_8: + Step = NumericOp->data.u64.Step; + break; + + default: + Step = 0; + break; + } + + return Step; +} + +/** + Initialize the HII String Token to the correct values. + +**/ +VOID +InitializeLibStrings ( + VOID + ) +{ + mLibUnknownString = L"!"; + + gEnterString = LibGetToken (STRING_TOKEN (ENTER_STRING), mCDLStringPackHandle); + gEnterCommitString = LibGetToken (STRING_TOKEN (ENTER_COMMIT_STRING), mCDLStringPackHandle); + gEnterEscapeString = LibGetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), mCDLStringPackHandle); + gEscapeString = LibGetToken (STRING_TOKEN (ESCAPE_STRING), mCDLStringPackHandle); + gMoveHighlight = LibGetToken (STRING_TOKEN (MOVE_HIGHLIGHT), mCDLStringPackHandle); + gDecNumericInput = LibGetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), mCDLStringPackHandle); + gHexNumericInput = LibGetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), mCDLStringPackHandle); + gToggleCheckBox = LibGetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), mCDLStringPackHandle); + + gAreYouSure = LibGetToken (STRING_TOKEN (ARE_YOU_SURE), mCDLStringPackHandle); + gYesResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_YES), mCDLStringPackHandle); + gNoResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_NO), mCDLStringPackHandle); + gPlusString = LibGetToken (STRING_TOKEN (PLUS_STRING), mCDLStringPackHandle); + gMinusString = LibGetToken (STRING_TOKEN (MINUS_STRING), mCDLStringPackHandle); + gAdjustNumber = LibGetToken (STRING_TOKEN (ADJUST_NUMBER), mCDLStringPackHandle); + gSaveChanges = LibGetToken (STRING_TOKEN (SAVE_CHANGES), mCDLStringPackHandle); + + gLibEmptyString = LibGetToken (STRING_TOKEN (EMPTY_STRING), mCDLStringPackHandle); + + gNvUpdateMessage = LibGetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), mCDLStringPackHandle); + gInputErrorMessage = LibGetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), mCDLStringPackHandle); + + // + // SpaceBuffer; + // + mSpaceBuffer = AllocatePool ((SPACE_BUFFER_SIZE + 1) * sizeof (CHAR16)); + ASSERT (mSpaceBuffer != NULL); + LibSetUnicodeMem (mSpaceBuffer, SPACE_BUFFER_SIZE, L' '); + mSpaceBuffer[SPACE_BUFFER_SIZE] = L'\0'; +} + + +/** + Free the HII String. + +**/ +VOID +FreeLibStrings ( + VOID + ) +{ + FreePool (gEnterString); + FreePool (gEnterCommitString); + FreePool (gEnterEscapeString); + FreePool (gEscapeString); + FreePool (gMoveHighlight); + FreePool (gDecNumericInput); + FreePool (gHexNumericInput); + FreePool (gToggleCheckBox); + + FreePool (gAreYouSure); + FreePool (gYesResponse); + FreePool (gNoResponse); + FreePool (gPlusString); + FreePool (gMinusString); + FreePool (gAdjustNumber); + FreePool (gSaveChanges); + + FreePool (gLibEmptyString); + + FreePool (gNvUpdateMessage); + FreePool (gInputErrorMessage); + + FreePool (mSpaceBuffer); +} + +/** + Wait for a key to be pressed by user. + + @param Key The key which is pressed by user. + + @retval EFI_SUCCESS The function always completed successfully. + +**/ +EFI_STATUS +WaitForKeyStroke ( + OUT EFI_INPUT_KEY *Key + ) +{ + EFI_STATUS Status; + UINTN Index; + + while (TRUE) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key); + if (!EFI_ERROR (Status)) { + break; + } + + if (Status != EFI_NOT_READY) { + continue; + } + + gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index); + } + return Status; +} + + +/** + Set Buffer to Value for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + +**/ +VOID +LibSetUnicodeMem ( + IN VOID *Buffer, + IN UINTN Size, + IN CHAR16 Value + ) +{ + CHAR16 *Ptr; + + Ptr = Buffer; + while ((Size--) != 0) { + *(Ptr++) = Value; + } +} + +/** + The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL + protocol instance. + + @param Width Width of string to be print. + @param Column The position of the output string. + @param Row The position of the output string. + @param Out The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param Fmt The format string. + @param Args The additional argument for the variables in the format string. + + @return Number of Unicode character printed. + +**/ +UINTN +PrintInternal ( + IN UINTN Width, + IN UINTN Column, + IN UINTN Row, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out, + IN CHAR16 *Fmt, + IN VA_LIST Args + ) +{ + CHAR16 *Buffer; + CHAR16 *BackupBuffer; + UINTN Index; + UINTN PreviousIndex; + UINTN Count; + UINTN PrintWidth; + UINTN CharWidth; + + // + // For now, allocate an arbitrarily long buffer + // + Buffer = AllocateZeroPool (0x10000); + BackupBuffer = AllocateZeroPool (0x10000); + ASSERT (Buffer); + ASSERT (BackupBuffer); + + if (Column != (UINTN) -1) { + Out->SetCursorPosition (Out, Column, Row); + } + + UnicodeVSPrint (Buffer, 0x10000, Fmt, Args); + + Out->Mode->Attribute = Out->Mode->Attribute & 0x7f; + + Out->SetAttribute (Out, Out->Mode->Attribute); + + Index = 0; + PreviousIndex = 0; + Count = 0; + PrintWidth = 0; + CharWidth = 1; + + do { + for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) { + BackupBuffer[Index] = Buffer[Index]; + } + + if (Buffer[Index] == 0) { + break; + } + // + // Null-terminate the temporary string + // + BackupBuffer[Index] = 0; + + // + // Print this out, we are about to switch widths + // + Out->OutputString (Out, &BackupBuffer[PreviousIndex]); + Count += StrLen (&BackupBuffer[PreviousIndex]); + PrintWidth += Count * CharWidth; + + // + // Preserve the current index + 1, since this is where we will start printing from next + // + PreviousIndex = Index + 1; + + // + // We are at a narrow or wide character directive. Set attributes and strip it and print it + // + if (Buffer[Index] == NARROW_CHAR) { + // + // Preserve bits 0 - 6 and zero out the rest + // + Out->Mode->Attribute = Out->Mode->Attribute & 0x7f; + Out->SetAttribute (Out, Out->Mode->Attribute); + CharWidth = 1; + } else { + // + // Must be wide, set bit 7 ON + // + Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE; + Out->SetAttribute (Out, Out->Mode->Attribute); + CharWidth = 2; + } + + Index++; + + } while (Buffer[Index] != 0); + + // + // We hit the end of the string - print it + // + Out->OutputString (Out, &BackupBuffer[PreviousIndex]); + Count += StrLen (&BackupBuffer[PreviousIndex]); + PrintWidth += Count * CharWidth; + if (PrintWidth < Width) { + Out->Mode->Attribute = Out->Mode->Attribute & 0x7f; + Out->SetAttribute (Out, Out->Mode->Attribute); + Out->OutputString (Out, &mSpaceBuffer[SPACE_BUFFER_SIZE - Width + PrintWidth]); + } + + FreePool (Buffer); + FreePool (BackupBuffer); + return Count; +} + +/** + Prints a formatted unicode string to the default console, at + the supplied cursor position. + + @param Width Width of String to be printed. + @param Column The cursor position to print the string at. + @param Row The cursor position to print the string at. + @param Fmt Format string. + @param ... Variable argument list for format string. + + @return Length of string printed to the console + +**/ +UINTN +EFIAPI +PrintAt ( + IN UINTN Width, + IN UINTN Column, + IN UINTN Row, + IN CHAR16 *Fmt, + ... + ) +{ + VA_LIST Args; + UINTN LengthOfPrinted; + + VA_START (Args, Fmt); + LengthOfPrinted = PrintInternal (Width, Column, Row, gST->ConOut, Fmt, Args); + VA_END (Args); + return LengthOfPrinted; +} + -- cgit v1.2.3