mirror of https://github.com/acidanthera/audk.git
960 lines
28 KiB
C
960 lines
28 KiB
C
/** @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;
|
|
}
|
|
|