ui.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,158 行 · 第 1/5 页
C
2,158 行
)
/*++
Routine Description:
Add one menu option by specified description and context.
Arguments:
String - String description for this option.
Context - Context data for entry.
Returns:
--*/
{
UI_MENU_OPTION *MenuOption;
MenuOption = EfiLibAllocateZeroPool (sizeof (UI_MENU_OPTION));
ASSERT (MenuOption);
MenuOption->Signature = UI_MENU_OPTION_SIGNATURE;
MenuOption->Description = String;
MenuOption->Handle = Handle;
MenuOption->Skip = Tags[TagIndex].NumberOfLines;
MenuOption->IfrNumber = gActiveIfr;
MenuOption->Tags = Tags;
MenuOption->TagIndex = TagIndex;
MenuOption->ThisTag = &(MenuOption->Tags[MenuOption->TagIndex]);
MenuOption->Consistency = Tags[TagIndex].Consistency;
MenuOption->FormId = FormId;
MenuOption->GrayOut = Tags[TagIndex].GrayOut;
MenuOption->EntryNumber = MenuItemCount;
InsertTailList (&Menu, &MenuOption->Link);
}
EFI_STATUS
CreateDialog (
IN UINTN NumberOfLines,
IN BOOLEAN HotKey,
IN UINTN MaximumStringSize,
OUT CHAR16 *StringBuffer,
OUT EFI_INPUT_KEY *KeyValue,
IN CHAR16 *String,
...
)
/*++
Routine Description:
Routine used to abstract a generic dialog interface and return the selected key or string
Arguments:
NumberOfLines - The number of lines for the dialog box
HotKey - Defines whether a single character is parsed (TRUE) and returned in KeyValue
or a string is returned in StringBuffer. Two special characters are considered when entering a string, a SCAN_ESC and
an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates string input and returns
MaximumStringSize - The maximum size in bytes of a typed in string (each character is a CHAR16) and the minimum string returned is two bytes
StringBuffer - The passed in pointer to the buffer which will hold the typed in string if HotKey is FALSE
KeyValue - The EFI_KEY value returned if HotKey is TRUE..
String - Pointer to the first string in the list
... - A series of (quantity == NumberOfLines) text strings which will be used to construct the dialog box
Returns:
EFI_SUCCESS - Displayed dialog and received user interaction
EFI_INVALID_PARAMETER - One of the parameters was invalid (e.g. (StringBuffer == NULL) && (HotKey == FALSE))
EFI_DEVICE_ERROR - User typed in an ESC character to exit the routine
--*/
{
VA_LIST Marker;
UINTN Count;
EFI_INPUT_KEY Key;
UINTN LargestString;
CHAR16 *TempString;
CHAR16 *BufferedString;
CHAR16 *StackString;
CHAR16 KeyPad[2];
UINTN Start;
UINTN Top;
UINTN Index;
EFI_STATUS Status;
BOOLEAN SelectionComplete;
UINTN InputOffset;
UINTN CurrentAttribute;
UINTN DimensionsWidth;
UINTN DimensionsHeight;
DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
SelectionComplete = FALSE;
InputOffset = 0;
TempString = EfiLibAllocateZeroPool (MaximumStringSize * 2);
BufferedString = EfiLibAllocateZeroPool (MaximumStringSize * 2);
CurrentAttribute = gST->ConOut->Mode->Attribute;
ASSERT (TempString);
ASSERT (BufferedString);
VA_START (Marker, String);
//
// Zero the outgoing buffer
//
EfiZeroMem (StringBuffer, MaximumStringSize);
if (HotKey) {
if (KeyValue == NULL) {
return EFI_INVALID_PARAMETER;
}
} else {
if (StringBuffer == NULL) {
return EFI_INVALID_PARAMETER;
}
}
//
// Disable cursor
//
gST->ConOut->EnableCursor (gST->ConOut, FALSE);
LargestString = (GetStringWidth (String) / 2);
if (LargestString == L' ') {
InputOffset = 1;
}
//
// Determine the largest string in the dialog box
// Notice we are starting with 1 since String is the first string
//
for (Count = 1; Count < NumberOfLines; Count++) {
StackString = VA_ARG (Marker, CHAR16 *);
if (StackString[0] == L' ') {
InputOffset = Count + 1;
}
if ((GetStringWidth (StackString) / 2) > LargestString) {
//
// Size of the string visually and subtract the width by one for the null-terminator
//
LargestString = (GetStringWidth (StackString) / 2);
}
}
Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;
Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
Count = 0;
//
// Display the Popup
//
CreateSharedPopUp (LargestString, NumberOfLines, &String);
//
// Take the first key typed and report it back?
//
if (HotKey) {
Status = WaitForKeyStroke (&Key);
EfiCopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));
} else {
do {
Status = WaitForKeyStroke (&Key);
switch (Key.UnicodeChar) {
case CHAR_NULL:
switch (Key.ScanCode) {
case SCAN_ESC:
gBS->FreePool (TempString);
gBS->FreePool (BufferedString);
gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
gST->ConOut->EnableCursor (gST->ConOut, TRUE);
return EFI_DEVICE_ERROR;
default:
break;
}
break;
case CHAR_CARRIAGE_RETURN:
SelectionComplete = TRUE;
gBS->FreePool (TempString);
gBS->FreePool (BufferedString);
gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
gST->ConOut->EnableCursor (gST->ConOut, TRUE);
return EFI_SUCCESS;
break;
case CHAR_BACKSPACE:
if (StringBuffer[0] != CHAR_NULL) {
for (Index = 0; StringBuffer[Index] != CHAR_NULL; Index++) {
TempString[Index] = StringBuffer[Index];
}
//
// Effectively truncate string by 1 character
//
TempString[Index - 1] = CHAR_NULL;
EfiStrCpy (StringBuffer, TempString);
}
default:
//
// If it is the beginning of the string, don't worry about checking maximum limits
//
if ((StringBuffer[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
StrnCpy (StringBuffer, &Key.UnicodeChar, 1);
StrnCpy (TempString, &Key.UnicodeChar, 1);
} else if ((GetStringWidth (StringBuffer) < MaximumStringSize) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
KeyPad[0] = Key.UnicodeChar;
KeyPad[1] = CHAR_NULL;
EfiStrCat (StringBuffer, KeyPad);
EfiStrCat (TempString, KeyPad);
}
//
// If the width of the input string is now larger than the screen, we nee to
// adjust the index to start printing portions of the string
//
SetUnicodeMem (BufferedString, LargestString, L' ');
PrintStringAt (Start + 1, Top + InputOffset, BufferedString);
if ((GetStringWidth (StringBuffer) / 2) > (DimensionsWidth - 2)) {
Index = (GetStringWidth (StringBuffer) / 2) - DimensionsWidth + 2;
} else {
Index = 0;
}
for (Count = 0; Index + 1 < GetStringWidth (StringBuffer) / 2; Index++, Count++) {
BufferedString[Count] = StringBuffer[Index];
}
PrintStringAt (Start + 1, Top + InputOffset, BufferedString);
break;
}
} while (!SelectionComplete);
}
gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
gST->ConOut->EnableCursor (gST->ConOut, TRUE);
return EFI_SUCCESS;
}
VOID
CreateSharedPopUp (
IN UINTN RequestedWidth,
IN UINTN NumberOfLines,
IN CHAR16 **ArrayOfStrings
)
{
UINTN Index;
UINTN Count;
CHAR16 Character;
UINTN Start;
UINTN End;
UINTN Top;
UINTN Bottom;
CHAR16 *String;
UINTN DimensionsWidth;
UINTN DimensionsHeight;
DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
Count = 0;
gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
if ((RequestedWidth + 2) > DimensionsWidth) {
RequestedWidth = DimensionsWidth - 2;
}
//
// Subtract the PopUp width from total Columns, allow for one space extra on
// each end plus a border.
//
Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1;
End = Start + RequestedWidth + 1;
Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
Bottom = Top + NumberOfLines + 2;
Character = BOXDRAW_DOWN_RIGHT;
PrintCharAt (Start, Top, Character);
Character = BOXDRAW_HORIZONTAL;
for (Index = Start; Index + 2 < End; Index++) {
PrintChar (Character);
}
Character = BOXDRAW_DOWN_LEFT;
PrintChar (Character);
Character = BOXDRAW_VERTICAL;
for (Index = Top; Index + 2 < Bottom; Index++) {
String = ArrayOfStrings[Count];
Count++;
//
// This will clear the background of the line - we never know who might have been
// here before us. This differs from the next clear in that it used the non-reverse
// video for normal printing.
//
if (GetStringWidth (String) / 2 > 1) {
ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);
}
//
// Passing in a space results in the assumption that this is where typing will occur
//
if (String[0] == L' ') {
ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);
}
//
// Passing in a NULL results in a blank space
//
if (String[0] == CHAR_NULL) {
ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);
}
PrintStringAt (
((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
Index + 1,
String
);
gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
PrintCharAt (Start, Index + 1, Character);
PrintCharAt (End - 1, Index + 1, Character);
}
Character = BOXDRAW_UP_RIGHT;
PrintCharAt (Start, Bottom - 1, Character);
Character = BOXDRAW_HORIZONTAL;
for (Index = Start; Index + 2 < End; Index++) {
PrintChar (Character);
}
Character = BOXDRAW_UP_LEFT;
PrintChar (Character);
}
VOID
CreatePopUp (
IN UINTN RequestedWidth,
IN UINTN NumberOfLines,
IN CHAR16 *ArrayOfStrings,
...
)
{
CreateSharedPopUp (RequestedWidth, NumberOfLines, &ArrayOfStrings);
}
VOID
UpdateStatusBar (
IN UINTN MessageType,
IN UINT8 Flags,
IN BOOLEAN State
)
{
UINTN Index;
STATIC BOOLEAN InputError;
CHAR16 *NvUpdateMessage;
CHAR16 *InputErrorMessage;
NvUpdateMessage = GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), gHiiHandle);
InputErrorMessage = GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), gHiiHandle);
switch (MessageType) {
case INPUT_ERROR:
if (State) {
gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);
PrintStringAt (
gScreenDimensions.LeftColumn + gPromptBlockWidth,
gScreenDimensions.BottomRow - 1,
InputErrorMessage
);
InputError = TRUE;
} else {
gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);
for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) {
PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, L" ");
}
InputError = FALSE;
}
break;
case NV_UPDATE_REQUIRED:
if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
if (State) {
gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);
PrintStringAt (
gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth,
gScreenDimensions.BottomRow - 1,
NvUpdateMessage
);
gResetRequired = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED));
gNvUpdateRequired = TRUE;
} else {
gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT);
for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {
PrintAt (
(gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index),
gScreenDimensions.BottomRow - 1,
L" "
);
}
gNvUpdateRequired = FALSE;
}
}
break;
case REFRESH_STATUS_BAR:
if (InputError) {
UpdateStatusBar (INPUT_ERROR, Flags, TRUE);
}
if (gNvUpdateRequired) {
UpdateStatusBar (NV_UPDATE_REQUIRED, Flags, TRUE);
}
break;
default:
break;
}
gBS->FreePool (InputErrorMessage);
gBS->FreePool (NvUpdateMessage);
return ;
}
VOID
FreeData (
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?