X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FSetupBrowserDxe%2FUi.c;h=189b6e1dc9dc51ba55313bc64a6e5db6c4511df6;hb=157136700dd0a95afa6d9046b58d110bb3c5ef51;hp=068a3e7f7fbe590c5cf6b2a3b44b92ce23994d4e;hpb=ebe43565f9f7ace6d19410c397c0df7482b022f3;p=mirror_edk2.git diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c index 068a3e7f7f..189b6e1dc9 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c @@ -1,8 +1,8 @@ /** @file Utility functions for User Interface functions. -Copyright (c) 2004 - 2007, Intel Corporation -All rights reserved. This program and the accompanying materials +Copyright (c) 2004 - 2011, 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 @@ -12,11 +12,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ -#include "Ui.h" #include "Setup.h" -LIST_ENTRY Menu; -LIST_ENTRY gMenuList; +LIST_ENTRY gMenuOption; +LIST_ENTRY gMenuList = INITIALIZE_LIST_HEAD_VARIABLE (gMenuList); MENU_REFRESH_ENTRY *gMenuRefreshHead; // @@ -43,10 +42,6 @@ SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = { SCAN_ESC, UiReset, }, - { - SCAN_F2, - UiPrevious, - }, { SCAN_LEFT, UiLeft, @@ -102,10 +97,6 @@ SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = { UiSave, CfUiSave, }, - { - UiPrevious, - CfUiPrevious, - }, { UiPageUp, CfUiPageUp, @@ -116,6 +107,9 @@ SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = { } }; +BOOLEAN mInputError; +BOOLEAN GetLineByWidthFinished = FALSE; + /** Set Buffer to Value for Size bytes. @@ -124,8 +118,6 @@ SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = { @param Size Number of bytes to set @param Value Value of the set operation. - @return Value. - **/ VOID SetUnicodeMem ( @@ -152,118 +144,162 @@ UiInitMenu ( VOID ) { - InitializeListHead (&Menu); + InitializeListHead (&gMenuOption); } /** - Initialize Menu option list. + Free Menu option linked list. **/ VOID -UiInitMenuList ( +UiFreeMenu ( VOID ) { - InitializeListHead (&gMenuList); + UI_MENU_OPTION *MenuOption; + + while (!IsListEmpty (&gMenuOption)) { + MenuOption = MENU_OPTION_FROM_LINK (gMenuOption.ForwardLink); + RemoveEntryList (&MenuOption->Link); + + // + // We allocated space for this description when we did a GetToken, free it here + // + if (MenuOption->Skip != 0) { + // + // For date/time, MenuOption->Description is shared by three Menu Options + // Data format : [01/02/2004] [11:22:33] + // Line number : 0 0 1 0 0 1 + // + FreePool (MenuOption->Description); + } + FreePool (MenuOption); + } } /** - Remove a Menu in list, and return FormId/QuestionId for previous Menu. + Create a menu with specified formset GUID and form ID, and add it as a child + of the given parent menu. - @param Selection Menu selection. + @param Parent The parent of menu to be added. + @param FormSetGuid The Formset Guid of menu to be added. + @param FormId The Form ID of menu to be added. + + @return A pointer to the newly added menu or NULL if memory is insufficient. **/ -VOID -UiRemoveMenuListEntry ( - OUT UI_MENU_SELECTION *Selection +UI_MENU_LIST * +UiAddMenuList ( + IN OUT UI_MENU_LIST *Parent, + IN EFI_GUID *FormSetGuid, + IN UINT16 FormId ) { - UI_MENU_LIST *UiMenuList; - - if (!IsListEmpty (&gMenuList)) { - UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE); + UI_MENU_LIST *MenuList; - Selection->FormId = UiMenuList->FormId; - Selection->QuestionId = UiMenuList->QuestionId; - RemoveEntryList (&UiMenuList->MenuLink); - gBS->FreePool (UiMenuList); + MenuList = AllocateZeroPool (sizeof (UI_MENU_LIST)); + if (MenuList == NULL) { + return NULL; } -} + MenuList->Signature = UI_MENU_LIST_SIGNATURE; + InitializeListHead (&MenuList->ChildListHead); -/** - Free Menu option linked list. - -**/ -VOID -UiFreeMenuList ( - VOID - ) -{ - UI_MENU_LIST *UiMenuList; + CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID)); + MenuList->FormId = FormId; + MenuList->Parent = Parent; - while (!IsListEmpty (&gMenuList)) { - UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE); - RemoveEntryList (&UiMenuList->MenuLink); - gBS->FreePool (UiMenuList); + if (Parent == NULL) { + // + // If parent is not specified, it is the root Form of a Formset + // + InsertTailList (&gMenuList, &MenuList->Link); + } else { + InsertTailList (&Parent->ChildListHead, &MenuList->Link); } + + return MenuList; } /** - Add one menu entry to the linked lst + Search Menu with given FormId in the parent menu and all its child menus. - @param Selection Menu selection. + @param Parent The parent of menu to search. + @param FormId The Form ID of menu to search. + + @return A pointer to menu found or NULL if not found. **/ -VOID -UiAddMenuListEntry ( - IN UI_MENU_SELECTION *Selection +UI_MENU_LIST * +UiFindChildMenuList ( + IN UI_MENU_LIST *Parent, + IN UINT16 FormId ) { - UI_MENU_LIST *UiMenuList; + LIST_ENTRY *Link; + UI_MENU_LIST *Child; + UI_MENU_LIST *MenuList; + + if (Parent->FormId == FormId) { + return Parent; + } - UiMenuList = AllocateZeroPool (sizeof (UI_MENU_LIST)); - ASSERT (UiMenuList != NULL); + Link = GetFirstNode (&Parent->ChildListHead); + while (!IsNull (&Parent->ChildListHead, Link)) { + Child = UI_MENU_LIST_FROM_LINK (Link); - UiMenuList->Signature = UI_MENU_LIST_SIGNATURE; - UiMenuList->FormId = Selection->FormId; - UiMenuList->QuestionId = Selection->QuestionId; + MenuList = UiFindChildMenuList (Child, FormId); + if (MenuList != NULL) { + return MenuList; + } + + Link = GetNextNode (&Parent->ChildListHead, Link); + } - InsertHeadList (&gMenuList, &UiMenuList->MenuLink); + return NULL; } /** - Free Menu option linked list. + Search Menu with given FormSetGuid and FormId in all cached menu list. + + @param FormSetGuid The Formset GUID of the menu to search. + @param FormId The Form ID of menu to search. + + @return A pointer to menu found or NULL if not found. **/ -VOID -UiFreeMenu ( - VOID +UI_MENU_LIST * +UiFindMenuList ( + IN EFI_GUID *FormSetGuid, + IN UINT16 FormId ) { - UI_MENU_OPTION *MenuOption; + LIST_ENTRY *Link; + UI_MENU_LIST *MenuList; + UI_MENU_LIST *Child; - while (!IsListEmpty (&Menu)) { - MenuOption = MENU_OPTION_FROM_LINK (Menu.ForwardLink); - RemoveEntryList (&MenuOption->Link); + Link = GetFirstNode (&gMenuList); + while (!IsNull (&gMenuList, Link)) { + MenuList = UI_MENU_LIST_FROM_LINK (Link); - // - // We allocated space for this description when we did a GetToken, free it here - // - if (MenuOption->Skip != 0) { + if (CompareGuid (FormSetGuid, &MenuList->FormSetGuid)) { // - // For date/time, MenuOption->Description is shared by three Menu Options - // Data format : [01/02/2004] [11:22:33] - // Line number : 0 0 1 0 0 1 + // This is the formset we are looking for, find the form in this formset // - gBS->FreePool (MenuOption->Description); + Child = UiFindChildMenuList (MenuList, FormId); + if (Child != NULL) { + return Child; + } } - gBS->FreePool (MenuOption); + + Link = GetNextNode (&gMenuList, Link); } + + return NULL; } @@ -280,7 +316,7 @@ UiFreeRefreshList ( while (gMenuRefreshHead != NULL) { OldMenuRefreshEntry = gMenuRefreshHead->Next; - gBS->FreePool (gMenuRefreshHead); + FreePool (gMenuRefreshHead); gMenuRefreshHead = OldMenuRefreshEntry; } @@ -293,66 +329,104 @@ UiFreeRefreshList ( Refresh screen. **/ -VOID +EFI_STATUS RefreshForm ( VOID ) { - CHAR16 *OptionString; - MENU_REFRESH_ENTRY *MenuRefreshEntry; - UINTN Index; - UINTN Loop; - EFI_STATUS Status; - UI_MENU_SELECTION *Selection; - FORM_BROWSER_STATEMENT *Question; - - OptionString = NULL; + CHAR16 *OptionString; + MENU_REFRESH_ENTRY *MenuRefreshEntry; + UINTN Index; + EFI_STATUS Status; + UI_MENU_SELECTION *Selection; + FORM_BROWSER_STATEMENT *Question; + EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; + EFI_BROWSER_ACTION_REQUEST ActionRequest; if (gMenuRefreshHead != NULL) { MenuRefreshEntry = gMenuRefreshHead; + // + // Reset FormPackage update flag + // + mHiiPackageListUpdated = FALSE; + do { gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute); Selection = MenuRefreshEntry->Selection; Question = MenuRefreshEntry->MenuOption->ThisTag; - // - // Don't update Question being edited - // - if (Question != MenuRefreshEntry->Selection->Statement) { + Status = GetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } - Status = GetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE); - if (EFI_ERROR (Status)) { - return; - } + OptionString = NULL; + ProcessOptions (Selection, MenuRefreshEntry->MenuOption, FALSE, &OptionString); - ProcessOptions (Selection, MenuRefreshEntry->MenuOption, FALSE, &OptionString); + if (OptionString != NULL) { + // + // If leading spaces on OptionString - remove the spaces + // + for (Index = 0; OptionString[Index] == L' '; Index++) + ; - if (OptionString != NULL) { - // - // If leading spaces on OptionString - remove the spaces - // - for (Index = 0; OptionString[Index] == L' '; Index++) - ; + PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, &OptionString[Index]); + FreePool (OptionString); + } - for (Loop = 0; OptionString[Index] != CHAR_NULL; Index++) { - OptionString[Loop] = OptionString[Index]; - Loop++; - } + // + // Question value may be changed, need invoke its Callback() + // + ConfigAccess = Selection->FormSet->ConfigAccess; + if (((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) { + ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; + Status = ConfigAccess->Callback ( + ConfigAccess, + EFI_BROWSER_ACTION_CHANGING, + Question->QuestionId, + Question->HiiValue.Type, + &Question->HiiValue.Value, + &ActionRequest + ); + if (!EFI_ERROR (Status)) { + switch (ActionRequest) { + case EFI_BROWSER_ACTION_REQUEST_RESET: + gResetRequired = TRUE; + break; - OptionString[Loop] = CHAR_NULL; + case EFI_BROWSER_ACTION_REQUEST_SUBMIT: + SubmitForm (Selection->FormSet, Selection->Form); + break; + + case EFI_BROWSER_ACTION_REQUEST_EXIT: + Selection->Action = UI_ACTION_EXIT; + gNvUpdateRequired = FALSE; + break; - PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString); - gBS->FreePool (OptionString); + default: + break; + } } } MenuRefreshEntry = MenuRefreshEntry->Next; } while (MenuRefreshEntry != NULL); + + if (mHiiPackageListUpdated) { + // + // Package list is updated, force to reparse IFR binary of target Formset + // + mHiiPackageListUpdated = FALSE; + Selection->Action = UI_ACTION_REFRESH_FORMSET; + return EFI_SUCCESS; + } } + + return EFI_TIMEOUT; } @@ -444,7 +518,7 @@ UiWaitForSingleEvent ( if (!EFI_ERROR (Status) && Index == 1) { Status = EFI_TIMEOUT; if (RefreshInterval != 0) { - RefreshForm (); + Status = RefreshForm (); } } @@ -465,8 +539,10 @@ UiWaitForSingleEvent ( @param NumberOfLines Display lines for this Menu Option. @param MenuItemCount The index for this Option in the Menu. + @retval Pointer Pointer to the added Menu Option. + **/ -VOID +UI_MENU_OPTION * UiAddMenuOption ( IN CHAR16 *String, IN EFI_HII_HANDLE Handle, @@ -480,6 +556,7 @@ UiAddMenuOption ( UINTN Count; Count = 1; + MenuOption = NULL; if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) { // @@ -524,13 +601,35 @@ UiAddMenuOption ( MenuOption->GrayOut = Statement->GrayOutExpression->Result.Value.b; } + switch (Statement->Operand) { + case EFI_IFR_ORDERED_LIST_OP: + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_NUMERIC_OP: + case EFI_IFR_TIME_OP: + case EFI_IFR_DATE_OP: + case EFI_IFR_CHECKBOX_OP: + case EFI_IFR_PASSWORD_OP: + case EFI_IFR_STRING_OP: + // + // User could change the value of these items + // + MenuOption->IsQuestion = TRUE; + break; + + default: + MenuOption->IsQuestion = FALSE; + break; + } + if ((Statement->ValueExpression != NULL) || ((Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY) != 0)) { MenuOption->ReadOnly = TRUE; } - InsertTailList (&Menu, &MenuOption->Link); + InsertTailList (&gMenuOption, &MenuOption->Link); } + + return MenuOption; } @@ -561,6 +660,7 @@ UiAddMenuOption ( **/ EFI_STATUS +EFIAPI CreateDialog ( IN UINTN NumberOfLines, IN BOOLEAN HotKey, @@ -571,7 +671,6 @@ CreateDialog ( ) { VA_LIST Marker; - VA_LIST MarkerBackup; UINTN Count; EFI_INPUT_KEY Key; UINTN LargestString; @@ -602,7 +701,6 @@ CreateDialog ( ASSERT (BufferedString); VA_START (Marker, KeyValue); - MarkerBackup = Marker; // // Zero the outgoing buffer @@ -643,6 +741,7 @@ CreateDialog ( LargestString = (GetStringWidth (StackString) / 2); } } + VA_END (Marker); Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1; Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1; @@ -652,7 +751,9 @@ CreateDialog ( // // Display the Popup // - CreateSharedPopUp (LargestString, NumberOfLines, MarkerBackup); + VA_START (Marker, KeyValue); + CreateSharedPopUp (LargestString, NumberOfLines, Marker); + VA_END (Marker); // // Take the first key typed and report it back? @@ -670,8 +771,8 @@ CreateDialog ( case CHAR_NULL: switch (Key.ScanCode) { case SCAN_ESC: - gBS->FreePool (TempString); - gBS->FreePool (BufferedString); + FreePool (TempString); + FreePool (BufferedString); gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); gST->ConOut->EnableCursor (gST->ConOut, TRUE); return EFI_DEVICE_ERROR; @@ -684,8 +785,8 @@ CreateDialog ( case CHAR_CARRIAGE_RETURN: SelectionComplete = TRUE; - gBS->FreePool (TempString); - gBS->FreePool (BufferedString); + FreePool (TempString); + FreePool (BufferedString); gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); gST->ConOut->EnableCursor (gST->ConOut, TRUE); return EFI_SUCCESS; @@ -860,7 +961,8 @@ CreateSharedPopUp ( **/ VOID -CreatePopUp ( +EFIAPI +CreateMultiStringPopUp ( IN UINTN RequestedWidth, IN UINTN NumberOfLines, ... @@ -869,7 +971,7 @@ CreatePopUp ( VA_LIST Marker; VA_START (Marker, NumberOfLines); - + CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker); VA_END (Marker); @@ -892,7 +994,6 @@ UpdateStatusBar ( ) { UINTN Index; - STATIC BOOLEAN InputError; CHAR16 *NvUpdateMessage; CHAR16 *InputErrorMessage; @@ -908,19 +1009,19 @@ UpdateStatusBar ( gScreenDimensions.BottomRow - 1, InputErrorMessage ); - InputError = TRUE; + mInputError = TRUE; } else { - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT); + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor)); for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) { PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, L" "); } - InputError = FALSE; + mInputError = FALSE; } break; case NV_UPDATE_REQUIRED: - if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) { + if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) { if (State) { gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT); PrintStringAt ( @@ -932,7 +1033,7 @@ UpdateStatusBar ( gNvUpdateRequired = TRUE; } else { - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT); + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor)); for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) { PrintAt ( (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index), @@ -947,7 +1048,7 @@ UpdateStatusBar ( break; case REFRESH_STATUS_BAR: - if (InputError) { + if (mInputError) { UpdateStatusBar (INPUT_ERROR, Flags, TRUE); } @@ -960,8 +1061,8 @@ UpdateStatusBar ( break; } - gBS->FreePool (InputErrorMessage); - gBS->FreePool (NvUpdateMessage); + FreePool (InputErrorMessage); + FreePool (NvUpdateMessage); return ; } @@ -993,7 +1094,7 @@ GetWidth ( if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) { String = GetToken (Statement->TextTwo, Handle); Size = StrLen (String); - gBS->FreePool (String); + FreePool (String); } if ((Statement->Operand == EFI_IFR_SUBTITLE_OP) || @@ -1015,12 +1116,9 @@ GetWidth ( Width -= SUBTITLE_INDENT; } - return Width; + return (UINT16) (Width - LEFT_SKIPPED_COLUMNS); } - -STATIC BOOLEAN GetLineByWidthFinished = FALSE; - /** 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. @@ -1161,7 +1259,7 @@ UpdateOptionSkipLines ( // // If there is more string to process print on the next row and increment the Skip value // - if (StrLen (&OptionString[Index])) { + if (StrLen (&OptionString[Index]) != 0) { if (SkipValue == 0) { Row++; // @@ -1177,7 +1275,7 @@ UpdateOptionSkipLines ( } } - gBS->FreePool (OutputString); + FreePool (OutputString); if (SkipValue != 0) { SkipValue--; } @@ -1219,7 +1317,7 @@ IsSelectable ( Determine if the menu is the last menu that can be selected. This is an internal function. - + @param Direction The scroll direction. False is down. True is up. @param CurrentPos The current focus. @@ -1238,11 +1336,11 @@ ValueIsScroll ( Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink; - if (Temp == &Menu) { + if (Temp == &gMenuOption) { return TRUE; } - for (; Temp != &Menu; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) { + for (; Temp != &gMenuOption; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) { MenuOption = MENU_OPTION_FROM_LINK (Temp); if (IsSelectable (MenuOption)) { return FALSE; @@ -1255,9 +1353,9 @@ ValueIsScroll ( /** Move to next selectable statement. - + This is an internal function. - + @param GoUp The navigation direction. TRUE: up, FALSE: down. @param CurrentPosition Current position. @@ -1284,7 +1382,7 @@ MoveToNextStatement ( if (IsSelectable (NextMenuOption)) { break; } - if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) { + if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) { HitEnd = TRUE; break; } @@ -1305,7 +1403,7 @@ MoveToNextStatement ( if (IsSelectable (NextMenuOption)) { break; } - if ((!GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) { + if ((!GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) { ASSERT (FALSE); break; } @@ -1323,7 +1421,7 @@ MoveToNextStatement ( Adjust Data and Time position accordingly. Data format : [01/02/2004] [11:22:33] Line number : 0 0 1 0 0 1 - + This is an internal function. @param DirectionUp the up or down direction. False is down. True is @@ -1393,6 +1491,102 @@ AdjustDateAndTimePosition ( return PadLineNumber; } +/** + Find HII Handle in the HII database associated with given Device Path. + + If DevicePath is NULL, then ASSERT. + + @param DevicePath Device Path associated with the HII package list + handle. + + @retval Handle HII package list Handle associated with the Device + Path. + @retval NULL Hii Package list handle is not found. + +**/ +EFI_HII_HANDLE +EFIAPI +DevicePathToHiiHandle ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; + UINTN BufferSize; + UINTN HandleCount; + UINTN Index; + EFI_HANDLE Handle; + EFI_HANDLE DriverHandle; + EFI_HII_HANDLE *HiiHandles; + EFI_HII_HANDLE HiiHandle; + + ASSERT (DevicePath != NULL); + + TmpDevicePath = DevicePath; + // + // Locate Device Path Protocol handle buffer + // + Status = gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &TmpDevicePath, + &DriverHandle + ); + if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) { + return NULL; + } + + // + // Retrieve all HII Handles from HII database + // + BufferSize = 0x1000; + HiiHandles = AllocatePool (BufferSize); + ASSERT (HiiHandles != NULL); + Status = mHiiDatabase->ListPackageLists ( + mHiiDatabase, + EFI_HII_PACKAGE_TYPE_ALL, + NULL, + &BufferSize, + HiiHandles + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + FreePool (HiiHandles); + HiiHandles = AllocatePool (BufferSize); + ASSERT (HiiHandles != NULL); + + Status = mHiiDatabase->ListPackageLists ( + mHiiDatabase, + EFI_HII_PACKAGE_TYPE_ALL, + NULL, + &BufferSize, + HiiHandles + ); + } + + if (EFI_ERROR (Status)) { + FreePool (HiiHandles); + return NULL; + } + + // + // Search Hii Handle by Driver Handle + // + HiiHandle = NULL; + HandleCount = BufferSize / sizeof (EFI_HII_HANDLE); + for (Index = 0; Index < HandleCount; Index++) { + Status = mHiiDatabase->GetPackageListHandle ( + mHiiDatabase, + HiiHandles[Index], + &Handle + ); + if (!EFI_ERROR (Status) && (Handle == DriverHandle)) { + HiiHandle = HiiHandles[Index]; + break; + } + } + + FreePool (HiiHandles); + return HiiHandle; +} /** Display menu and wait for user to select one menu option, then return it. @@ -1432,6 +1626,8 @@ UiDisplayMenu ( BOOLEAN NewLine; BOOLEAN Repaint; BOOLEAN SavedValue; + BOOLEAN UpArrow; + BOOLEAN DownArrow; EFI_STATUS Status; EFI_INPUT_KEY Key; LIST_ENTRY *Link; @@ -1451,6 +1647,12 @@ UiDisplayMenu ( UINT16 DefaultId; EFI_DEVICE_PATH_PROTOCOL *DevicePath; FORM_BROWSER_STATEMENT *Statement; + CHAR16 TemStr[2]; + UINT8 *DevicePathBuffer; + UINT8 DigitUint8; + UI_MENU_LIST *CurrentMenu; + UI_MENU_LIST *MenuList; + FORM_BROWSER_FORM *RefForm; CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); @@ -1463,8 +1665,8 @@ UiDisplayMenu ( DefaultId = 0; OutputString = NULL; - gUpArrow = FALSE; - gDownArrow = FALSE; + UpArrow = FALSE; + DownArrow = FALSE; SkipValue = 0; OldSkipValue = 0; MenuRefreshEntry = gMenuRefreshHead; @@ -1472,10 +1674,11 @@ UiDisplayMenu ( NextMenuOption = NULL; PreviousMenuOption = NULL; SavedMenuOption = NULL; + RefForm = NULL; ZeroMem (&Key, sizeof (EFI_INPUT_KEY)); - if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) { + if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE){ TopRow = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; Row = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; } else { @@ -1483,7 +1686,7 @@ UiDisplayMenu ( Row = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; } - Col = LocalScreen.LeftColumn; + Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS; BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - SCROLL_ARROW_HEIGHT - 1; Selection->TopRow = TopRow; @@ -1492,14 +1695,33 @@ UiDisplayMenu ( Selection->OptionCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn; Selection->Statement = NULL; - TopOfScreen = Menu.ForwardLink; + TopOfScreen = gMenuOption.ForwardLink; Repaint = TRUE; MenuOption = NULL; + // + // Find current Menu + // + CurrentMenu = UiFindMenuList (&Selection->FormSetGuid, Selection->FormId); + if (CurrentMenu == NULL) { + // + // Current menu not found, add it to the menu tree + // + CurrentMenu = UiAddMenuList (NULL, &Selection->FormSetGuid, Selection->FormId); + } + ASSERT (CurrentMenu != NULL); + + if (Selection->QuestionId == 0) { + // + // Highlight not specified, fetch it from cached menu + // + Selection->QuestionId = CurrentMenu->QuestionId; + } + // // Get user's selection // - NewPos = Menu.ForwardLink; + NewPos = gMenuOption.ForwardLink; gST->ConOut->EnableCursor (gST->ConOut, FALSE); UpdateStatusBar (REFRESH_STATUS_BAR, (UINT8) 0, TRUE); @@ -1509,7 +1731,7 @@ UiDisplayMenu ( while (TRUE) { switch (ControlFlag) { case CfInitialization: - if (IsListEmpty (&Menu)) { + if (IsListEmpty (&gMenuOption)) { ControlFlag = CfReadKey; } else { ControlFlag = CfCheckSelection; @@ -1531,25 +1753,25 @@ UiDisplayMenu ( // // Display menu // - gDownArrow = FALSE; - gUpArrow = FALSE; + DownArrow = FALSE; + UpArrow = FALSE; Row = TopRow; - Temp = SkipValue; - Temp2 = SkipValue; + Temp = (UINTN) SkipValue; + Temp2 = (UINTN) SkipValue; ClearLines ( LocalScreen.LeftColumn, LocalScreen.RightColumn, TopRow - SCROLL_ARROW_HEIGHT, BottomRow + SCROLL_ARROW_HEIGHT, - FIELD_TEXT | FIELD_BACKGROUND + PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND ); UiFreeRefreshList (); MinRefreshInterval = 0; - for (Link = TopOfScreen; Link != &Menu; Link = Link->ForwardLink) { + for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) { MenuOption = MENU_OPTION_FROM_LINK (Link); MenuOption->Row = Row; MenuOption->Col = Col; @@ -1564,13 +1786,26 @@ UiDisplayMenu ( gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND); } else { if (Statement->Operand == EFI_IFR_SUBTITLE_OP) { - gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND); + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND); } } Width = GetWidth (Statement, MenuOption->Handle); OriginalRow = Row; + if (Statement->Operand == EFI_IFR_REF_OP && + MenuOption->Col >= 2) { + // + // Print Arrow for Goto button. + // + PrintAt ( + MenuOption->Col - 2, + Row, + L"%c", + GEOMETRICSHAPE_RIGHT_TRIANGLE + ); + } + for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) { if ((Temp == 0) && (Row <= BottomRow)) { PrintStringAt (MenuOption->Col, Row, OutputString); @@ -1578,13 +1813,13 @@ UiDisplayMenu ( // // If there is more string to process print on the next row and increment the Skip value // - if (StrLen (&MenuOption->Description[Index])) { + if (StrLen (&MenuOption->Description[Index]) != 0) { if (Temp == 0) { Row++; } } - gBS->FreePool (OutputString); + FreePool (OutputString); if (Temp != 0) { Temp--; } @@ -1593,8 +1828,16 @@ UiDisplayMenu ( Temp = 0; Row = OriginalRow; - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); - ProcessOptions (Selection, MenuOption, FALSE, &OptionString); + Status = ProcessOptions (Selection, MenuOption, FALSE, &OptionString); + if (EFI_ERROR (Status)) { + // + // Repaint to clear possible error prompt pop-up + // + Repaint = TRUE; + NewLine = TRUE; + ControlFlag = CfRepaint; + break; + } if (OptionString != NULL) { if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) { @@ -1632,7 +1875,11 @@ UiDisplayMenu ( MenuRefreshEntry->Selection = Selection; MenuRefreshEntry->CurrentColumn = MenuOption->OptCol; MenuRefreshEntry->CurrentRow = MenuOption->Row; - MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND; + if (MenuOption->GrayOut) { + MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND; + } else { + MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND; + } gMenuRefreshHead = MenuRefreshEntry; } else { // @@ -1650,7 +1897,11 @@ UiDisplayMenu ( MenuRefreshEntry->Selection = Selection; MenuRefreshEntry->CurrentColumn = MenuOption->OptCol; MenuRefreshEntry->CurrentRow = MenuOption->Row; - MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND; + if (MenuOption->GrayOut) { + MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND; + } else { + MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND; + } } } @@ -1664,7 +1915,7 @@ UiDisplayMenu ( // // If there is more string to process print on the next row and increment the Skip value // - if (StrLen (&OptionString[Index])) { + if (StrLen (&OptionString[Index]) != 0) { if (Temp2 == 0) { Row++; // @@ -1680,7 +1931,7 @@ UiDisplayMenu ( } } - gBS->FreePool (OutputString); + FreePool (OutputString); if (Temp2 != 0) { Temp2--; } @@ -1689,7 +1940,7 @@ UiDisplayMenu ( Temp2 = 0; Row = OriginalRow; - gBS->FreePool (OptionString); + FreePool (OptionString); } // // If this is a text op with secondary text information @@ -1707,7 +1958,7 @@ UiDisplayMenu ( // // If there is more string to process print on the next row and increment the Skip value // - if (StrLen (&StringPtr[Index])) { + if (StrLen (&StringPtr[Index]) != 0) { if (Temp2 == 0) { Row++; // @@ -1723,15 +1974,16 @@ UiDisplayMenu ( } } - gBS->FreePool (OutputString); + FreePool (OutputString); if (Temp2 != 0) { Temp2--; } } Row = OriginalRow; - gBS->FreePool (StringPtr); + FreePool (StringPtr); } + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND); // // Need to handle the bottom of the display @@ -1745,7 +1997,7 @@ UiDisplayMenu ( if (Row > BottomRow) { if (!ValueIsScroll (FALSE, Link)) { - gDownArrow = TRUE; + DownArrow = TRUE; } Row = BottomRow + 1; @@ -1754,10 +2006,10 @@ UiDisplayMenu ( } if (!ValueIsScroll (TRUE, TopOfScreen)) { - gUpArrow = TRUE; + UpArrow = TRUE; } - if (gUpArrow) { + if (UpArrow) { gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND); PrintAt ( LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1, @@ -1765,10 +2017,10 @@ UiDisplayMenu ( L"%c", ARROW_UP ); - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND); } - if (gDownArrow) { + if (DownArrow) { gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND); PrintAt ( LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1, @@ -1776,7 +2028,7 @@ UiDisplayMenu ( L"%c", ARROW_DOWN ); - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND); } MenuOption = NULL; @@ -1799,10 +2051,10 @@ UiDisplayMenu ( Repaint = FALSE; if (Selection->QuestionId != 0) { - NewPos = Menu.ForwardLink; + NewPos = gMenuOption.ForwardLink; SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos); - while (SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId && NewPos->ForwardLink != &Menu) { + while (SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId && NewPos->ForwardLink != &gMenuOption) { NewPos = NewPos->ForwardLink; SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos); } @@ -1852,7 +2104,7 @@ UiDisplayMenu ( // gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row); ProcessOptions (Selection, MenuOption, FALSE, &OptionString); - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND); if (OptionString != NULL) { if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP) @@ -1881,22 +2133,22 @@ UiDisplayMenu ( // // If there is more string to process print on the next row and increment the Skip value // - if (StrLen (&OptionString[Index])) { + if (StrLen (&OptionString[Index]) != 0) { MenuOption->Row++; } - gBS->FreePool (OutputString); + FreePool (OutputString); } MenuOption->Row = OriginalRow; - gBS->FreePool (OptionString); + FreePool (OptionString); } else { if (NewLine) { if (MenuOption->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); + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND); } OriginalRow = MenuOption->Row; @@ -1909,15 +2161,15 @@ UiDisplayMenu ( // // If there is more string to process print on the next row and increment the Skip value // - if (StrLen (&MenuOption->Description[Index])) { + if (StrLen (&MenuOption->Description[Index]) != 0) { MenuOption->Row++; } - gBS->FreePool (OutputString); + FreePool (OutputString); } MenuOption->Row = OriginalRow; - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND); } } } @@ -1939,11 +2191,15 @@ UiDisplayMenu ( // Statement = MenuOption->ThisTag; Selection->Statement = Statement; + // + // Record highlight for current menu + // + CurrentMenu->QuestionId = Statement->QuestionId; // // Set reverse attribute // - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT); + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor)); gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row); // @@ -1953,9 +2209,13 @@ UiDisplayMenu ( // if (gMenuRefreshHead != NULL) { for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) { - MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND; + if (MenuOption->GrayOut) { + MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND; + } else { + MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND; + } if (MenuRefreshEntry->MenuOption == MenuOption) { - MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT; + MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor); } } } @@ -1987,16 +2247,16 @@ UiDisplayMenu ( // // If there is more string to process print on the next row and increment the Skip value // - if (StrLen (&OptionString[Index])) { + if (StrLen (&OptionString[Index]) != 0) { MenuOption->Row++; } - gBS->FreePool (OutputString); + FreePool (OutputString); } MenuOption->Row = OriginalRow; - gBS->FreePool (OptionString); + FreePool (OptionString); } else { if (NewLine) { OriginalRow = MenuOption->Row; @@ -2010,11 +2270,11 @@ UiDisplayMenu ( // // If there is more string to process print on the next row and increment the Skip value // - if (StrLen (&MenuOption->Description[Index])) { + if (StrLen (&MenuOption->Description[Index]) != 0) { MenuOption->Row++; } - gBS->FreePool (OutputString); + FreePool (OutputString); } MenuOption->Row = OriginalRow; @@ -2022,16 +2282,12 @@ UiDisplayMenu ( } } - if (((NewPos->ForwardLink != &Menu) && (ScreenOperation == UiDown)) || - ((NewPos->BackLink != &Menu) && (ScreenOperation == UiUp)) || - (ScreenOperation == UiNoOperation) - ) { - UpdateKeyHelp (MenuOption, FALSE); - } + UpdateKeyHelp (Selection, MenuOption, FALSE); + // // Clear reverse attribute // - gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND); } // // Repaint flag will be used when process CfUpdateHelpString, so restore its value @@ -2043,10 +2299,11 @@ UiDisplayMenu ( case CfUpdateHelpString: ControlFlag = CfPrepareToReadKey; - if ((Repaint || NewLine) && (gClassOfVfr != EFI_GENERAL_APPLICATION_SUBCLASS)) { + if (Repaint || NewLine) { // // Don't print anything if it is a NULL help token // + ASSERT(MenuOption != NULL); if (MenuOption->ThisTag->Help == 0) { StringPtr = L"\0"; } else { @@ -2094,23 +2351,20 @@ UiDisplayMenu ( Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, MinRefreshInterval); } while (Status == EFI_TIMEOUT); - if (Status == EFI_TIMEOUT) { - Key.UnicodeChar = CHAR_CARRIAGE_RETURN; - } else { - Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (Selection->Action == UI_ACTION_REFRESH_FORMSET) { // - // if we encounter error, continue to read another key in. + // IFR is updated in Callback of refresh opcode, re-parse it // - if (EFI_ERROR (Status)) { - ControlFlag = CfReadKey; - continue; - } + Selection->Statement = NULL; + return EFI_SUCCESS; } - if (IsListEmpty (&Menu) && Key.UnicodeChar != CHAR_NULL) { - // - // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset - // + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + // + // If we encounter error, continue to read another key in. + // + if (EFI_ERROR (Status)) { + ControlFlag = CfReadKey; break; } @@ -2126,6 +2380,16 @@ UiDisplayMenu ( // case '+': case '-': + // + // If the screen has no menu items, and the user didn't select UiReset + // ignore the selection and go back to reading keys. + // + if(IsListEmpty (&gMenuOption)) { + ControlFlag = CfReadKey; + break; + } + + ASSERT(MenuOption != NULL); Statement = MenuOption->ThisTag; if ((Statement->Operand == EFI_IFR_DATE_OP) || (Statement->Operand == EFI_IFR_TIME_OP) @@ -2137,7 +2401,18 @@ UiDisplayMenu ( gDirection = SCAN_LEFT; } Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString); - SafeFreePool (OptionString); + if (EFI_ERROR (Status)) { + // + // Repaint to clear possible error prompt pop-up + // + Repaint = TRUE; + NewLine = TRUE; + } else { + Selection->Action = UI_ACTION_REFRESH_FORM; + } + if (OptionString != NULL) { + FreePool (OptionString); + } } break; @@ -2151,7 +2426,17 @@ UiDisplayMenu ( break; case ' ': - if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) { + if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) { + // + // If the screen has no menu items, and the user didn't select UiReset + // ignore the selection and go back to reading keys. + // + if(IsListEmpty (&gMenuOption)) { + ControlFlag = CfReadKey; + break; + } + + ASSERT(MenuOption != NULL); if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut) { ScreenOperation = UiSelect; } @@ -2159,9 +2444,7 @@ UiDisplayMenu ( 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)) || + if (((Key.ScanCode == SCAN_F9) && ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE)) || ((Key.ScanCode == SCAN_F10) && ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN)) ) { // @@ -2186,35 +2469,29 @@ UiDisplayMenu ( break; case CfScreenOperation: - if (ScreenOperation != UiPrevious && ScreenOperation != UiReset) { + if (ScreenOperation != UiReset) { // - // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset + // If the screen has no menu items, and the user didn't select UiReset // ignore the selection and go back to reading keys. // - if (IsListEmpty (&Menu)) { + if (IsListEmpty (&gMenuOption)) { 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) { + for (Link = gMenuOption.ForwardLink; Link != &gMenuOption; Link = Link->ForwardLink) { NextMenuOption = MENU_OPTION_FROM_LINK (Link); if (IsSelectable (NextMenuOption)) { break; } } - if (Link == &Menu) { + if (Link == &gMenuOption) { ControlFlag = CfPrepareToReadKey; break; } - } else if (ScreenOperation == UiReset) { - // - // Press ESC to exit FormSet - // - Selection->Action = UI_ACTION_EXIT; - Selection->Statement = NULL; } for (Index = 0; @@ -2228,34 +2505,12 @@ UiDisplayMenu ( } break; - case CfUiPrevious: - ControlFlag = CfCheckSelection; - - if (IsListEmpty (&gMenuList)) { - Selection->Action = UI_ACTION_NONE; - if (IsListEmpty (&Menu)) { - ControlFlag = CfReadKey; - } - break; - } - - // - // Remove the Cached page entry - // - UiRemoveMenuListEntry (Selection); - - Selection->Action = UI_ACTION_REFRESH_FORM; - Selection->Statement = NULL; - break; - case CfUiSelect: ControlFlag = CfCheckSelection; + ASSERT(MenuOption != NULL); Statement = MenuOption->ThisTag; - if ((Statement->Operand == EFI_IFR_TEXT_OP) || - (Statement->Operand == EFI_IFR_DATE_OP) || - (Statement->Operand == EFI_IFR_TIME_OP) || - (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) { + if (Statement->Operand == EFI_IFR_TEXT_OP) { break; } @@ -2270,7 +2525,6 @@ UiDisplayMenu ( // // Goto another Hii Package list // - ControlFlag = CfUiReset; Selection->Action = UI_ACTION_REFRESH_FORMSET; StringPtr = GetToken (Statement->RefDevicePath, Selection->FormSet->HiiHandle); @@ -2284,9 +2538,29 @@ UiDisplayMenu ( } BufferSize = StrLen (StringPtr) / 2; DevicePath = AllocatePool (BufferSize); + ASSERT (DevicePath != NULL); + + // + // Convert from Device Path String to DevicePath Buffer in the reverse order. + // + DevicePathBuffer = (UINT8 *) DevicePath; + for (Index = 0; StringPtr[Index] != L'\0'; Index ++) { + TemStr[0] = StringPtr[Index]; + DigitUint8 = (UINT8) StrHexToUint64 (TemStr); + if (DigitUint8 == 0 && TemStr[0] != L'0') { + // + // Invalid Hex Char as the tail. + // + break; + } + if ((Index & 1) == 0) { + DevicePathBuffer [Index/2] = DigitUint8; + } else { + DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8); + } + } - HexStringToBuffer ((UINT8 *) DevicePath, &BufferSize, StringPtr); - Selection->Handle = HiiLibDevicePathToHiiHandle (DevicePath); + Selection->Handle = DevicePathToHiiHandle (DevicePath); if (Selection->Handle == NULL) { // // If target Hii Handle not found, exit @@ -2296,8 +2570,8 @@ UiDisplayMenu ( break; } - gBS->FreePool (StringPtr); - gBS->FreePool (DevicePath); + FreePool (StringPtr); + FreePool (DevicePath); CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID)); Selection->FormId = Statement->RefFormId; @@ -2306,22 +2580,48 @@ UiDisplayMenu ( // // Goto another Formset, check for uncommitted data // - ControlFlag = CfUiReset; Selection->Action = UI_ACTION_REFRESH_FORMSET; CopyMem (&Selection->FormSetGuid, &Statement->RefFormSetId, sizeof (EFI_GUID)); Selection->FormId = Statement->RefFormId; Selection->QuestionId = Statement->RefQuestionId; } else if (Statement->RefFormId != 0) { + // + // Check whether target From is suppressed. + // + RefForm = IdToForm (Selection->FormSet, Statement->RefFormId); + + if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) { + Status = EvaluateExpression (Selection->FormSet, RefForm, RefForm->SuppressExpression); + if (EFI_ERROR (Status)) { + return Status; + } + + if (RefForm->SuppressExpression->Result.Value.b) { + // + // Form is suppressed. + // + do { + CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + Repaint = TRUE; + break; + } + } + // // Goto another form inside this formset, // Selection->Action = UI_ACTION_REFRESH_FORM; // - // Link current form so that we can always go back when someone hits the UiPrevious + // Link current form so that we can always go back when someone hits the ESC // - UiAddMenuListEntry (Selection); + MenuList = UiFindMenuList (&Selection->FormSetGuid, Statement->RefFormId); + if (MenuList == NULL) { + MenuList = UiAddMenuList (CurrentMenu, &Selection->FormSetGuid, Statement->RefFormId); + } Selection->FormId = Statement->RefFormId; Selection->QuestionId = Statement->RefQuestionId; @@ -2369,42 +2669,64 @@ UiDisplayMenu ( // // Editable Questions: oneof, ordered list, checkbox, numeric, string, password // - UpdateKeyHelp (MenuOption, TRUE); + UpdateKeyHelp (Selection, MenuOption, TRUE); Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString); if (EFI_ERROR (Status)) { Repaint = TRUE; NewLine = TRUE; - break; + UpdateKeyHelp (Selection, MenuOption, FALSE); + } else { + Selection->Action = UI_ACTION_REFRESH_FORM; } if (OptionString != NULL) { - PrintStringAt (LocalScreen.LeftColumn + gPromptBlockWidth + 1, MenuOption->Row, OptionString); - gBS->FreePool (OptionString); + FreePool (OptionString); } - - Selection->Action = UI_ACTION_REFRESH_FORM; break; } break; case CfUiReset: // - // We are going to leave current FormSet, so check uncommited data in this FormSet + // We come here when someone press ESC // ControlFlag = CfCheckSelection; - if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) { + if (CurrentMenu->Parent != NULL) { + // + // we have a parent, so go to the parent menu + // + if (CompareGuid (&CurrentMenu->FormSetGuid, &CurrentMenu->Parent->FormSetGuid)) { + // + // The parent menu and current menu are in the same formset + // + Selection->Action = UI_ACTION_REFRESH_FORM; + } else { + Selection->Action = UI_ACTION_REFRESH_FORMSET; + } + Selection->Statement = NULL; + + Selection->FormId = CurrentMenu->Parent->FormId; + Selection->QuestionId = CurrentMenu->Parent->QuestionId; + + // + // Clear highlight record for this menu + // + CurrentMenu->QuestionId = 0; + break; + } + + if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) { // - // There is no parent menu for FrontPage + // We never exit FrontPage, so skip the ESC // Selection->Action = UI_ACTION_NONE; - Selection->Statement = MenuOption->ThisTag; break; } // - // If NV flag is up, prompt user + // We are going to leave current FormSet, so check uncommited data in this FormSet // if (gNvUpdateRequired) { Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); @@ -2412,8 +2734,11 @@ UiDisplayMenu ( YesResponse = gYesResponse[0]; NoResponse = gNoResponse[0]; + // + // If NV flag is up, prompt user + // do { - CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gAreYouSure, gEmptyString); + CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gAreYouSure, gEmptyString); } while ( (Key.ScanCode != SCAN_ESC) && @@ -2421,33 +2746,40 @@ UiDisplayMenu ( ((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 { + if (Key.ScanCode == SCAN_ESC) { + // + // User hits the ESC key + // Repaint = TRUE; NewLine = TRUE; Selection->Action = UI_ACTION_NONE; break; } + + // + // If the user hits the YesResponse key + // + if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) { + Status = SubmitForm (Selection->FormSet, Selection->Form); + } } - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); - gST->ConOut->EnableCursor (gST->ConOut, TRUE); + Selection->Action = UI_ACTION_EXIT; + Selection->Statement = NULL; + CurrentMenu->QuestionId = 0; - UiFreeMenuList (); - gST->ConOut->ClearScreen (gST->ConOut); return EFI_SUCCESS; case CfUiLeft: ControlFlag = CfCheckSelection; + ASSERT(MenuOption != NULL); if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) { if (MenuOption->Sequence != 0) { // // In the middle or tail of the Date/Time op-code set, go left. // + ASSERT(NewPos != NULL); NewPos = NewPos->BackLink; } } @@ -2455,11 +2787,13 @@ UiDisplayMenu ( case CfUiRight: ControlFlag = CfCheckSelection; + ASSERT(MenuOption != NULL); if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) { if (MenuOption->Sequence != 2) { // // In the middle or tail of the Date/Time op-code set, go left. // + ASSERT(NewPos != NULL); NewPos = NewPos->ForwardLink; } } @@ -2470,7 +2804,8 @@ UiDisplayMenu ( SavedListEntry = TopOfScreen; - if (NewPos->BackLink != &Menu) { + ASSERT(NewPos != NULL); + if (NewPos->BackLink != &gMenuOption) { NewLine = TRUE; // // Adjust Date/Time position before we advance forward. @@ -2480,10 +2815,11 @@ UiDisplayMenu ( // // Caution that we have already rewind to the top, don't go backward in this situation. // - if (NewPos->BackLink != &Menu) { + if (NewPos->BackLink != &gMenuOption) { NewPos = NewPos->BackLink; } + Difference = MoveToNextStatement (TRUE, &NewPos); PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos); DistanceValue = PreviousMenuOption->Skip; @@ -2494,36 +2830,26 @@ UiDisplayMenu ( // checking can be done. // DistanceValue += AdjustDateAndTimePosition (TRUE, &NewPos); - - // - // Check the previous menu entry to see if it was a zero-length advance. If it was, - // don't worry about a redraw. - // - if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) { - Repaint = TRUE; - TopOfScreen = NewPos; - } - - Difference = MoveToNextStatement (TRUE, &NewPos); - if ((INTN) MenuOption->Row - (INTN) DistanceValue < (INTN) TopRow) { - if (Difference > 0) { - // - // Previous focus MenuOption is above the TopOfScreen, so we need to scroll - // - TopOfScreen = NewPos; - Repaint = TRUE; - } - } + + ASSERT (MenuOption != NULL); if (Difference < 0) { // // We want to goto previous MenuOption, but finally we go down. // it means that we hit the begining MenuOption that can be focused // so we simply scroll to the top // - if (SavedListEntry != Menu.ForwardLink) { - TopOfScreen = Menu.ForwardLink; + if (SavedListEntry != gMenuOption.ForwardLink) { + TopOfScreen = gMenuOption.ForwardLink; Repaint = TRUE; } + } else if ((INTN) MenuOption->Row - (INTN) DistanceValue - Difference < (INTN) TopRow) { + // + // Previous focus MenuOption is above the TopOfScreen, so we need to scroll + // + TopOfScreen = NewPos; + Repaint = TRUE; + SkipValue = 0; + OldSkipValue = 0; } // @@ -2551,7 +2877,8 @@ UiDisplayMenu ( case CfUiPageUp: ControlFlag = CfCheckSelection; - if (NewPos->BackLink == &Menu) { + ASSERT(NewPos != NULL); + if (NewPos->BackLink == &gMenuOption) { NewLine = FALSE; Repaint = FALSE; break; @@ -2562,7 +2889,7 @@ UiDisplayMenu ( Link = TopOfScreen; PreviousMenuOption = MENU_OPTION_FROM_LINK (Link); Index = BottomRow; - while ((Index >= TopRow) && (Link->BackLink != &Menu)) { + while ((Index >= TopRow) && (Link->BackLink != &gMenuOption)) { Index = Index - PreviousMenuOption->Skip; Link = Link->BackLink; PreviousMenuOption = MENU_OPTION_FROM_LINK (Link); @@ -2580,7 +2907,7 @@ UiDisplayMenu ( // This happens when there is no MenuOption can be focused from // Current MenuOption to the first MenuOption // - TopOfScreen = Menu.ForwardLink; + TopOfScreen = gMenuOption.ForwardLink; } Index += Difference; if (Index < TopRow) { @@ -2605,7 +2932,8 @@ UiDisplayMenu ( case CfUiPageDown: ControlFlag = CfCheckSelection; - if (NewPos->ForwardLink == &Menu) { + ASSERT (NewPos != NULL); + if (NewPos->ForwardLink == &gMenuOption) { NewLine = FALSE; Repaint = FALSE; break; @@ -2616,7 +2944,7 @@ UiDisplayMenu ( Link = TopOfScreen; NextMenuOption = MENU_OPTION_FROM_LINK (Link); Index = TopRow; - while ((Index <= BottomRow) && (Link->ForwardLink != &Menu)) { + while ((Index <= BottomRow) && (Link->ForwardLink != &gMenuOption)) { Index = Index + NextMenuOption->Skip; Link = Link->ForwardLink; NextMenuOption = MENU_OPTION_FROM_LINK (Link); @@ -2661,18 +2989,19 @@ UiDisplayMenu ( SavedListEntry = NewPos; DistanceValue = AdjustDateAndTimePosition (FALSE, &NewPos); - if (NewPos->ForwardLink != &Menu) { + if (NewPos->ForwardLink != &gMenuOption) { MenuOption = MENU_OPTION_FROM_LINK (NewPos); NewLine = TRUE; NewPos = NewPos->ForwardLink; - NextMenuOption = MENU_OPTION_FROM_LINK (NewPos); - DistanceValue += NextMenuOption->Skip; DistanceValue += MoveToNextStatement (FALSE, &NewPos); + NextMenuOption = MENU_OPTION_FROM_LINK (NewPos); + // // An option might be multi-line, so we need to reflect that data in the overall skip value // - UpdateOptionSkipLines (Selection, NextMenuOption, &OptionString, SkipValue); + UpdateOptionSkipLines (Selection, NextMenuOption, &OptionString, (UINTN) SkipValue); + DistanceValue += NextMenuOption->Skip; Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1; if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) && @@ -2714,26 +3043,13 @@ UiDisplayMenu ( // // 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 - ) { + while (Difference >= (INTN) SavedMenuOption->Skip) { // // Since the Difference is greater than or equal to this op-code's skip value, skip it // + Difference = Difference - (INTN) SavedMenuOption->Skip; TopOfScreen = TopOfScreen->ForwardLink; SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); - if (Difference < (INTN) SavedMenuOption->Skip) { - Difference = SavedMenuOption->Skip - Difference - 1; - break; - } else { - if (Difference == (INTN) SavedMenuOption->Skip) { - TopOfScreen = TopOfScreen->ForwardLink; - SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); - Difference = SavedMenuOption->Skip - Difference; - break; - } - } } // // Since we will act on this op-code in the next routine, and increment the @@ -2766,6 +3082,8 @@ UiDisplayMenu ( } else { SkipValue++; } + } else if (SavedMenuOption->Skip == 1) { + SkipValue = 0; } else { SkipValue = 0; TopOfScreen = TopOfScreen->ForwardLink; @@ -2809,6 +3127,7 @@ UiDisplayMenu ( Status = SubmitForm (Selection->FormSet, Selection->Form); if (!EFI_ERROR (Status)) { + ASSERT(MenuOption != NULL); UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE); UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE); } else { @@ -2823,6 +3142,12 @@ UiDisplayMenu ( case CfUiDefault: ControlFlag = CfCheckSelection; + if (!Selection->FormEditable) { + // + // This Form is not editable, ignore the F9 (reset to default) + // + break; + } Status = ExtractFormDefault (Selection->FormSet, Selection->Form, DefaultId); @@ -2834,6 +3159,7 @@ UiDisplayMenu ( // Show NV update flag on status bar // gNvUpdateRequired = TRUE; + gResetRequired = TRUE; } break;