/** @file | |
This library class defines a set of interfaces to customize Display module | |
Copyright (c) 2013, Intel Corporation. All rights reserved.<BR> | |
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 and form title for a page. | |
@param[in] FormData Form Data to be shown in Page | |
**/ | |
VOID | |
PrintFramework ( | |
IN FORM_DISPLAY_ENGINE_FORM *FormData | |
) | |
{ | |
UINTN Index; | |
CHAR16 Character; | |
CHAR16 *Buffer; | |
UINTN Row; | |
CHAR16 *TitleStr; | |
UINTN TitleColumn; | |
if (gClassOfVfr != FORMSET_CLASS_PLATFORM_SETUP) { | |
// | |
// Only Setup page needs Framework | |
// | |
ClearLines ( | |
gScreenDimensions.LeftColumn, | |
gScreenDimensions.RightColumn, | |
gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, | |
gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1, | |
KEYHELP_TEXT | KEYHELP_BACKGROUND | |
); | |
return; | |
} | |
Buffer = AllocateZeroPool (0x10000); | |
ASSERT (Buffer != NULL); | |
Character = BOXDRAW_HORIZONTAL; | |
for (Index = 0; Index + 2 < (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn); Index++) { | |
Buffer[Index] = Character; | |
} | |
// | |
// Print Top border line | |
// +------------------------------------------------------------------------------+ | |
// ? ? | |
// +------------------------------------------------------------------------------+ | |
// | |
gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND); | |
Character = BOXDRAW_DOWN_RIGHT; | |
PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow, 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); | |
} | |
// | |
// Print Form Title | |
// | |
TitleStr = LibGetToken (FormData->FormTitle, FormData->HiiHandle); | |
ASSERT (TitleStr != NULL); | |
TitleColumn = (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - LibGetStringWidth (TitleStr) / 2) / 2; | |
PrintStringAtWithWidth (gScreenDimensions.LeftColumn + 1, gScreenDimensions.TopRow + 1, gLibEmptyString, TitleColumn - gScreenDimensions.LeftColumn - 1); | |
PrintStringAtWithWidth ( | |
TitleColumn, | |
gScreenDimensions.TopRow + 1, | |
TitleStr, | |
gScreenDimensions.RightColumn - 1 - TitleColumn | |
); | |
FreePool (TitleStr); | |
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); | |
} | |
/** | |
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) { | |
// | |
// 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; | |
LIST_ENTRY *NestLink; | |
FORM_DISPLAY_ENGINE_STATEMENT *Statement; | |
FORM_DISPLAY_ENGINE_STATEMENT *NestStatement; | |
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); | |
NestLink = GetFirstNode (&Statement->NestStatementList); | |
while (!IsNull (&Statement->NestStatementList, NestLink)) { | |
NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink); | |
NestLink = GetNextNode (&Statement->NestStatementList, NestLink); | |
ProcessUserOpcode(NestStatement->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. | |
@param SetState Set HotKey or Clear HotKey | |
**/ | |
VOID | |
PrintHotKeyHelpString ( | |
IN FORM_DISPLAY_ENGINE_FORM *FormData, | |
IN BOOLEAN SetState | |
) | |
{ | |
UINTN CurrentCol; | |
UINTN CurrentRow; | |
UINTN BottomRowOfHotKeyHelp; | |
UINTN ColumnIndexWidth; | |
UINTN ColumnWidth; | |
UINTN ColumnIndex; | |
UINTN Index; | |
EFI_SCREEN_DESCRIPTOR LocalScreen; | |
LIST_ENTRY *Link; | |
BROWSER_HOT_KEY *HotKey; | |
CHAR16 BakChar; | |
CHAR16 *ColumnStr; | |
CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); | |
ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3; | |
BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3; | |
ColumnStr = gLibEmptyString; | |
// | |
// Calculate total number of Register HotKeys. | |
// | |
Index = 0; | |
Link = GetFirstNode (&FormData->HotKeyListHead); | |
while (!IsNull (&FormData->HotKeyListHead, Link)) { | |
HotKey = BROWSER_HOT_KEY_FROM_LINK (Link); | |
// | |
// Calculate help information Column and Row. | |
// | |
ColumnIndex = Index % 3; | |
if (ColumnIndex == 0) { | |
CurrentCol = LocalScreen.LeftColumn + 2 * ColumnWidth; | |
ColumnIndexWidth = ColumnWidth - 1; | |
} else if (ColumnIndex == 1) { | |
CurrentCol = LocalScreen.LeftColumn + ColumnWidth; | |
ColumnIndexWidth = ColumnWidth; | |
} else { | |
CurrentCol = LocalScreen.LeftColumn + 2; | |
ColumnIndexWidth = ColumnWidth - 2; | |
} | |
CurrentRow = BottomRowOfHotKeyHelp - Index / 3; | |
// | |
// Help string can't exceed ColumnWidth. One Row will show three Help information. | |
// | |
BakChar = L'\0'; | |
if (StrLen (HotKey->HelpString) > ColumnIndexWidth) { | |
BakChar = HotKey->HelpString[ColumnIndexWidth]; | |
HotKey->HelpString[ColumnIndexWidth] = L'\0'; | |
} | |
// | |
// Print HotKey help string on bottom Row. | |
// | |
if (SetState) { | |
ColumnStr = HotKey->HelpString; | |
} | |
PrintStringAtWithWidth (CurrentCol, CurrentRow, ColumnStr, ColumnIndexWidth); | |
if (BakChar != L'\0') { | |
HotKey->HelpString[ColumnIndexWidth] = BakChar; | |
} | |
// | |
// Get Next Hot Key. | |
// | |
Link = GetNextNode (&FormData->HotKeyListHead, Link); | |
Index ++; | |
} | |
if (SetState) { | |
// | |
// Clear KeyHelp | |
// | |
CurrentRow = BottomRowOfHotKeyHelp - Index / 3; | |
ColumnIndex = Index % 3; | |
if (ColumnIndex == 0) { | |
CurrentCol = LocalScreen.LeftColumn + 2 * ColumnWidth; | |
ColumnIndexWidth = ColumnWidth - 1; | |
ColumnIndex ++; | |
PrintStringAtWithWidth (CurrentCol, CurrentRow, gLibEmptyString, ColumnIndexWidth); | |
} | |
if (ColumnIndex == 1) { | |
CurrentCol = LocalScreen.LeftColumn + ColumnWidth; | |
ColumnIndexWidth = ColumnWidth; | |
PrintStringAtWithWidth (CurrentCol, CurrentRow, gLibEmptyString, ColumnIndexWidth); | |
} | |
} | |
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 TotalCount; | |
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; | |
TotalCount = 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; | |
} | |
// | |
// Print this out, we are about to switch widths | |
// | |
Out->OutputString (Out, &BackupBuffer[PreviousIndex]); | |
Count = StrLen (&BackupBuffer[PreviousIndex]); | |
PrintWidth += Count * CharWidth; | |
TotalCount += Count; | |
// | |
// 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; | |
TotalCount += Count; | |
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 TotalCount; | |
} | |
/** | |
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; | |
} | |