X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=EdkModulePkg%2FUniversal%2FUserInterface%2FSetupBrowser%2FDxe%2FUi.c;fp=EdkModulePkg%2FUniversal%2FUserInterface%2FSetupBrowser%2FDxe%2FUi.c;h=0000000000000000000000000000000000000000;hb=808def96aa4589fba9c2d0ea55837754a3b7a4f7;hp=3d30c1bd2def0396919ddb2e124467b01d9e95c8;hpb=9216450d1143056a50a5f916984a2d7faf590488;p=mirror_edk2.git diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Ui.c b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Ui.c deleted file mode 100644 index 3d30c1bd2d..0000000000 --- a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Ui.c +++ /dev/null @@ -1,3150 +0,0 @@ -/**@file - Implementation for UI. - -Copyright (c) 2006 - 2007, 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 -which 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 "Setup.h" -#include "Ui.h" -#include "Colors.h" - -// -// Implementation -// -VOID -SetUnicodeMem ( - IN VOID *Buffer, - IN UINTN Size, - IN CHAR16 Value - ) -/*++ - -Routine Description: - - Set Buffer to Value for Size bytes. - -Arguments: - - Buffer - Memory to set. - - Size - Number of bytes to set - - Value - Value of the set operation. - -Returns: - - None - ---*/ -{ - CHAR16 *Ptr; - - Ptr = Buffer; - while (Size--) { - *(Ptr++) = Value; - } -} - -VOID -UiInitMenu ( - VOID - ) -/*++ - -Routine Description: - Initialize Menu option list. - -Arguments: - -Returns: - ---*/ -{ - InitializeListHead (&Menu); -} - -VOID -UiInitMenuList ( - VOID - ) -/*++ - -Routine Description: - Initialize Menu option list. - -Arguments: - -Returns: - ---*/ -{ - InitializeListHead (&gMenuList); -} - -VOID -UiRemoveMenuListEntry ( - IN UI_MENU_OPTION *Selection, - OUT UI_MENU_OPTION **PreviousSelection - ) -/*++ - -Routine Description: - Remove Menu option list. - -Arguments: - -Returns: - ---*/ -{ - UI_MENU_LIST *UiMenuList; - - *PreviousSelection = AllocateZeroPool (sizeof (UI_MENU_OPTION)); - ASSERT (*PreviousSelection != NULL); - - if (!IsListEmpty (&gMenuList)) { - UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE); - (*PreviousSelection)->IfrNumber = UiMenuList->Selection.IfrNumber; - (*PreviousSelection)->FormId = UiMenuList->Selection.FormId; - (*PreviousSelection)->Tags = UiMenuList->Selection.Tags; - (*PreviousSelection)->ThisTag = UiMenuList->Selection.ThisTag; - (*PreviousSelection)->Handle = UiMenuList->Selection.Handle; - gEntryNumber = UiMenuList->FormerEntryNumber; - RemoveEntryList (&UiMenuList->MenuLink); - FreePool (UiMenuList); - } -} - -VOID -UiFreeMenuList ( - VOID - ) -/*++ - -Routine Description: - Free Menu option linked list. - -Arguments: - -Returns: - ---*/ -{ - UI_MENU_LIST *UiMenuList; - - while (!IsListEmpty (&gMenuList)) { - UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE); - RemoveEntryList (&UiMenuList->MenuLink); - FreePool (UiMenuList); - } -} - -VOID -UiAddMenuListEntry ( - IN UI_MENU_OPTION *Selection - ) -/*++ - -Routine Description: - Add one menu entry to the linked lst - -Arguments: - -Returns: - ---*/ -{ - UI_MENU_LIST *UiMenuList; - - UiMenuList = AllocateZeroPool (sizeof (UI_MENU_LIST)); - ASSERT (UiMenuList != NULL); - - UiMenuList->Signature = UI_MENU_LIST_SIGNATURE; - CopyMem (&UiMenuList->Selection, Selection, sizeof (UI_MENU_OPTION)); - - InsertHeadList (&gMenuList, &UiMenuList->MenuLink); -} - -VOID -UiFreeMenu ( - VOID - ) -/*++ - -Routine Description: - Free Menu option linked list. - -Arguments: - -Returns: - ---*/ -{ - UI_MENU_OPTION *MenuOption; - - while (!IsListEmpty (&Menu)) { - MenuOption = CR (Menu.ForwardLink, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - RemoveEntryList (&MenuOption->Link); - - // - // We allocated space for this description when we did a GetToken, free it here - // - FreePool (MenuOption->Description); - FreePool (MenuOption); - } -} - -STATIC -VOID -UpdateDateAndTime ( - VOID - ) -/*++ - -Routine Description: - Refresh screen with current date and/or time based on screen context - -Arguments: - -Returns: - ---*/ -{ - CHAR16 *OptionString; - MENU_REFRESH_ENTRY *MenuRefreshEntry; - UINTN Index; - UINTN Loop; - - OptionString = NULL; - - if (gMenuRefreshHead != NULL) { - - MenuRefreshEntry = gMenuRefreshHead; - - do { - gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute); - ProcessOptions (MenuRefreshEntry->MenuOption, FALSE, MenuRefreshEntry->FileFormTagsHead, NULL, &OptionString); - - if (OptionString != NULL) { - // - // If leading spaces on OptionString - remove the spaces - // - for (Index = 0; OptionString[Index] == L' '; Index++) - ; - - for (Loop = 0; OptionString[Index] != CHAR_NULL; Index++) { - OptionString[Loop] = OptionString[Index]; - Loop++; - } - - OptionString[Loop] = CHAR_NULL; - - PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString); - } - - MenuRefreshEntry = MenuRefreshEntry->Next; - - } while (MenuRefreshEntry != NULL); - } - - if (OptionString != NULL) { - FreePool (OptionString); - } -} - -EFI_STATUS -UiWaitForSingleEvent ( - IN EFI_EVENT Event, - IN UINT64 Timeout OPTIONAL - ) -/*++ - -Routine Description: - Wait for a given event to fire, or for an optional timeout to expire. - -Arguments: - Event - The event to wait for - - Timeout - An optional timeout value in 100 ns units. - -Returns: - - EFI_SUCCESS - Event fired before Timeout expired. - EFI_TIME_OUT - Timout expired before Event fired. - ---*/ -{ - EFI_STATUS Status; - UINTN Index; - EFI_EVENT TimerEvent; - EFI_EVENT WaitList[2]; - - if (Timeout) { - // - // Create a timer event - // - Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent); - if (!EFI_ERROR (Status)) { - // - // Set the timer event - // - gBS->SetTimer ( - TimerEvent, - TimerRelative, - Timeout - ); - - // - // Wait for the original event or the timer - // - WaitList[0] = Event; - WaitList[1] = TimerEvent; - Status = gBS->WaitForEvent (2, WaitList, &Index); - gBS->CloseEvent (TimerEvent); - - // - // If the timer expired, change the return to timed out - // - if (!EFI_ERROR (Status) && Index == 1) { - Status = EFI_TIMEOUT; - } - } - } else { - // - // Update screen every second - // - Timeout = ONE_SECOND; - - do { - Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent); - - // - // Set the timer event - // - gBS->SetTimer ( - TimerEvent, - TimerRelative, - Timeout - ); - - // - // Wait for the original event or the timer - // - WaitList[0] = Event; - WaitList[1] = TimerEvent; - Status = gBS->WaitForEvent (2, WaitList, &Index); - - // - // If the timer expired, update anything that needs a refresh and keep waiting - // - if (!EFI_ERROR (Status) && Index == 1) { - Status = EFI_TIMEOUT; - UpdateDateAndTime (); - } - - gBS->CloseEvent (TimerEvent); - } while (Status == EFI_TIMEOUT); - } - - return Status; -} - -VOID -UiAddMenuOption ( - IN CHAR16 *String, - IN EFI_HII_HANDLE Handle, - IN EFI_TAG *Tags, - IN VOID *FormBinary, - IN UINTN IfrNumber - ) -/*++ - -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 = AllocateZeroPool (sizeof (UI_MENU_OPTION)); - ASSERT (MenuOption); - - MenuOption->Signature = UI_MENU_OPTION_SIGNATURE; - MenuOption->Description = String; - MenuOption->Handle = Handle; - MenuOption->FormBinary = FormBinary; - MenuOption->IfrNumber = IfrNumber; - MenuOption->Skip = 1; - MenuOption->Tags = Tags; - MenuOption->TagIndex = 0; - MenuOption->ThisTag = &(MenuOption->Tags[MenuOption->TagIndex]); - MenuOption->EntryNumber = (UINT16) IfrNumber; - - InsertTailList (&Menu, &MenuOption->Link); -} - -VOID -UiAddSubMenuOption ( - IN CHAR16 *String, - IN EFI_HII_HANDLE Handle, - IN EFI_TAG *Tags, - IN UINTN TagIndex, - IN UINT16 FormId, - IN UINT16 MenuItemCount - ) -/*++ - -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 = AllocateZeroPool (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; - 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 = AllocateZeroPool (MaximumStringSize * 2); - BufferedString = AllocateZeroPool (MaximumStringSize * 2); - CurrentAttribute = gST->ConOut->Mode->Attribute; - - ASSERT (TempString); - ASSERT (BufferedString); - - VA_START (Marker, String); - - // - // Zero the outgoing buffer - // - ZeroMem (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) { - WaitForKeyStroke (&Key); - CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY)); - - } else { - do { - WaitForKeyStroke (&Key); - - switch (Key.UnicodeChar) { - case CHAR_NULL: - switch (Key.ScanCode) { - case SCAN_ESC: - FreePool (TempString); - 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; - FreePool (TempString); - 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; - StrCpy (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; - StrCat (StringBuffer, KeyPad); - StrCat (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 = (CHAR16) BOXDRAW_DOWN_RIGHT; - PrintCharAt (Start, Top, Character); - Character = (CHAR16) BOXDRAW_HORIZONTAL; - for (Index = Start; Index + 2 < End; Index++) { - PrintChar (Character); - } - - Character = (CHAR16) BOXDRAW_DOWN_LEFT; - PrintChar (Character); - Character = (CHAR16) 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 = (CHAR16) BOXDRAW_UP_RIGHT; - PrintCharAt (Start, Bottom - 1, Character); - Character = (CHAR16) BOXDRAW_HORIZONTAL; - for (Index = Start; Index + 2 < End; Index++) { - PrintChar (Character); - } - - Character = (CHAR16) 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, (CHAR16 *) 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, - (CHAR16 *) 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; - } - - FreePool (InputErrorMessage); - FreePool (NvUpdateMessage); - return ; -} - -VOID -FreeData ( - IN EFI_FILE_FORM_TAGS *FileFormTagsHead, - IN CHAR16 *FormattedString, - IN CHAR16 *OptionString - ) -/*++ - -Routine Description: - - Used to remove the allocated data instances - -Arguments: - -Returns: - ---*/ -{ - EFI_FILE_FORM_TAGS *FileForm; - EFI_FILE_FORM_TAGS *PreviousFileForm; - EFI_FORM_TAGS *FormTags; - EFI_FORM_TAGS *PreviousFormTags; - EFI_IFR_BINARY *IfrBinary; - EFI_IFR_BINARY *PreviousIfrBinary; - EFI_INCONSISTENCY_DATA *Inconsistent; - EFI_VARIABLE_DEFINITION *VariableDefinition; - EFI_VARIABLE_DEFINITION *PreviousVariableDefinition; - VOID *Buffer; - UINTN Index; - - FileForm = FileFormTagsHead; - - if (FormattedString != NULL) { - FreePool (FormattedString); - } - - if (OptionString != NULL) { - FreePool (OptionString); - } - - for (; FileForm != NULL;) { - PreviousFileForm = NULL; - - // - // Advance FileForm to the last entry - // - for (; FileForm->NextFile != NULL; FileForm = FileForm->NextFile) { - PreviousFileForm = FileForm; - } - - FormTags = &FileForm->FormTags; - - for (; FormTags != NULL;) { - FormTags = &FileForm->FormTags; - PreviousFormTags = NULL; - - // - // Advance FormTags to the last entry - // - for (; FormTags->Next != NULL; FormTags = FormTags->Next) { - PreviousFormTags = FormTags; - } - // - // Walk through each of the tags and free the IntList allocation - // - for (Index = 0; FormTags->Tags[Index].Operand != EFI_IFR_END_FORM_OP; Index++) { - // - // It is more than likely that the very last page will contain an end formset - // - if (FormTags->Tags[Index].Operand == EFI_IFR_END_FORM_SET_OP) { - break; - } - - if (FormTags->Tags[Index].IntList != NULL) { - FreePool (FormTags->Tags[Index].IntList); - } - } - - if (PreviousFormTags != NULL) { - FreePool (FormTags->Tags); - FormTags = PreviousFormTags; - FreePool (FormTags->Next); - FormTags->Next = NULL; - } else { - FreePool (FormTags->Tags); - FormTags = NULL; - } - } - // - // Last FileForm entry's Inconsistent database - // - Inconsistent = FileForm->InconsistentTags; - - // - // Advance Inconsistent to the last entry - // - for (; Inconsistent->Next != NULL; Inconsistent = Inconsistent->Next) - ; - - for (; Inconsistent != NULL;) { - // - // Preserve the Previous pointer - // - Buffer = (VOID *) Inconsistent->Previous; - - // - // Free the current entry - // - FreePool (Inconsistent); - - // - // Restore the Previous pointer - // - Inconsistent = (EFI_INCONSISTENCY_DATA *) Buffer; - } - - VariableDefinition = FileForm->VariableDefinitions; - - for (; VariableDefinition != NULL;) { - VariableDefinition = FileForm->VariableDefinitions; - PreviousVariableDefinition = NULL; - - // - // Advance VariableDefinitions to the last entry - // - for (; VariableDefinition->Next != NULL; VariableDefinition = VariableDefinition->Next) { - PreviousVariableDefinition = VariableDefinition; - } - - FreePool (VariableDefinition->VariableName); - - if (VariableDefinition->NvRamMap != NULL) { - FreePool (VariableDefinition->NvRamMap); - } - - if (VariableDefinition->FakeNvRamMap != NULL) { - FreePool (VariableDefinition->FakeNvRamMap); - } - - if (PreviousVariableDefinition != NULL) { - VariableDefinition = PreviousVariableDefinition; - FreePool (VariableDefinition->Next); - VariableDefinition->Next = NULL; - } else { - FreePool (VariableDefinition); - VariableDefinition = NULL; - } - } - - if (PreviousFileForm != NULL) { - FileForm = PreviousFileForm; - FreePool (FileForm->NextFile); - FileForm->NextFile = NULL; - } else { - FreePool (FileForm); - FileForm = NULL; - } - } - - IfrBinary = gBinaryDataHead; - - for (; IfrBinary != NULL;) { - IfrBinary = gBinaryDataHead; - PreviousIfrBinary = NULL; - - // - // Advance IfrBinary to the last entry - // - for (; IfrBinary->Next != NULL; IfrBinary = IfrBinary->Next) { - PreviousIfrBinary = IfrBinary; - } - - FreePool (IfrBinary->IfrPackage); - - if (PreviousIfrBinary != NULL) { - IfrBinary = PreviousIfrBinary; - FreePool (IfrBinary->Next); - IfrBinary->Next = NULL; - } else { - FreePool (IfrBinary); - IfrBinary = NULL; - } - } - - FreePool (gPreviousValue); - gPreviousValue = NULL; - - // - // Free Browser Strings - // - FreePool (gPressEnter); - FreePool (gConfirmError); - FreePool (gConfirmPassword); - FreePool (gPromptForNewPassword); - FreePool (gPromptForPassword); - FreePool (gToggleCheckBox); - FreePool (gNumericInput); - FreePool (gMakeSelection); - FreePool (gMoveHighlight); - FreePool (gEscapeString); - FreePool (gEnterCommitString); - FreePool (gEnterString); - FreePool (gFunctionOneString); - FreePool (gFunctionTwoString); - FreePool (gFunctionNineString); - FreePool (gFunctionTenString); - return ; -} - -STATIC -BOOLEAN -SelectionsAreValid ( - IN UI_MENU_OPTION *MenuOption, - IN EFI_FILE_FORM_TAGS *FileFormTagsHead - ) -/*++ - -Routine Description: - Initiate late consistency checks against the current page. - -Arguments: - None - -Returns: - ---*/ -{ - LIST_ENTRY *Link; - EFI_TAG *Tag; - EFI_FILE_FORM_TAGS *FileFormTags; - CHAR16 *StringPtr; - CHAR16 NullCharacter; - UINTN Index; - UINT16 *NvRamMap; - STRING_REF PopUp; - EFI_INPUT_KEY Key; - EFI_VARIABLE_DEFINITION *VariableDefinition; - - StringPtr = (CHAR16 *) L"\0"; - NullCharacter = CHAR_NULL; - - FileFormTags = FileFormTagsHead; - - for (Index = 0; Index < MenuOption->IfrNumber; Index++) { - FileFormTags = FileFormTags->NextFile; - } - - for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) { - MenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - - Tag = MenuOption->ThisTag; - - ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition); - NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart]; - - // - // If the op-code has a late check, ensure consistency checks are now applied - // - if (Tag->Flags & EFI_IFR_FLAG_LATE_CHECK) { - if (ValueIsNotValid (TRUE, 0, Tag, FileFormTags, &PopUp)) { - if (PopUp != 0x0000) { - StringPtr = GetToken (PopUp, MenuOption->Handle); - - CreatePopUp (GetStringWidth (StringPtr) / 2, 3, &NullCharacter, StringPtr, &NullCharacter); - - do { - WaitForKeyStroke (&Key); - - switch (Key.UnicodeChar) { - - case CHAR_CARRIAGE_RETURN: - // - // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth - // - CopyMem (NvRamMap, &Tag->OldValue, Tag->StorageWidth); - FreePool (StringPtr); - break; - - default: - break; - } - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - } - - return FALSE; - } - } - } - - return TRUE; -} - -UINT16 -GetWidth ( - IN EFI_TAG *Tag, - IN EFI_HII_HANDLE Handle - ) -/*++ - -Routine Description: - Get the supported width for a particular op-code - -Arguments: - Tag - The Tag structure passed in. - Handle - The handle in the HII database being used - -Returns: - Returns the number of CHAR16 characters that is support. - - ---*/ -{ - CHAR16 *String; - UINTN Size; - - Size = 0x00; - - // - // See if the second text parameter is really NULL - // - if ((Tag->Operand == EFI_IFR_TEXT_OP) && (Tag->TextTwo != 0)) { - String = GetToken (Tag->TextTwo, Handle); - Size = StrLen (String); - FreePool (String); - } - - if ((Tag->Operand == EFI_IFR_SUBTITLE_OP) || - (Tag->Operand == EFI_IFR_REF_OP) || - (Tag->Operand == EFI_IFR_PASSWORD_OP) || - (Tag->Operand == EFI_IFR_STRING_OP) || - (Tag->Operand == EFI_IFR_INVENTORY_OP) || - // - // Allow a wide display if text op-code and no secondary text op-code - // - ((Tag->Operand == EFI_IFR_TEXT_OP) && (Size == 0x0000)) - ) { - return (UINT16) (gPromptBlockWidth + gOptionBlockWidth); - } else { - return (UINT16) gPromptBlockWidth; - } -} - -UINT16 -GetLineByWidth ( - IN CHAR16 *InputString, - IN UINT16 LineWidth, - IN OUT UINTN *Index, - OUT CHAR16 **OutputString - ) -/*++ - -Routine Description: - Will copy LineWidth amount of a string in the OutputString buffer and return the - number of CHAR16 characters that were copied into the OutputString buffer. - -Arguments: - InputString - String description for this option. - LineWidth - Width of the desired string to extract in CHAR16 characters - Index - Where in InputString to start the copy process - OutputString - Buffer to copy the string into - -Returns: - Returns the number of CHAR16 characters that were copied into the OutputString buffer. - - ---*/ -{ - static BOOLEAN Finished; - UINT16 Count; - UINT16 Count2; - - if (Finished) { - Finished = FALSE; - return (UINT16) 0; - } - - Count = LineWidth; - Count2 = 0; - - *OutputString = AllocateZeroPool (((UINTN) (LineWidth + 1) * 2)); - - // - // Ensure we have got a valid buffer - // - if (*OutputString != NULL) { - - // - //NARROW_CHAR can not be printed in screen, so if a line only contain the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line in Screen. - //To avoid displaying this empty line in screen, just skip the two CHARs here. - // - if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) { - *Index = *Index + 2; - } - - // - // Fast-forward the string and see if there is a carriage-return in the string - // - for (; (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++) - ; - - // - // Copy the desired LineWidth of data to the output buffer. - // Also make sure that we don't copy more than the string. - // Also make sure that if there are linefeeds, we account for them. - // - if ((StrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) && - (StrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2)) - ) { - // - // Convert to CHAR16 value and show that we are done with this operation - // - LineWidth = (UINT16) ((StrSize (&InputString[*Index]) - 2) / 2); - if (LineWidth != 0) { - Finished = TRUE; - } - } else { - if (Count2 == LineWidth) { - // - // Rewind the string from the maximum size until we see a space to break the line - // - for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--) - ; - if (LineWidth == 0) { - LineWidth = Count; - } - } else { - LineWidth = Count2; - } - } - - CopyMem (*OutputString, &InputString[*Index], LineWidth * 2); - - // - // If currently pointing to a space, increment the index to the first non-space character - // - for (; - (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN); - (*Index)++ - ) - ; - *Index = (UINT16) (*Index + LineWidth); - return LineWidth; - } else { - return (UINT16) 0; - } -} - -STATIC -VOID -UpdateOptionSkipLines ( - IN EFI_IFR_DATA_ARRAY *PageData, - IN UI_MENU_OPTION *MenuOption, - IN EFI_FILE_FORM_TAGS *FileFormTagsHead, - IN CHAR16 **OptionalString, - IN UINTN SkipValue - ) -{ - UINTN Index; - UINT16 Width; - UINTN Row; - UINTN OriginalRow; - CHAR16 *OutputString; - CHAR16 *OptionString; - - Row = 0; - OptionString = *OptionalString; - OutputString = NULL; - - ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString); - - if (OptionString != NULL) { - Width = (UINT16) gOptionBlockWidth; - - OriginalRow = Row; - - for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) { - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&OptionString[Index])) { - if (SkipValue == 0) { - Row++; - // - // Since the Number of lines for this menu entry may or may not be reflected accurately - // since the prompt might be 1 lines and option might be many, and vice versa, we need to do - // some testing to ensure we are keeping this in-sync. - // - // If the difference in rows is greater than or equal to the skip value, increase the skip value - // - if ((Row - OriginalRow) >= MenuOption->Skip) { - MenuOption->Skip++; - } - } - } - - FreePool (OutputString); - if (SkipValue != 0) { - SkipValue--; - } - } - - Row = OriginalRow; - } - - *OptionalString = OptionString; -} -// -// Search table for UiDisplayMenu() -// -SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = { - { SCAN_UP, UiUp }, - { SCAN_DOWN, UiDown }, - { SCAN_PAGE_UP, UiPageUp }, - { SCAN_PAGE_DOWN, UiPageDown}, - { SCAN_ESC, UiReset}, - { SCAN_F2, UiPrevious}, - { SCAN_LEFT, UiLeft }, - { SCAN_RIGHT, UiRight }, - { SCAN_F9, UiDefault}, - { SCAN_F10, UiSave } -}; - -SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = { - { UiNoOperation, CfUiNoOperation }, - { UiDefault, CfUiDefault }, - { UiSelect, CfUiSelect }, - { UiUp, CfUiUp}, - { UiDown, CfUiDown }, - { UiLeft, CfUiLeft }, - { UiRight, CfUiRight }, - { UiReset, CfUiReset }, - { UiSave, CfUiSave }, - { UiPrevious, CfUiPrevious }, - { UiPageUp, CfUiPageUp }, - { UiPageDown, CfUiPageDown } -}; - -UI_MENU_OPTION * -UiDisplayMenu ( - IN BOOLEAN SubMenu, - IN EFI_FILE_FORM_TAGS *FileFormTagsHead, - OUT EFI_IFR_DATA_ARRAY *PageData - ) -/*++ - -Routine Description: - Display menu and wait for user to select one menu option, then return it. - If AutoBoot is enabled, then if user doesn't select any option, - after period of time, it will automatically return the first menu option. - -Arguments: - SubMenu - Indicate is sub menu. - FileFormTagsHead - A pointer to the EFI_FILE_FORM_TAGS structure. - PageData - A pointer to the EFI_IFR_DATA_ARRAY. - -Returns: - Return the pointer of the menu which selected, - otherwise return NULL. - ---*/ -{ - INTN SkipValue; - INTN Difference; - INTN OldSkipValue; - UINTN Row; - UINTN Col; - UINTN Temp; - UINTN Temp2; - UINTN TopRow; - UINTN BottomRow; - UINTN OriginalRow; - UINTN Index; - UINTN DataAndTimeLineNumberPad; - UINT32 Count; - INT16 OriginalTimeOut; - UINT8 *Location; - UINT16 Width; - CHAR16 *StringPtr; - CHAR16 *OptionString; - CHAR16 *OutputString; - CHAR16 *FormattedString; - CHAR16 YesResponse; - CHAR16 NoResponse; - BOOLEAN NewLine; - BOOLEAN Repaint; - BOOLEAN SavedValue; - EFI_STATUS Status; - UI_MENU_LIST *UiMenuList; - EFI_INPUT_KEY Key; - LIST_ENTRY *Link; - LIST_ENTRY *NewPos; - LIST_ENTRY *TopOfScreen; - LIST_ENTRY *SavedListEntry; - UI_MENU_OPTION *Selection; - UI_MENU_OPTION *MenuOption; - UI_MENU_OPTION *NextMenuOption; - UI_MENU_OPTION *SavedMenuOption; - UI_MENU_OPTION *PreviousMenuOption; - EFI_IFR_BINARY *IfrBinary; - UI_CONTROL_FLAG ControlFlag; - EFI_SCREEN_DESCRIPTOR LocalScreen; - EFI_FILE_FORM_TAGS *FileFormTags; - MENU_REFRESH_ENTRY *MenuRefreshEntry; - MENU_REFRESH_ENTRY *OldMenuRefreshEntry; - UI_SCREEN_OPERATION ScreenOperation; - EFI_VARIABLE_DEFINITION *VariableDefinition; - EFI_FORM_CALLBACK_PROTOCOL *FormCallback; - EFI_HII_VARIABLE_PACK_LIST *NvMapListHead; - EFI_HII_VARIABLE_PACK_LIST *NvMapListNode; - VOID *NvMap; - UINTN NvMapSize; - - CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); - - VariableDefinition = NULL; - Status = EFI_SUCCESS; - FormattedString = NULL; - OptionString = NULL; - ScreenOperation = UiNoOperation; - NewLine = TRUE; - FormCallback = NULL; - FileFormTags = NULL; - OutputString = NULL; - gUpArrow = FALSE; - gDownArrow = FALSE; - SkipValue = 0; - OldSkipValue = 0; - MenuRefreshEntry = gMenuRefreshHead; - OldMenuRefreshEntry = gMenuRefreshHead; - NextMenuOption = NULL; - PreviousMenuOption = NULL; - SavedMenuOption = NULL; - IfrBinary = NULL; - NvMap = NULL; - NvMapSize = 0; - - ZeroMem (&Key, sizeof (EFI_INPUT_KEY)); - - if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) { - TopRow = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; - Row = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; - } else { - TopRow = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; - Row = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; - } - - if (SubMenu) { - Col = LocalScreen.LeftColumn; - } else { - Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS; - } - - BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - SCROLL_ARROW_HEIGHT - 1; - - TopOfScreen = Menu.ForwardLink; - Repaint = TRUE; - MenuOption = NULL; - - // - // Get user's selection - // - Selection = NULL; - NewPos = Menu.ForwardLink; - gST->ConOut->EnableCursor (gST->ConOut, FALSE); - - UpdateStatusBar (REFRESH_STATUS_BAR, (UINT8) 0, TRUE); - - ControlFlag = CfInitialization; - - while (TRUE) { - switch (ControlFlag) { - case CfInitialization: - ControlFlag = CfCheckSelection; - if (gExitRequired) { - ScreenOperation = UiReset; - ControlFlag = CfScreenOperation; - } else if (gSaveRequired) { - ScreenOperation = UiSave; - ControlFlag = CfScreenOperation; - } else if (IsListEmpty (&Menu)) { - ControlFlag = CfReadKey; - } - break; - - case CfCheckSelection: - if (Selection != NULL) { - ControlFlag = CfExit; - } else { - ControlFlag = CfRepaint; - } - - FileFormTags = FileFormTagsHead; - break; - - case CfRepaint: - ControlFlag = CfRefreshHighLight; - - if (Repaint) { - // - // Display menu - // - SavedMenuOption = MenuOption; - gDownArrow = FALSE; - gUpArrow = FALSE; - Row = TopRow; - - Temp = SkipValue; - Temp2 = SkipValue; - - ClearLines ( - LocalScreen.LeftColumn, - LocalScreen.RightColumn, - TopRow - SCROLL_ARROW_HEIGHT, - BottomRow + SCROLL_ARROW_HEIGHT, - FIELD_TEXT | FIELD_BACKGROUND - ); - - while (gMenuRefreshHead != NULL) { - OldMenuRefreshEntry = gMenuRefreshHead->Next; - - FreePool (gMenuRefreshHead); - - gMenuRefreshHead = OldMenuRefreshEntry; - } - - for (Link = TopOfScreen; Link != &Menu; Link = Link->ForwardLink) { - MenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - MenuOption->Row = Row; - OriginalRow = Row; - MenuOption->Col = Col; - MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn; - - if (SubMenu) { - if (MenuOption->ThisTag->GrayOut) { - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND); - } else { - if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) { - gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND); - } - } - - Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle); - - OriginalRow = Row; - - for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) { - if ((Temp == 0) && (Row <= BottomRow)) { - PrintStringAt (Col, Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&MenuOption->Description[Index])) { - if (Temp == 0) { - Row++; - } - } - - FreePool (OutputString); - if (Temp != 0) { - Temp--; - } - } - - Temp = 0; - - Row = OriginalRow; - - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); - ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString); - - if (OptionString != NULL) { - if (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP || - MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP - ) { - // - // If leading spaces on OptionString - remove the spaces - // - for (Index = 0; OptionString[Index] == L' '; Index++) { - MenuOption->OptCol++; - } - - for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) { - OptionString[Count] = OptionString[Index]; - Count++; - } - - OptionString[Count] = CHAR_NULL; - } - - // - // If this is a date or time op-code and is used to reflect an RTC, register the op-code - // - if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP || - MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP) && - (MenuOption->ThisTag->StorageStart >= FileFormTags->FormTags.Tags[0].NvDataSize)) { - - if (gMenuRefreshHead == NULL) { - MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY)); - ASSERT (MenuRefreshEntry != NULL); - MenuRefreshEntry->MenuOption = MenuOption; - MenuRefreshEntry->FileFormTagsHead = FileFormTagsHead; - MenuRefreshEntry->CurrentColumn = MenuOption->OptCol; - MenuRefreshEntry->CurrentRow = MenuOption->Row; - MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND; - gMenuRefreshHead = MenuRefreshEntry; - } else { - // - // Advance to the last entry - // - for (MenuRefreshEntry = gMenuRefreshHead; - MenuRefreshEntry->Next != NULL; - MenuRefreshEntry = MenuRefreshEntry->Next - ) - ; - MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY)); - ASSERT (MenuRefreshEntry->Next != NULL); - MenuRefreshEntry = MenuRefreshEntry->Next; - MenuRefreshEntry->MenuOption = MenuOption; - MenuRefreshEntry->FileFormTagsHead = FileFormTagsHead; - MenuRefreshEntry->CurrentColumn = MenuOption->OptCol; - MenuRefreshEntry->CurrentRow = MenuOption->Row; - MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND; - } - } - - Width = (UINT16) gOptionBlockWidth; - - OriginalRow = Row; - - for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) { - if ((Temp2 == 0) && (Row <= BottomRow)) { - PrintStringAt (MenuOption->OptCol, Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&OptionString[Index])) { - if (Temp2 == 0) { - Row++; - // - // Since the Number of lines for this menu entry may or may not be reflected accurately - // since the prompt might be 1 lines and option might be many, and vice versa, we need to do - // some testing to ensure we are keeping this in-sync. - // - // If the difference in rows is greater than or equal to the skip value, increase the skip value - // - if ((Row - OriginalRow) >= MenuOption->Skip) { - MenuOption->Skip++; - } - } - } - - FreePool (OutputString); - if (Temp2 != 0) { - Temp2--; - } - } - - Temp2 = 0; - Row = OriginalRow; - } - // - // If this is a text op with secondary text information - // - if ((MenuOption->ThisTag->Operand == EFI_IFR_TEXT_OP) && (MenuOption->ThisTag->TextTwo != 0)) { - StringPtr = GetToken (MenuOption->ThisTag->TextTwo, MenuOption->Handle); - - Width = (UINT16) gOptionBlockWidth; - - OriginalRow = Row; - - for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) { - if ((Temp == 0) && (Row <= BottomRow)) { - PrintStringAt (MenuOption->OptCol, Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&StringPtr[Index])) { - if (Temp2 == 0) { - Row++; - // - // Since the Number of lines for this menu entry may or may not be reflected accurately - // since the prompt might be 1 lines and option might be many, and vice versa, we need to do - // some testing to ensure we are keeping this in-sync. - // - // If the difference in rows is greater than or equal to the skip value, increase the skip value - // - if ((Row - OriginalRow) >= MenuOption->Skip) { - MenuOption->Skip++; - } - } - } - - FreePool (OutputString); - if (Temp2 != 0) { - Temp2--; - } - } - - Row = OriginalRow; - FreePool (StringPtr); - } - } else { - // - // For now, assume left-justified 72 width max setup entries - // - PrintStringAt (Col, Row, MenuOption->Description); - } - // - // Tracker 6210 - need to handle the bottom of the display - // - if (MenuOption->Skip > 1) { - Row += MenuOption->Skip - SkipValue; - SkipValue = 0; - } else { - Row += MenuOption->Skip; - } - - if (Row > BottomRow) { - if (!ValueIsScroll (FALSE, Link)) { - gDownArrow = TRUE; - } - - Row = BottomRow + 1; - break; - } - } - - if (!ValueIsScroll (TRUE, TopOfScreen)) { - gUpArrow = TRUE; - } - - if (gUpArrow) { - gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND); - PrintAt ( - LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1, - TopRow - SCROLL_ARROW_HEIGHT, - (CHAR16 *) L"%c", - ARROW_UP - ); - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); - } - - if (gDownArrow) { - gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND); - PrintAt ( - LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1, - BottomRow + SCROLL_ARROW_HEIGHT, - (CHAR16 *) L"%c", - ARROW_DOWN - ); - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); - } - - if (SavedMenuOption != NULL) { - MenuOption = SavedMenuOption; - } - } - break; - - case CfRefreshHighLight: - ControlFlag = CfUpdateHelpString; - // - // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily - // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing. - // - SavedValue = Repaint; - Repaint = FALSE; - - if (NewPos != NULL) { - gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row); - if (SubMenu) { - if (gLastOpr && (gEntryNumber != -1)) { - MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - if (gEntryNumber != MenuOption->EntryNumber) { - ScreenOperation = UiDown; - ControlFlag = CfScreenOperation; - break; - } else { - gLastOpr = FALSE; - } - } - - ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString); - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); - if (OptionString != NULL) { - if (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP || - MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP - ) { - // - // If leading spaces on OptionString - remove the spaces - // - for (Index = 0; OptionString[Index] == L' '; Index++) - ; - - for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) { - OptionString[Count] = OptionString[Index]; - Count++; - } - - OptionString[Count] = CHAR_NULL; - } - - Width = (UINT16) gOptionBlockWidth; - - OriginalRow = MenuOption->Row; - - for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) { - if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) { - PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&OptionString[Index])) { - MenuOption->Row++; - } - - FreePool (OutputString); - } - - MenuOption->Row = OriginalRow; - } else { - if (NewLine) { - if (MenuOption->ThisTag->GrayOut) { - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND); - } else { - if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) { - gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND); - } - } - - OriginalRow = MenuOption->Row; - Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle); - - for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) { - if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) { - PrintStringAt (Col, MenuOption->Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&MenuOption->Description[Index])) { - MenuOption->Row++; - } - - FreePool (OutputString); - } - - MenuOption->Row = OriginalRow; - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); - } - } - } else { - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); - gST->ConOut->OutputString (gST->ConOut, MenuOption->Description); - } - - MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - - if ((gPriorMenuEntry != 0) && (MenuOption->EntryNumber != gPriorMenuEntry) && (NewPos->ForwardLink != &Menu)) { - ScreenOperation = UiDown; - ControlFlag = CfScreenOperation; - break; - } else { - gPriorMenuEntry = 0; - } - // - // This is only possible if we entered this page and the first menu option is - // a "non-menu" item. In that case, force it UiDown - // - if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut) { - // - // If we previously hit an UP command and we are still sitting on a text operation - // we must continue going up - // - if (ScreenOperation == UiUp) { - ControlFlag = CfScreenOperation; - break; - } else { - ScreenOperation = UiDown; - ControlFlag = CfScreenOperation; - break; - } - } - // - // Set reverse attribute - // - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT); - gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row); - - // - // Assuming that we have a refresh linked-list created, lets annotate the - // appropriate entry that we are highlighting with its new attribute. Just prior to this - // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh - // - if (gMenuRefreshHead != NULL) { - for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) { - MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND; - if (MenuRefreshEntry->MenuOption == MenuOption) { - MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT; - } - } - } - - if (SubMenu) { - ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString); - if (OptionString != NULL) { - if (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP || - MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP - ) { - // - // If leading spaces on OptionString - remove the spaces - // - for (Index = 0; OptionString[Index] == L' '; Index++) - ; - - for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) { - OptionString[Count] = OptionString[Index]; - Count++; - } - - OptionString[Count] = CHAR_NULL; - } - Width = (UINT16) gOptionBlockWidth; - - OriginalRow = MenuOption->Row; - - for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) { - if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) { - PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&OptionString[Index])) { - MenuOption->Row++; - } - - FreePool (OutputString); - } - - MenuOption->Row = OriginalRow; - } else { - if (NewLine) { - OriginalRow = MenuOption->Row; - - Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle); - - for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) { - if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) { - PrintStringAt (Col, MenuOption->Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&MenuOption->Description[Index])) { - MenuOption->Row++; - } - - FreePool (OutputString); - } - - MenuOption->Row = OriginalRow; - - } - } - - if (((NewPos->ForwardLink != &Menu) && (ScreenOperation == UiDown)) || - ((NewPos->BackLink != &Menu) && (ScreenOperation == UiUp)) || - (ScreenOperation == UiNoOperation) - ) { - UpdateKeyHelp (MenuOption, FALSE); - } - } else { - gST->ConOut->OutputString (gST->ConOut, MenuOption->Description); - } - // - // Clear reverse attribute - // - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); - } - // - // Repaint flag will be used when process CfUpdateHelpString, so restore its value - // if we didn't break halfway when process CfRefreshHighLight. - // - Repaint = SavedValue; - break; - - case CfUpdateHelpString: - ControlFlag = CfPrepareToReadKey; - - if (SubMenu && - (Repaint || NewLine || - (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || - (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) && - !(gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS)) { - // - // Don't print anything if it is a NULL help token - // - if (MenuOption->ThisTag->Help == 0x00000000) { - StringPtr = (CHAR16 *) L"\0"; - } else { - StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle); - } - - ProcessHelpString (StringPtr, &FormattedString, BottomRow - TopRow); - - gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND); - - for (Index = 0; Index < BottomRow - TopRow; Index++) { - // - // Pad String with spaces to simulate a clearing of the previous line - // - for (; GetStringWidth (&FormattedString[Index * gHelpBlockWidth * 2]) / 2 < gHelpBlockWidth;) { - StrCat (&FormattedString[Index * gHelpBlockWidth * 2], (CHAR16 *) L" "); - } - - PrintStringAt ( - LocalScreen.RightColumn - gHelpBlockWidth, - Index + TopRow, - &FormattedString[Index * gHelpBlockWidth * 2] - ); - } - } - // - // Reset this flag every time we finish using it. - // - Repaint = FALSE; - NewLine = FALSE; - break; - - case CfPrepareToReadKey: - ControlFlag = CfReadKey; - - for (Index = 0; Index < MenuOption->IfrNumber; Index++) { - FileFormTags = FileFormTags->NextFile; - } - - ScreenOperation = UiNoOperation; - - Status = gBS->HandleProtocol ( - (VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle, - &gEfiFormCallbackProtocolGuid, - (VOID **) &FormCallback - ); - - break; - - case CfReadKey: - ControlFlag = CfScreenOperation; - - OriginalTimeOut = FrontPageTimeOutValue; - do { - if (FrontPageTimeOutValue >= 0 && (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) && FrontPageTimeOutValue != (INT16) -1) { - // - // Remember that if set to 0, must immediately boot an option - // - if (FrontPageTimeOutValue == 0) { - FrontPageTimeOutValue = 0xFFFF; - Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - if (EFI_ERROR (Status)) { - Status = EFI_TIMEOUT; - } - break; - } - - Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND); - if (Status == EFI_TIMEOUT) { - EFI_IFR_DATA_ENTRY *DataEntry; - - DataEntry = (EFI_IFR_DATA_ENTRY *) (PageData + 1); - - PageData->EntryCount = 1; - Count = (UINT32) ((OriginalTimeOut - FrontPageTimeOutValue) * 100 / OriginalTimeOut); - CopyMem (&DataEntry->Data, &Count, sizeof (UINT32)); - - if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) { - FormCallback->Callback ( - FormCallback, - 0xFFFF, - (EFI_IFR_DATA_ARRAY *) PageData, - NULL - ); - } - // - // Count down 1 second - // - FrontPageTimeOutValue--; - - } else { - ASSERT (!EFI_ERROR (Status)); - PageData->EntryCount = 0; - if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) { - FormCallback->Callback ( - FormCallback, - 0xFFFE, - (EFI_IFR_DATA_ARRAY *) PageData, - NULL - ); - } - - FrontPageTimeOutValue = 0xFFFF; - } - } else { - // - // Wait for user's selection, no auto boot - // - Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0); - } - } while (Status == EFI_TIMEOUT); - - if (gFirstIn) { - gFirstIn = FALSE; - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); - DisableQuietBoot (); - } - - if (Status == EFI_TIMEOUT) { - Key.UnicodeChar = CHAR_CARRIAGE_RETURN; - } else { - Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - // - // if we encounter error, continue to read another key in. - // - if (EFI_ERROR (Status)) { - ControlFlag = CfReadKey; - continue; - } - } - - switch (Key.UnicodeChar) { - case CHAR_CARRIAGE_RETURN: - Selection = MenuOption; - ScreenOperation = UiSelect; - gDirection = 0; - break; - - // - // We will push the adjustment of these numeric values directly to the input handler - // - case '+': - case '-': - if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) { - - if (Key.UnicodeChar == '+') { - gDirection = SCAN_RIGHT; - } else { - gDirection = SCAN_LEFT; - } - - Status = ProcessOptions (MenuOption, TRUE, FileFormTagsHead, NULL, &OptionString); - } - break; - - case '^': - ScreenOperation = UiUp; - break; - - case 'V': - case 'v': - ScreenOperation = UiDown; - break; - - case ' ': - if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) { - if (SubMenu) { - if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !(MenuOption->ThisTag->GrayOut)) { - gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row); - gST->ConOut->OutputString (gST->ConOut, MenuOption->Description); - Selection = MenuOption; - ScreenOperation = UiSelect; - } - } - } - break; - - case CHAR_NULL: - if (((Key.ScanCode == SCAN_F1) && ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE)) || - ((Key.ScanCode == SCAN_F2) && ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO)) || - ((Key.ScanCode == SCAN_F9) && ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE)) || - ((Key.ScanCode == SCAN_F10) && ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN)) - ) { - // - // If the function key has been disabled, just ignore the key. - // - } else { - for (Index = 0; Index < sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]); Index++) { - if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) { - if ((Key.ScanCode == SCAN_F9) || (Key.ScanCode == SCAN_F10)) { - if (SubMenu) { - ScreenOperation = gScanCodeToOperation[Index].ScreenOperation; - } - } else { - ScreenOperation = gScanCodeToOperation[Index].ScreenOperation; - } - } - } - } - break; - } - break; - - case CfScreenOperation: - IfrBinary = gBinaryDataHead; - - // - // Advance to the Ifr we are using - // - for (Index = 0; Index < gActiveIfr; Index++) { - IfrBinary = IfrBinary->Next; - } - - if (ScreenOperation != UiPrevious && ScreenOperation != UiReset) { - // - // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset - // ignore the selection and go back to reading keys. - // - if (IsListEmpty (&Menu)) { - ControlFlag = CfReadKey; - break; - } - // - // if there is nothing logical to place a cursor on, just move on to wait for a key. - // - for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) { - NextMenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - if (!(NextMenuOption->ThisTag->GrayOut) && (NextMenuOption->ThisTag->Operand != EFI_IFR_SUBTITLE_OP)) { - break; - } - } - - if (Link == &Menu) { - ControlFlag = CfPrepareToReadKey; - break; - } - } - - for (Index = 0; - Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]); - Index++ - ) { - if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) { - ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag; - } - } - - break; - - case CfUiPrevious: - ControlFlag = CfCheckSelection; - // - // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data. - // - if (MenuOption != NULL) { - if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) { - Selection = NULL; - Repaint = TRUE; - break; - } - } - - if (IsListEmpty (&gMenuList)) { - Selection = NULL; - if (IsListEmpty (&Menu)) { - ControlFlag = CfReadKey; - } - break; - } - - gLastOpr = TRUE; - - while (gMenuRefreshHead != NULL) { - OldMenuRefreshEntry = gMenuRefreshHead->Next; - - FreePool (gMenuRefreshHead); - - gMenuRefreshHead = OldMenuRefreshEntry; - } - // - // Remove the Cached page entry, free and init the menus, flag Selection as jumping to previous page and a valid Tag - // - if (SubMenu) { - UiRemoveMenuListEntry (MenuOption, &Selection); - Selection->Previous = TRUE; - UiFreeMenu (); - UiInitMenu (); - } - - gActiveIfr = Selection->IfrNumber; - return Selection; - - case CfUiSelect: - ControlFlag = CfCheckSelection; - - ExtractRequestedNvMap (FileFormTags, MenuOption->ThisTag->VariableNumber, &VariableDefinition); - - if (SubMenu) { - if ((MenuOption->ThisTag->Operand == EFI_IFR_TEXT_OP && - !(MenuOption->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE)) || - (MenuOption->ThisTag->GrayOut) || - (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || - (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) { - Selection = NULL; - break; - } - - NewLine = TRUE; - UpdateKeyHelp (MenuOption, TRUE); - Status = ProcessOptions (MenuOption, TRUE, FileFormTagsHead, PageData, &OptionString); - - if (EFI_ERROR (Status)) { - Selection = NULL; - Repaint = TRUE; - break; - } - - if (OptionString != NULL) { - PrintStringAt (LocalScreen.LeftColumn + gPromptBlockWidth + 1, MenuOption->Row, OptionString); - } - - if (MenuOption->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) { - Selection = MenuOption; - } - - if (Selection == NULL) { - break; - } - - Location = (UINT8 *) &PageData->EntryCount; - - // - // If not a goto, dump single piece of data, otherwise dump everything - // - if (Selection->ThisTag->Operand == EFI_IFR_REF_OP) { - // - // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data. - // - if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) { - Selection = NULL; - Repaint = TRUE; - break; - } - - UiAddMenuListEntry (Selection); - gPriorMenuEntry = 0; - - // - // Now that we added a menu entry specific to a goto, we can always go back when someone hits the UiPrevious - // - UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE); - UiMenuList->FormerEntryNumber = MenuOption->EntryNumber; - - gLastOpr = FALSE; - - // - // Rewind to the beginning of the menu - // - for (; NewPos->BackLink != &Menu; NewPos = NewPos->BackLink) - ; - - // - // Get Total Count of Menu entries - // - for (Count = 1; NewPos->ForwardLink != &Menu; NewPos = NewPos->ForwardLink) { - Count++; - } - // - // Rewind to the beginning of the menu - // - for (; NewPos->BackLink != &Menu; NewPos = NewPos->BackLink) - ; - - // - // Copy the number of entries being described to the PageData location - // - CopyMem (&Location[0], &Count, sizeof (UINT32)); - - for (Index = 4; NewPos->ForwardLink != &Menu; Index = Index + MenuOption->ThisTag->StorageWidth + 2) { - - MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - Location[Index] = MenuOption->ThisTag->Operand; - Location[Index + 1] = (UINT8) (MenuOption->ThisTag->StorageWidth + 4); - CopyMem ( - &Location[Index + 4], - &VariableDefinition->NvRamMap[MenuOption->ThisTag->StorageStart], - MenuOption->ThisTag->StorageWidth - ); - NewPos = NewPos->ForwardLink; - } - } else { - - gPriorMenuEntry = MenuOption->EntryNumber; - - Count = 1; - - // - // Copy the number of entries being described to the PageData location - // - CopyMem (&Location[0], &Count, sizeof (UINT32)); - - // - // Start at PageData[4] since the EntryCount is a UINT32 - // - Index = 4; - - // - // Copy data to destination - // - Location[Index] = MenuOption->ThisTag->Operand; - Location[Index + 1] = (UINT8) (MenuOption->ThisTag->StorageWidth + 4); - CopyMem ( - &Location[Index + 4], - &VariableDefinition->NvRamMap[MenuOption->ThisTag->StorageStart], - MenuOption->ThisTag->StorageWidth - ); - } - } - break; - - case CfUiReset: - ControlFlag = CfCheckSelection; - gLastOpr = FALSE; - if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) { - break; - } - // - // If NV flag is up, prompt user - // - if (gNvUpdateRequired) { - Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - - YesResponse = gYesResponse[0]; - NoResponse = gNoResponse[0]; - - do { - CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gAreYouSure, gEmptyString); - } while - ( - (Key.ScanCode != SCAN_ESC) && - ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) && - ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET)) - ); - - // - // If the user hits the YesResponse key - // - if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) { - } else { - Repaint = TRUE; - NewLine = TRUE; - break; - } - } - // - // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data. - // - if (MenuOption != NULL) { - if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) { - Selection = NULL; - Repaint = TRUE; - NewLine = TRUE; - break; - } - } - - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); - gST->ConOut->EnableCursor (gST->ConOut, TRUE); - - if (SubMenu) { - UiFreeMenuList (); - gST->ConOut->ClearScreen (gST->ConOut); - return NULL; - } - - UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE); - UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->Flags, FALSE); - - if (IfrBinary->UnRegisterOnExit) { - Hii->RemovePack (Hii, MenuOption->Handle); - } - - UiFreeMenu (); - - // - // Clean up the allocated data buffers - // - FreeData (FileFormTagsHead, FormattedString, OptionString); - - gST->ConOut->ClearScreen (gST->ConOut); - return NULL; - - case CfUiLeft: - ControlFlag = CfCheckSelection; - if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) { - if (MenuOption->Skip == 1) { - // - // In the tail of the Date/Time op-code set, go left. - // - NewPos = NewPos->BackLink; - } else { - // - // In the middle of the Data/Time op-code set, go left. - // - NextMenuOption = CR (NewPos->ForwardLink, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - if (NextMenuOption->Skip == 1) { - NewPos = NewPos->BackLink; - } - } - } - break; - - case CfUiRight: - ControlFlag = CfCheckSelection; - if ((MenuOption->Skip == 0) && - ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) - ) { - // - // We are in the head or middle of the Date/Time op-code set, advance right. - // - NewPos = NewPos->ForwardLink; - } - break; - - case CfUiUp: - ControlFlag = CfCheckSelection; - - if (NewPos->BackLink != &Menu) { - NewLine = TRUE; - // - // Adjust Date/Time position before we advance forward. - // - AdjustDateAndTimePosition (TRUE, &NewPos); - - // - // Caution that we have already rewind to the top, don't go backward in this situation. - // - if (NewPos->BackLink != &Menu) { - NewPos = NewPos->BackLink; - } - - PreviousMenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - - // - // Since the behavior of hitting the up arrow on a Date/Time op-code is intended - // to be one that back to the previous set of op-codes, we need to advance to the sencond - // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate - // checking can be done. - // - DataAndTimeLineNumberPad = AdjustDateAndTimePosition (TRUE, &NewPos); - - if (SubMenu) { - // - // If the previous MenuOption contains a display-only op-code, skip to the next one - // - if (PreviousMenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || PreviousMenuOption->ThisTag->GrayOut) { - // - // This is ok as long as not at the end of the list - // - if (NewPos->BackLink == &Menu) { - // - // If we are at the start of the list, then this list must start with a display only - // piece of data, so do not allow the backward motion - // - ScreenOperation = UiDown; - - if (PreviousMenuOption->Row <= TopRow) { - if (TopOfScreen->BackLink != &Menu) { - TopOfScreen = TopOfScreen->BackLink; - Repaint = TRUE; - } - } - - UpdateStatusBar (INPUT_ERROR, PreviousMenuOption->ThisTag->Flags, FALSE); - break; - } - } - } - // - // Check the previous menu entry to see if it was a zero-length advance. If it was, - // don't worry about a redraw. - // - if ((MenuOption->Row - PreviousMenuOption->Skip - DataAndTimeLineNumberPad < TopRow) || - (PreviousMenuOption->Skip > MenuOption->Row) - ) { - do { - if (TopOfScreen->BackLink == &Menu) { - break; - } - - Repaint = TRUE; - - // - // Is the current top of screen a zero-advance op-code? - // If so, keep moving forward till we hit a >0 advance op-code - // - SavedMenuOption = CR (TopOfScreen->BackLink, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - TopOfScreen = TopOfScreen->BackLink; - } while (SavedMenuOption->Skip == 0); - // - // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. - // - AdjustDateAndTimePosition (TRUE, &TopOfScreen); - } - - UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE); - } else { - if (SubMenu) { - SavedMenuOption = MenuOption; - MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut) { - // - // If we are at the end of the list and sitting on a text op, we need to more forward - // - ScreenOperation = UiDown; - ControlFlag = CfScreenOperation; - break; - } - - MenuOption = SavedMenuOption; - } - } - break; - - case CfUiPageUp: - ControlFlag = CfCheckSelection; - - SavedListEntry = NewPos; - Link = TopOfScreen; - for (Index = BottomRow; Index >= TopRow + 1; Index -= MenuOption->Skip) { - if (Link->BackLink == &Menu) { - TopOfScreen = Link; - Link = SavedListEntry; - MenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - break; - } - - NewLine = TRUE; - Repaint = TRUE; - Link = Link->BackLink; - MenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - TopOfScreen = Link; - SavedListEntry = Link; - } - - NewPos = Link; - - // - // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. - // Don't do this when we are already in the first page. - // - if (Repaint) { - AdjustDateAndTimePosition (TRUE, &TopOfScreen); - AdjustDateAndTimePosition (TRUE, &NewPos); - MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - } - break; - - case CfUiPageDown: - ControlFlag = CfCheckSelection; - - SavedListEntry = NewPos; - Link = TopOfScreen; - NewPos = TopOfScreen; - for (Index = TopRow; Index <= BottomRow - 1; Index += MenuOption->Skip) { - if (NewPos->ForwardLink == &Menu) { - NewPos = SavedListEntry; - MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - Link = TopOfScreen; - NewLine = FALSE; - Repaint = FALSE; - break; - } - - NewLine = TRUE; - Repaint = TRUE; - MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - NewPos = NewPos->ForwardLink; - Link = NewPos; - } - - TopOfScreen = Link; - - // - // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. - // Don't do this when we are already in the last page. - // - if (Repaint) { - AdjustDateAndTimePosition (TRUE, &TopOfScreen); - AdjustDateAndTimePosition (TRUE, &NewPos); - MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - } - break; - - case CfUiDown: - ControlFlag = CfCheckSelection; - // - // Since the behavior of hitting the down arrow on a Date/Time op-code is intended - // to be one that progresses to the next set of op-codes, we need to advance to the last - // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate - // checking can be done. The only other logic we need to introduce is that if a Date/Time - // op-code is the last entry in the menu, we need to rewind back to the first op-code of - // the Date/Time op-code. - // - DataAndTimeLineNumberPad = AdjustDateAndTimePosition (FALSE, &NewPos); - - if (NewPos->ForwardLink != &Menu) { - NewLine = TRUE; - NewPos = NewPos->ForwardLink; - NextMenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - - if (SubMenu) { - // - // If the next MenuOption contains a display-only op-code, skip to the next one - // Also if the next MenuOption is date or time, - // - if (NextMenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || NextMenuOption->ThisTag->GrayOut) { - // - // This is ok as long as not at the end of the list - // - if (NewPos == &Menu) { - // - // If we are at the end of the list, then this list must end with a display only - // piece of data, so do not allow the forward motion - // - UpdateStatusBar (INPUT_ERROR, NextMenuOption->ThisTag->Flags, FALSE); - NewPos = NewPos->BackLink; - ScreenOperation = UiUp; - break; - } - } - } - // - // An option might be multi-line, so we need to reflect that data in the overall skip value - // - UpdateOptionSkipLines (PageData, NextMenuOption, FileFormTagsHead, &OptionString, SkipValue); - - if (NextMenuOption->Skip > 1) { - Temp = MenuOption->Row + MenuOption->Skip + NextMenuOption->Skip - 1; - } else { - Temp = MenuOption->Row + MenuOption->Skip + DataAndTimeLineNumberPad; - } - // - // If we are going to scroll - // - if (Temp > BottomRow) { - do { - // - // Is the current top of screen a zero-advance op-code? - // If so, keep moving forward till we hit a >0 advance op-code - // - SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - - // - // If bottom op-code is more than one line or top op-code is more than one line - // - if ((NextMenuOption->Skip > 1) || (MenuOption->Skip > 1)) { - // - // Is the bottom op-code greater than or equal in size to the top op-code? - // - if ((Temp - BottomRow) >= (SavedMenuOption->Skip - OldSkipValue)) { - // - // Skip the top op-code - // - TopOfScreen = TopOfScreen->ForwardLink; - Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - OldSkipValue); - - OldSkipValue = Difference; - - SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - - // - // If we have a remainder, skip that many more op-codes until we drain the remainder - // - for (; - Difference >= (INTN) SavedMenuOption->Skip; - Difference = Difference - (INTN) SavedMenuOption->Skip - ) { - // - // Since the Difference is greater than or equal to this op-code's skip value, skip it - // - TopOfScreen = TopOfScreen->ForwardLink; - SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - if (Difference < (INTN) SavedMenuOption->Skip) { - Difference = SavedMenuOption->Skip - Difference - 1; - break; - } else { - if (Difference == (INTN) SavedMenuOption->Skip) { - TopOfScreen = TopOfScreen->ForwardLink; - SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - Difference = SavedMenuOption->Skip - Difference; - break; - } - } - } - // - // Since we will act on this op-code in the next routine, and increment the - // SkipValue, set the skips to one less than what is required. - // - SkipValue = Difference - 1; - - } else { - // - // Since we will act on this op-code in the next routine, and increment the - // SkipValue, set the skips to one less than what is required. - // - SkipValue = OldSkipValue + (Temp - BottomRow) - 1; - } - } else { - if ((OldSkipValue + 1) == (INTN) SavedMenuOption->Skip) { - TopOfScreen = TopOfScreen->ForwardLink; - break; - } else { - SkipValue = OldSkipValue; - } - } - // - // If the op-code at the top of the screen is more than one line, let's not skip it yet - // Let's set a skip flag to smoothly scroll the top of the screen. - // - if (SavedMenuOption->Skip > 1) { - if (SavedMenuOption == NextMenuOption) { - SkipValue = 0; - } else { - SkipValue++; - } - } else { - SkipValue = 0; - TopOfScreen = TopOfScreen->ForwardLink; - } - } while (SavedMenuOption->Skip == 0); - - Repaint = TRUE; - OldSkipValue = SkipValue; - } - - UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE); - - } else { - if (SubMenu) { - SavedMenuOption = MenuOption; - MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut) { - // - // If we are at the end of the list and sitting on a text op, we need to more forward - // - ScreenOperation = UiUp; - ControlFlag = CfScreenOperation; - break; - } - - MenuOption = SavedMenuOption; - // - // If we are at the end of the list and sitting on a Date/Time op, rewind to the head. - // - AdjustDateAndTimePosition (TRUE, &NewPos); - } - } - break; - - case CfUiSave: - ControlFlag = CfCheckSelection; - // - // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data. - // - if (MenuOption != NULL) { - if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) { - Selection = NULL; - Repaint = TRUE; - break; - } - } - // - // If callbacks are active, and the callback has a Write method, try to use it - // - if (FileFormTags->VariableDefinitions->VariableName == NULL) { - if ((FormCallback != NULL) && (FormCallback->NvWrite != NULL)) { - Status = FormCallback->NvWrite ( - FormCallback, - (CHAR16 *) L"Setup", - &FileFormTags->FormTags.Tags[0].GuidValue, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - VariableDefinition->VariableSize, - (VOID *) VariableDefinition->NvRamMap, - &gResetRequired - ); - - } else { - Status = gRT->SetVariable ( - (CHAR16 *) L"Setup", - &FileFormTags->FormTags.Tags[0].GuidValue, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - VariableDefinition->VariableSize, - (VOID *) VariableDefinition->NvRamMap - ); - } - } else { - VariableDefinition = FileFormTags->VariableDefinitions; - - for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) { - if ((FormCallback != NULL) && (FormCallback->NvWrite != NULL)) { - Status = FormCallback->NvWrite ( - FormCallback, - VariableDefinition->VariableName, - &VariableDefinition->Guid, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - VariableDefinition->VariableSize, - (VOID *) VariableDefinition->NvRamMap, - &gResetRequired - ); - - } else { - Status = gRT->SetVariable ( - VariableDefinition->VariableName, - &VariableDefinition->Guid, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - VariableDefinition->VariableSize, - (VOID *) VariableDefinition->NvRamMap - ); - } - } - } - - UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE); - UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->Flags, FALSE); - break; - - case CfUiDefault: - ControlFlag = CfCheckSelection; - - NvMapListHead = NULL; - - Status = Hii->GetDefaultImage (Hii, MenuOption->Handle, EFI_IFR_FLAG_DEFAULT, &NvMapListHead); - - if (!EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (NULL != NvMapListHead); - - NvMapListNode = NvMapListHead; - - while (NULL != NvMapListNode) { - if (FileFormTags->VariableDefinitions->VariableId == NvMapListNode->VariablePack->VariableId) { - NvMap = (VOID *) ((CHAR8 *) NvMapListNode->VariablePack + sizeof (EFI_HII_VARIABLE_PACK) + NvMapListNode->VariablePack->VariableNameLength); - NvMapSize = NvMapListNode->VariablePack->Header.Length - sizeof (EFI_HII_VARIABLE_PACK) - NvMapListNode->VariablePack->VariableNameLength; - break; - } - NvMapListNode = NvMapListNode->NextVariablePack; - } - - // - // Free the buffer that was allocated. - // - FreePool (FileFormTags->VariableDefinitions->NvRamMap); - FreePool (FileFormTags->VariableDefinitions->FakeNvRamMap); - - // - // Allocate, copy the NvRamMap. - // - FileFormTags->VariableDefinitions->VariableFakeSize = (UINT16) (FileFormTags->VariableDefinitions->VariableFakeSize - FileFormTags->VariableDefinitions->VariableSize); - FileFormTags->VariableDefinitions->VariableSize = (UINT16) NvMapSize; - FileFormTags->VariableDefinitions->VariableFakeSize = (UINT16) (FileFormTags->VariableDefinitions->VariableFakeSize + FileFormTags->VariableDefinitions->VariableSize); - - FileFormTags->VariableDefinitions->NvRamMap = AllocateZeroPool (FileFormTags->VariableDefinitions->VariableSize); - ASSERT (FileFormTags->VariableDefinitions->NvRamMap != NULL); - - FileFormTags->VariableDefinitions->FakeNvRamMap = AllocateZeroPool (NvMapSize + FileFormTags->VariableDefinitions->VariableFakeSize); - ASSERT (FileFormTags->VariableDefinitions->FakeNvRamMap != NULL); - - CopyMem (FileFormTags->VariableDefinitions->NvRamMap, NvMap, NvMapSize); - FreePool (NvMapListHead); - } - - UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->Flags, TRUE); - Repaint = TRUE; - // - // After the repaint operation, we should refresh the highlight. - // - NewLine = TRUE; - break; - - case CfUiNoOperation: - ControlFlag = CfCheckSelection; - break; - - case CfExit: - while (gMenuRefreshHead != NULL) { - OldMenuRefreshEntry = gMenuRefreshHead->Next; - - FreePool (gMenuRefreshHead); - - gMenuRefreshHead = OldMenuRefreshEntry; - } - - gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4); - gST->ConOut->EnableCursor (gST->ConOut, TRUE); - gST->ConOut->OutputString (gST->ConOut, (CHAR16 *) L"\n"); - - gActiveIfr = MenuOption->IfrNumber; - return Selection; - - default: - break; - } - } -} - -BOOLEAN -ValueIsScroll ( - IN BOOLEAN Direction, - IN LIST_ENTRY *CurrentPos - ) -/*++ - -Routine Description: - Determine if the menu is the last menu that can be selected. - -Arguments: - Direction - the scroll direction. False is down. True is up. - -Returns: - FALSE -- the menu isn't the last menu that can be selected. - TRUE -- the menu is the last menu that can be selected. ---*/ -{ - LIST_ENTRY *Temp; - UI_MENU_OPTION *MenuOption; - MenuOption = NULL; - - Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink; - - if (Temp == &Menu) { - return TRUE; - } - - for (; Temp != &Menu; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) { - MenuOption = CR (Temp, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - if (!(MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut)) { - return FALSE; - } - } - - return TRUE; -} - -UINTN -AdjustDateAndTimePosition ( - IN BOOLEAN DirectionUp, - IN LIST_ENTRY **CurrentPosition - ) -/*++ -Routine Description: - Adjust Data and Time tag position accordingly. - Data format : [01/02/2004] [11:22:33] - Line number : 0 0 1 0 0 1 - -Arguments: - Direction - the up or down direction. False is down. True is up. - CurrentPos - Current position. - -Returns: - Return line number to pad. It is possible that we stand on a zero-advance - data or time opcode, so pad one line when we judge if we are going to scroll outside. ---*/ -{ - UINTN Count; - LIST_ENTRY *NewPosition; - UI_MENU_OPTION *MenuOption; - UINTN PadLineNumber; - - PadLineNumber = 0; - NewPosition = *CurrentPosition; - MenuOption = CR (NewPosition, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - - if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) { - // - // Calculate the distance from current position to the last Date/Time op-code. - // - Count = 0; - while (MenuOption->ThisTag->NumberOfLines == 0) { - Count++; - NewPosition = NewPosition->ForwardLink; - MenuOption = CR (NewPosition, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); - PadLineNumber = 1; - } - - NewPosition = *CurrentPosition; - if (DirectionUp) { - // - // Since the behavior of hitting the up arrow on a Date/Time op-code is intended - // to be one that back to the previous set of op-codes, we need to advance to the first - // Date/Time op-code and leave the remaining logic in CfUiUp intact so the appropriate - // checking can be done. - // - while (Count++ < 2) { - NewPosition = NewPosition->BackLink; - } - } else { - // - // Since the behavior of hitting the down arrow on a Date/Time op-code is intended - // to be one that progresses to the next set of op-codes, we need to advance to the last - // Date/Time op-code and leave the remaining logic in CfUiDown intact so the appropriate - // checking can be done. - // - while (Count-- > 0) { - NewPosition = NewPosition->ForwardLink; - } - } - - *CurrentPosition = NewPosition; - } - - return PadLineNumber; -}