/** This function invokes Boot Manager. If all devices have not a chance to be connected, the connect all will be triggered. It then enumerate all boot options. If a boot option from the Boot Manager page is selected, Boot Manager will boot from this boot option. **/ VOID UpdateBootManager ( VOID ) { UINTN Index; EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; UINTN BootOptionCount; EFI_STRING_ID Token; CHAR16 *HelpString; EFI_STRING_ID HelpToken; UINT16 *TempStr; EFI_HII_HANDLE HiiHandle; UINTN TempSize; VOID *StartOpCodeHandle; VOID *EndOpCodeHandle; EFI_IFR_GUID_LABEL *StartLabel; EFI_IFR_GUID_LABEL *EndLabel; UINT16 DeviceType; BOOLEAN IsLegacyOption; BOOLEAN NeedEndOp; UINTN MaxLen; DeviceType = (UINT16) -1; EfiBootManagerConnectAll (); // // for better user experience // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option // EfiBootManagerRefreshAllBootOption (); // // BdsDxe doesn't group the legacy boot options for the same device type // It's UI's choice. // GroupMultipleLegacyBootOption4SameType (); BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); HiiHandle = gBootManagerPrivate.HiiHandle; // // Allocate space for creation of UpdateData Buffer // StartOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (StartOpCodeHandle != NULL); EndOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (EndOpCodeHandle != NULL); // // Create Hii Extend Label OpCode as the start opcode // StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; StartLabel->Number = LABEL_BOOT_OPTION; // // Create Hii Extend Label OpCode as the end opcode // EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; EndLabel->Number = LABEL_BOOT_OPTION_END; mKeyInput = 0; NeedEndOp = FALSE; for (Index = 0; Index < BootOptionCount; Index++) { // // At this stage we are creating a menu entry, thus the Keys are reproduceable // mKeyInput++; // // Don't display the hidden/inactive boot option // if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) { continue; } // // Group the legacy boot option in the sub title created dynamically // IsLegacyOption = (BOOLEAN) ( (DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) && (DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP) ); if (!IsLegacyOption && NeedEndOp) { NeedEndOp = FALSE; HiiCreateEndOpCode (StartOpCodeHandle); } if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) { if (NeedEndOp) { HiiCreateEndOpCode (StartOpCodeHandle); } DeviceType = ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType; Token = HiiSetString ( HiiHandle, 0, mDeviceTypeStr[ MIN (DeviceType & 0xF, sizeof (mDeviceTypeStr) / sizeof (mDeviceTypeStr[0]) - 1) ], NULL ); HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1); NeedEndOp = TRUE; } ASSERT (BootOption[Index].Description != NULL); Token = HiiSetString (HiiHandle, 0, BootOption[Index].Description, NULL); TempStr = BmDevicePathToStr (BootOption[Index].FilePath); TempSize = StrSize (TempStr); HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : ")); MaxLen = (TempSize + StrSize (L"Device Path : "))/sizeof(CHAR16); ASSERT (HelpString != NULL); StrCatS (HelpString, MaxLen, L"Device Path : "); StrCatS (HelpString, MaxLen, TempStr); HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL); HiiCreateActionOpCode ( StartOpCodeHandle, mKeyInput, Token, HelpToken, EFI_IFR_FLAG_CALLBACK, 0 ); } if (NeedEndOp) { HiiCreateEndOpCode (StartOpCodeHandle); } HiiUpdateForm ( HiiHandle, &mBootManagerGuid, BOOT_MANAGER_FORM_ID, StartOpCodeHandle, EndOpCodeHandle ); HiiFreeOpCodeHandle (StartOpCodeHandle); HiiFreeOpCodeHandle (EndOpCodeHandle); EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); }
/** Create UEFI HII Text Opcode from a Framework HII Text Opcode. @param UefiUpdateDataHandle The newly created UEFI HII opcode is appended to UefiUpdateDataHandle. @param FwOpcode The input Framework Opcode. @retval NULL There is not enough space left in Buffer to add the opcode. @retval Other A pointer to the created opcode. **/ UINT8 * F2UCreateTextOpCode ( IN OUT VOID *UefiUpdateDataHandle, IN CONST FRAMEWORK_EFI_IFR_TEXT *FwOpcode ) { EFI_IFR_TEXT UTextOpCode; if ((FwOpcode->Flags & EFI_IFR_FLAG_INTERACTIVE) == 0) { ZeroMem (&UTextOpCode, sizeof(UTextOpCode)); UTextOpCode.Header.OpCode = EFI_IFR_TEXT_OP; UTextOpCode.Header.Length = (UINT8) sizeof (EFI_IFR_TEXT); UTextOpCode.Statement.Help = FwOpcode->Help; UTextOpCode.Statement.Prompt = FwOpcode->Text; UTextOpCode.TextTwo = FwOpcode->TextTwo; return HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UTextOpCode, sizeof(UTextOpCode)); } else { // // Iteractive Text Opcode is EFI_IFR_ACTION // return HiiCreateActionOpCode (UefiUpdateDataHandle, FwOpcode->Key, FwOpcode->Text, FwOpcode->Help, EFI_IFR_FLAG_CALLBACK, 0); } }
/** Create the "Apply changes" and "Discard changes" tags. And ensure user can return to the main page. @param CallbackData The BMM context data. **/ VOID UpdatePageEnd ( IN BMM_CALLBACK_DATA *CallbackData ) { // // Create the "Apply changes" and "Discard changes" tags. // if (CallbackData->BmmAskSaveOrNot) { HiiCreateSubTitleOpCode ( mStartOpCodeHandle, STRING_TOKEN (STR_NULL_STRING), 0, 0, 0 ); HiiCreateActionOpCode ( mStartOpCodeHandle, KEY_VALUE_SAVE_AND_EXIT, STRING_TOKEN (STR_SAVE_AND_EXIT), STRING_TOKEN (STR_NULL_STRING), EFI_IFR_FLAG_CALLBACK, 0 ); } // // Ensure user can return to the main page. // HiiCreateActionOpCode ( mStartOpCodeHandle, KEY_VALUE_NO_SAVE_AND_EXIT, STRING_TOKEN (STR_NO_SAVE_AND_EXIT), STRING_TOKEN (STR_NULL_STRING), EFI_IFR_FLAG_CALLBACK, 0 ); HiiUpdateForm ( CallbackData->BmmHiiHandle, &gBootMaintFormSetGuid, CallbackData->BmmCurrentPageId, mStartOpCodeHandle, // Label CallbackData->BmmCurrentPageId mEndOpCodeHandle // LABEL_END ); }
/** Update the File Explore page. **/ VOID LibUpdateFileExplorePage ( VOID ) { UINTN Index; MENU_ENTRY *NewMenuEntry; FILE_CONTEXT *NewFileContext; MENU_OPTION *MenuOption; NewMenuEntry = NULL; NewFileContext = NULL; LibRefreshUpdateData (); MenuOption = gFileExplorerPrivate.FsOptionMenu; for (Index = 0; Index < MenuOption->MenuNumber; Index++) { NewMenuEntry = LibGetMenuEntry (MenuOption, Index); NewFileContext = (FILE_CONTEXT *) NewMenuEntry->VariableContext; if (!NewFileContext->IsDir) { // // Create Text opcode for directory, also create Text opcode for file in FileExplorerStateBootFromFile. // HiiCreateActionOpCode ( mLibStartOpCodeHandle, (UINT16) (FILE_OPTION_OFFSET + Index), NewMenuEntry->DisplayStringToken, STRING_TOKEN (STR_NULL_STRING), EFI_IFR_FLAG_CALLBACK, 0 ); } else { // // Create Goto opcode for file in FileExplorerStateAddBootOption or FileExplorerStateAddDriverOptionState. // HiiCreateGotoOpCode ( mLibStartOpCodeHandle, FORM_FILE_EXPLORER_ID, NewMenuEntry->DisplayStringToken, STRING_TOKEN (STR_NULL_STRING), EFI_IFR_FLAG_CALLBACK, (UINT16) (FILE_OPTION_OFFSET + Index) ); } } HiiUpdateForm ( gFileExplorerPrivate.FeHiiHandle, &FileExplorerGuid, FORM_FILE_EXPLORER_ID, mLibStartOpCodeHandle, // Label FORM_FILE_EXPLORER_ID mLibEndOpCodeHandle // LABEL_END ); }
/** Create an action OpCode with QuestionID and DevicePath on a given OpCodeHandle. @param[in] QuestionID The question ID. @param[in] DevicePath Points to device path. @param[in] OpCodeHandle Points to container for dynamic created opcodes. **/ VOID AddDevicePath ( IN UINTN QuestionID, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN VOID *OpCodeHandle ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *Next; EFI_STRING_ID NameID; EFI_STRING DriverName; EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathText; // // Locate device path to text protocol. // Status = gBS->LocateProtocol ( &gEfiDevicePathToTextProtocolGuid, NULL, (VOID **) &DevicePathText ); if (EFI_ERROR (Status)) { return ; } // // Get driver file name node. // Next = DevicePath; while (!IsDevicePathEnd (Next)) { DevicePath = Next; Next = NextDevicePathNode (Next); } // // Display the device path in form. // DriverName = DevicePathText->ConvertDevicePathToText (DevicePath, FALSE, FALSE); NameID = HiiSetString (mCallbackInfo->HiiHandle, 0, DriverName, NULL); FreePool (DriverName); if (NameID == 0) { return ; } HiiCreateActionOpCode ( OpCodeHandle, // Container for dynamic created opcodes (UINT16) QuestionID, // Question ID NameID, // Prompt text STRING_TOKEN (STR_NULL_STRING), // Help text EFI_IFR_FLAG_CALLBACK, // Question flag 0 // Action String ID ); }
/** Create Reset menu in the front page. @param[in] HiiHandle The hii handle for the Uiapp driver. @param[in] StartOpCodeHandle The opcode handle to save the new opcode. **/ VOID UiCreateResetMenu ( IN EFI_HII_HANDLE HiiHandle, IN VOID *StartOpCodeHandle ) { HiiCreateActionOpCode ( StartOpCodeHandle, FRONT_PAGE_KEY_RESET, STRING_TOKEN (STR_RESET_STRING), STRING_TOKEN (STR_RESET_STRING), EFI_IFR_FLAG_CALLBACK, 0 ); }
/** Create continue menu in the front page. @param[in] HiiHandle The hii handle for the Uiapp driver. @param[in] StartOpCodeHandle The opcode handle to save the new opcode. **/ VOID UiCreateContinueMenu ( IN EFI_HII_HANDLE HiiHandle, IN VOID *StartOpCodeHandle ) { HiiCreateActionOpCode ( StartOpCodeHandle, FRONT_PAGE_KEY_CONTINUE, STRING_TOKEN (STR_CONTINUE_PROMPT), STRING_TOKEN (STR_CONTINUE_PROMPT), EFI_IFR_FLAG_CALLBACK, 0 ); }
/** Add a username item in form. @param[in] User Points to the user profile whose username is added. @param[in] Index The index of the user in the user name list @param[in] OpCodeHandle Points to container for dynamic created opcodes. **/ VOID AddUserToForm ( IN EFI_USER_PROFILE_HANDLE User, IN UINT16 Index, IN VOID *OpCodeHandle ) { EFI_STRING_ID NameId; // // Get user name // NameId = GetUserName (User); if (NameId == 0) { return ; } // // Create user name option. // switch (Index & KEY_FIRST_FORM_MASK) { case KEY_MODIFY_USER: HiiCreateGotoOpCode ( OpCodeHandle, // Container for dynamic created opcodes FORMID_USER_INFO, // Target Form ID NameId, // Prompt text STRING_TOKEN (STR_NULL_STRING), // Help text EFI_IFR_FLAG_CALLBACK, // Question flag Index // Question ID ); break; case KEY_DEL_USER: HiiCreateActionOpCode ( OpCodeHandle, // Container for dynamic created opcodes Index, // Question ID NameId, // Prompt text STRING_TOKEN (STR_NULL_STRING), // Help text EFI_IFR_FLAG_CALLBACK, // Question flag 0 // Action String ID ); break; default: break; } }
/** Update the File Explore page. **/ VOID LibUpdateFileExplorePage ( VOID ) { UINTN Index; MENU_ENTRY *NewMenuEntry; FILE_CONTEXT *NewFileContext; MENU_OPTION *MenuOption; BOOLEAN CreateNewFile; NewMenuEntry = NULL; NewFileContext = NULL; CreateNewFile = FALSE; LibRefreshUpdateData (); MenuOption = gFileExplorerPrivate.FsOptionMenu; mQuestionIdUpdate += QUESTION_ID_UPDATE_STEP; for (Index = 0; Index < MenuOption->MenuNumber; Index++) { NewMenuEntry = LibGetMenuEntry (MenuOption, Index); NewFileContext = (FILE_CONTEXT *) NewMenuEntry->VariableContext; if (!NewFileContext->IsRoot && !CreateNewFile) { HiiCreateGotoOpCode ( mLibStartOpCodeHandle, FORM_ADD_NEW_FILE_ID, STRING_TOKEN (STR_NEW_FILE), STRING_TOKEN (STR_NEW_FILE_HELP), EFI_IFR_FLAG_CALLBACK, (UINT16) (mNewFileQuestionId++) ); HiiCreateGotoOpCode ( mLibStartOpCodeHandle, FORM_ADD_NEW_FOLDER_ID, STRING_TOKEN (STR_NEW_FOLDER), STRING_TOKEN (STR_NEW_FOLDER_HELP), EFI_IFR_FLAG_CALLBACK, (UINT16) (mNewFolderQuestionId++) ); HiiCreateTextOpCode( mLibStartOpCodeHandle, STRING_TOKEN (STR_NULL_STRING), STRING_TOKEN (STR_NULL_STRING), 0 ); CreateNewFile = TRUE; } if (!NewFileContext->IsDir) { // // Create Text opcode for directory, also create Text opcode for file in FileExplorerStateBootFromFile. // HiiCreateActionOpCode ( mLibStartOpCodeHandle, (UINT16) (FILE_OPTION_OFFSET + Index + mQuestionIdUpdate), NewMenuEntry->DisplayStringToken, STRING_TOKEN (STR_NULL_STRING), EFI_IFR_FLAG_CALLBACK, 0 ); } else { // // Create Goto opcode for file in FileExplorerStateAddBootOption or FileExplorerStateAddDriverOptionState. // HiiCreateGotoOpCode ( mLibStartOpCodeHandle, FORM_FILE_EXPLORER_ID, NewMenuEntry->DisplayStringToken, STRING_TOKEN (STR_NULL_STRING), EFI_IFR_FLAG_CALLBACK, (UINT16) (FILE_OPTION_OFFSET + Index + mQuestionIdUpdate) ); } } HiiUpdateForm ( gFileExplorerPrivate.FeHiiHandle, &FileExplorerGuid, FORM_FILE_EXPLORER_ID, mLibStartOpCodeHandle, // Label FORM_FILE_EXPLORER_ID mLibEndOpCodeHandle // LABEL_END ); }
/** Update the File Explore page. @param CallbackData The BMM context data. @param MenuOption Pointer to menu options to display. **/ VOID UpdateFileExplorePage ( IN BMM_CALLBACK_DATA *CallbackData, BM_MENU_OPTION *MenuOption ) { UINTN Index; BM_MENU_ENTRY *NewMenuEntry; BM_FILE_CONTEXT *NewFileContext; EFI_FORM_ID FormId; NewMenuEntry = NULL; NewFileContext = NULL; FormId = 0; RefreshUpdateData (); mStartLabel->Number = FORM_FILE_EXPLORER_ID; for (Index = 0; Index < MenuOption->MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index); NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; if (NewFileContext->IsBootLegacy) { continue; } if ((NewFileContext->IsDir) || (FileExplorerStateBootFromFile == CallbackData->FeCurrentState)) { // // Create Text opcode for directory, also create Text opcode for file in FileExplorerStateBootFromFile. // HiiCreateActionOpCode ( mStartOpCodeHandle, (UINT16) (FILE_OPTION_OFFSET + Index), NewMenuEntry->DisplayStringToken, STRING_TOKEN (STR_NULL_STRING), EFI_IFR_FLAG_CALLBACK, 0 ); } else { // // Create Goto opcode for file in FileExplorerStateAddBootOption or FileExplorerStateAddDriverOptionState. // if (FileExplorerStateAddBootOption == CallbackData->FeCurrentState) { FormId = FORM_BOOT_ADD_DESCRIPTION_ID; } else if (FileExplorerStateAddDriverOptionState == CallbackData->FeCurrentState) { FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; } HiiCreateGotoOpCode ( mStartOpCodeHandle, FormId, NewMenuEntry->DisplayStringToken, STRING_TOKEN (STR_NULL_STRING), EFI_IFR_FLAG_CALLBACK, (UINT16) (FILE_OPTION_OFFSET + Index) ); } } HiiUpdateForm ( CallbackData->FeHiiHandle, &mFileExplorerGuid, FORM_FILE_EXPLORER_ID, mStartOpCodeHandle, // Label FORM_FILE_EXPLORER_ID mEndOpCodeHandle // LABEL_END ); }
/** This function invokes Boot Manager. If all devices have not a chance to be connected, the connect all will be triggered. It then enumerate all boot options. If a boot option from the Boot Manager page is selected, Boot Manager will boot from this boot option. **/ VOID CallBootManager ( VOID ) { EFI_STATUS Status; BDS_COMMON_OPTION *Option; LIST_ENTRY *Link; CHAR16 *ExitData; UINTN ExitDataSize; EFI_STRING_ID Token; EFI_INPUT_KEY Key; CHAR16 *HelpString; UINTN HelpSize; EFI_STRING_ID HelpToken; UINT16 *TempStr; EFI_HII_HANDLE HiiHandle; EFI_BROWSER_ACTION_REQUEST ActionRequest; VOID *StartOpCodeHandle; VOID *EndOpCodeHandle; EFI_IFR_GUID_LABEL *StartLabel; EFI_IFR_GUID_LABEL *EndLabel; UINT16 DeviceType; BOOLEAN IsLegacyOption; BOOLEAN NeedEndOp; DeviceType = (UINT16) -1; gOption = NULL; InitializeListHead (&mBootOptionsList); // // Connect all prior to entering the platform setup menu. // if (!gConnectAllHappened) { BdsLibConnectAllDriversToAllControllers (); gConnectAllHappened = TRUE; } BdsLibEnumerateAllBootOption (&mBootOptionsList); // // Group the legacy boot options for the same device type // GroupMultipleLegacyBootOption4SameType (); InitializeListHead (&mBootOptionsList); BdsLibBuildOptionFromVar (&mBootOptionsList, L"BootOrder"); HiiHandle = gBootManagerPrivate.HiiHandle; // // Allocate space for creation of UpdateData Buffer // StartOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (StartOpCodeHandle != NULL); EndOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (EndOpCodeHandle != NULL); // // Create Hii Extend Label OpCode as the start opcode // StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; StartLabel->Number = LABEL_BOOT_OPTION; // // Create Hii Extend Label OpCode as the end opcode // EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; EndLabel->Number = LABEL_BOOT_OPTION_END; mKeyInput = 0; NeedEndOp = FALSE; for (Link = GetFirstNode (&mBootOptionsList); !IsNull (&mBootOptionsList, Link); Link = GetNextNode (&mBootOptionsList, Link)) { Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); // // At this stage we are creating a menu entry, thus the Keys are reproduceable // mKeyInput++; // // Don't display the hidden/inactive boot option // if (((Option->Attribute & LOAD_OPTION_HIDDEN) != 0) || ((Option->Attribute & LOAD_OPTION_ACTIVE) == 0)) { continue; } // // Group the legacy boot option in the sub title created dynamically // IsLegacyOption = (BOOLEAN) ( (DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) && (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP) ); if (!IsLegacyOption && NeedEndOp) { NeedEndOp = FALSE; HiiCreateEndOpCode (StartOpCodeHandle); } if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType) { if (NeedEndOp) { HiiCreateEndOpCode (StartOpCodeHandle); } DeviceType = ((BBS_BBS_DEVICE_PATH *) Option->DevicePath)->DeviceType; Token = HiiSetString ( HiiHandle, 0, mDeviceTypeStr[ MIN (DeviceType & 0xF, ARRAY_SIZE (mDeviceTypeStr) - 1) ], NULL ); HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1); NeedEndOp = TRUE; } ASSERT (Option->Description != NULL); Token = HiiSetString (HiiHandle, 0, Option->Description, NULL); TempStr = DevicePathToStr (Option->DevicePath); HelpSize = StrSize (TempStr) + StrSize (L"Device Path : "); HelpString = AllocateZeroPool (HelpSize); ASSERT (HelpString != NULL); StrCatS (HelpString, HelpSize / sizeof (CHAR16), L"Device Path : "); StrCatS (HelpString, HelpSize / sizeof (CHAR16), TempStr); HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL); HiiCreateActionOpCode ( StartOpCodeHandle, mKeyInput, Token, HelpToken, EFI_IFR_FLAG_CALLBACK, 0 ); } if (NeedEndOp) { HiiCreateEndOpCode (StartOpCodeHandle); } HiiUpdateForm ( HiiHandle, &gBootManagerFormSetGuid, BOOT_MANAGER_FORM_ID, StartOpCodeHandle, EndOpCodeHandle ); HiiFreeOpCodeHandle (StartOpCodeHandle); HiiFreeOpCodeHandle (EndOpCodeHandle); ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; Status = gFormBrowser2->SendForm ( gFormBrowser2, &HiiHandle, 1, &gBootManagerFormSetGuid, 0, NULL, &ActionRequest ); if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { EnableResetRequired (); } if (gOption == NULL) { return ; } // // Will leave browser, check any reset required change is applied? if yes, reset system // SetupResetReminder (); // // Restore to original mode before launching boot option. // BdsSetConsoleMode (FALSE); // // parse the selected option // Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData); if (!EFI_ERROR (Status)) { gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); PlatformBdsBootSuccess (gOption); } else { gOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize); gST->ConOut->OutputString ( gST->ConOut, GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE)) ); gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); } }
/** Update the form to include the driver health instances. @param ConfigureOnly Only include the configure required driver health instances when TRUE, include all the driver health instances otherwise. **/ VOID DriverHealthManagerUpdateForm ( BOOLEAN ConfigureOnly ) { EFI_STATUS Status; EFI_IFR_GUID_LABEL *StartLabel; EFI_IFR_GUID_LABEL *EndLabel; VOID *StartOpCodeHandle; VOID *EndOpCodeHandle; UINTN Index; EFI_STRING_ID Prompt; EFI_STRING_ID Help; CHAR16 String[512]; UINTN StringCount; EFI_STRING TmpString; EFI_STRING DriverName; EFI_STRING ControllerName; UINTN MessageIndex; EFI_HANDLE DriverHandle; EFI_STRING_ID DevicePath; EFI_GUID FormsetGuid; EfiBootManagerFreeDriverHealthInfo (mDriverHealthManagerHealthInfo, mDriverHealthManagerHealthInfoCount); mDriverHealthManagerHealthInfo = EfiBootManagerGetDriverHealthInfo (&mDriverHealthManagerHealthInfoCount); // // Allocate space for creation of UpdateData Buffer // StartOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (StartOpCodeHandle != NULL); EndOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (EndOpCodeHandle != NULL); // // Create Hii Extend Label OpCode as the start opcode // StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; StartLabel->Number = LABEL_BEGIN; // // Create Hii Extend Label OpCode as the end opcode // EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; EndLabel->Number = LABEL_END; for (Index = 0; Index < mDriverHealthManagerHealthInfoCount; Index++) { if (ConfigureOnly && mDriverHealthManagerHealthInfo[Index].HealthStatus != EfiDriverHealthStatusConfigurationRequired) { continue; } DriverName = DriverHealthManagerGetDriverName (mDriverHealthManagerHealthInfo[Index].DriverHealthHandle); ASSERT (DriverName != NULL); if (mDriverHealthManagerHealthInfo[Index].ControllerHandle == NULL) { // // The ControllerHandle is set to NULL and the HealthStatus is set to EfiDriverHealthStatusHealthy // if all the controllers managed by the driver are in healthy state. // ASSERT (mDriverHealthManagerHealthInfo[Index].HealthStatus == EfiDriverHealthStatusHealthy); UnicodeSPrint (String, sizeof (String), L"%s", DriverName); } else { ControllerName = DriverHealthManagerGetControllerName ( mDriverHealthManagerHealthInfo[Index].DriverHealthHandle, mDriverHealthManagerHealthInfo[Index].ControllerHandle, mDriverHealthManagerHealthInfo[Index].ChildHandle ); ASSERT (ControllerName != NULL); UnicodeSPrint (String, sizeof (String), L"%s %s", DriverName, ControllerName); FreePool (ControllerName); } FreePool (DriverName); Prompt = HiiSetString (mDriverHealthManagerHiiHandle, 0, String, NULL); switch(mDriverHealthManagerHealthInfo[Index].HealthStatus) { case EfiDriverHealthStatusRepairRequired: TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_REPAIR_REQUIRED), NULL); break; case EfiDriverHealthStatusConfigurationRequired: TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_CONFIGURATION_REQUIRED), NULL); break; case EfiDriverHealthStatusFailed: TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_FAILED), NULL); break; case EfiDriverHealthStatusReconnectRequired: TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_RECONNECT_REQUIRED), NULL); break; case EfiDriverHealthStatusRebootRequired: TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_REBOOT_REQUIRED), NULL); break; default: ASSERT (mDriverHealthManagerHealthInfo[Index].HealthStatus == EfiDriverHealthStatusHealthy); TmpString = HiiGetString (mDriverHealthManagerHiiHandle, STRING_TOKEN (STR_HEALTHY), NULL); break; } StringCount = UnicodeSPrint (String, sizeof (String), L"%s\n", TmpString); FreePool (TmpString); // // Add the message of the Module itself provided as the help. // if (mDriverHealthManagerHealthInfo[Index].MessageList != NULL) { for (MessageIndex = 0; mDriverHealthManagerHealthInfo[Index].MessageList[MessageIndex].HiiHandle != NULL; MessageIndex++) { TmpString = HiiGetString ( mDriverHealthManagerHealthInfo[Index].MessageList[MessageIndex].HiiHandle, mDriverHealthManagerHealthInfo[Index].MessageList[MessageIndex].StringId, NULL ); StringCount += UnicodeSPrint (String + StringCount, sizeof (String) - sizeof (String[0]) * StringCount, L"\n%s", TmpString); FreePool (TmpString); } } Help = HiiSetString (mDriverHealthManagerHiiHandle, 0, String, NULL); switch (mDriverHealthManagerHealthInfo[Index].HealthStatus) { case EfiDriverHealthStatusConfigurationRequired: Status = mDriverHealthManagerDatabase->GetPackageListHandle ( mDriverHealthManagerDatabase, mDriverHealthManagerHealthInfo[Index].HiiHandle, &DriverHandle ); ASSERT_EFI_ERROR (Status); TmpString = ConvertDevicePathToText (DevicePathFromHandle (DriverHandle), FALSE, TRUE); DevicePath = HiiSetString (mDriverHealthManagerHiiHandle, 0, TmpString, NULL); FreePool (TmpString); Status = DriverHealthManagerGetFormsetId (mDriverHealthManagerHealthInfo[Index].HiiHandle, &FormsetGuid); ASSERT_EFI_ERROR (Status); HiiCreateGotoExOpCode ( StartOpCodeHandle, 0, Prompt, Help, 0, 0, 0, &FormsetGuid, DevicePath ); break; case EfiDriverHealthStatusRepairRequired: case EfiDriverHealthStatusReconnectRequired: case EfiDriverHealthStatusRebootRequired: HiiCreateActionOpCode ( StartOpCodeHandle, (EFI_QUESTION_ID) (Index + QUESTION_ID_DRIVER_HEALTH_BASE), Prompt, Help, EFI_IFR_FLAG_CALLBACK, 0 ); break; default: ASSERT (mDriverHealthManagerHealthInfo[Index].HealthStatus == EfiDriverHealthStatusHealthy || mDriverHealthManagerHealthInfo[Index].HealthStatus == EfiDriverHealthStatusFailed); HiiCreateTextOpCode ( StartOpCodeHandle, Prompt, Help, 0 ); break; } } Status = HiiUpdateForm ( mDriverHealthManagerHiiHandle, ConfigureOnly ? PcdGetPtr (PcdDriverHealthConfigureForm) : &mDriverHealthManagerForm, DRIVER_HEALTH_FORM_ID, StartOpCodeHandle, EndOpCodeHandle ); ASSERT_EFI_ERROR (Status); HiiFreeOpCodeHandle (StartOpCodeHandle); HiiFreeOpCodeHandle (EndOpCodeHandle); }
/** Update the File Explore page. @param[in] HiiHandle Hii Handle of the package to be updated. @param[in] MenuOption The Menu whose string tokens need to be updated. @param[in] FeCurrentState Current file explorer state. **/ VOID UpdateFileExplorePage ( IN EFI_HII_HANDLE HiiHandle, IN SECUREBOOT_MENU_OPTION *MenuOption, IN FILE_EXPLORER_STATE FeCurrentState ) { UINTN Index; SECUREBOOT_MENU_ENTRY *NewMenuEntry; SECUREBOOT_FILE_CONTEXT *NewFileContext; EFI_FORM_ID FormId; EFI_FORM_ID FileFormId; if (FeCurrentState == FileExplorerStateEnrollPkFile) { FormId = SECUREBOOT_ADD_PK_FILE_FORM_ID; FileFormId = FORM_FILE_EXPLORER_ID_PK; } else if (FeCurrentState == FileExplorerStateEnrollKekFile) { FormId = FORMID_ENROLL_KEK_FORM; FileFormId = FORM_FILE_EXPLORER_ID_KEK; } else if (FeCurrentState == FileExplorerStateEnrollSignatureFileToDb) { FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB; FileFormId = FORM_FILE_EXPLORER_ID_DB; } else if (FeCurrentState == FileExplorerStateEnrollSignatureFileToDbx) { FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX; FileFormId = FORM_FILE_EXPLORER_ID_DBX; } else if (FeCurrentState == FileExplorerStateEnrollSignatureFileToDbt) { FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT; FileFormId = FORM_FILE_EXPLORER_ID_DBT; } else { return; } NewMenuEntry = NULL; NewFileContext = NULL; RefreshUpdateData (); mStartLabel->Number = FORM_FILE_EXPLORER_ID; for (Index = 0; Index < MenuOption->MenuNumber; Index++) { NewMenuEntry = GetMenuEntry (MenuOption, Index); NewFileContext = (SECUREBOOT_FILE_CONTEXT *) NewMenuEntry->FileContext; if (NewFileContext->IsDir) { // // Create Text opcode for directory. // HiiCreateActionOpCode ( mStartOpCodeHandle, (UINT16) (FILE_OPTION_OFFSET + Index), NewMenuEntry->DisplayStringToken, STRING_TOKEN (STR_NULL), EFI_IFR_FLAG_CALLBACK, 0 ); } else { // // Create Goto opcode for file. // HiiCreateGotoOpCode ( mStartOpCodeHandle, FormId, NewMenuEntry->DisplayStringToken, STRING_TOKEN (STR_NULL), EFI_IFR_FLAG_CALLBACK, (UINT16) (FILE_OPTION_GOTO_OFFSET + Index) ); } } HiiUpdateForm ( HiiHandle, &gSecureBootConfigFormSetGuid, FileFormId, mStartOpCodeHandle, // Label FORM_FILE_EXPLORER_ID mEndOpCodeHandle // LABEL_END ); }
/** This function processes changes in user profile configuration. @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @param Action Specifies the type of action taken by the browser. @param QuestionId A unique value which is sent to the original exporting driver so that it can identify the type of data to expect. @param Type The type of value for the question. @param Value A pointer to the data being sent to the original exporting driver. @param ActionRequest On return, points to the action requested by the callback function. @retval EFI_SUCCESS The callback successfully handled the action. @retval Others Fail to handle the action. **/ EFI_STATUS EFIAPI UserProfileManagerCallback ( IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, IN EFI_BROWSER_ACTION Action, IN EFI_QUESTION_ID QuestionId, IN UINT8 Type, IN EFI_IFR_TYPE_VALUE *Value, OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest ) { EFI_STATUS Status; EFI_INPUT_KEY Key; UINT32 CurrentAccessRight; CHAR16 *QuestionStr; CHAR16 *PromptStr; VOID *StartOpCodeHandle; VOID *EndOpCodeHandle; EFI_IFR_GUID_LABEL *StartLabel; EFI_IFR_GUID_LABEL *EndLabel; EFI_USER_PROFILE_HANDLE CurrentUser; Status = EFI_SUCCESS; switch (Action) { case EFI_BROWSER_ACTION_FORM_OPEN: { // // Update user manage Form when user manage Form is opened. // This will be done only in FORM_OPEN CallBack of question with QUESTIONID_USER_MANAGE from user manage Form. // if (QuestionId != QUESTIONID_USER_MANAGE) { return EFI_SUCCESS; } // // Get current user // CurrentUser = NULL; mUserManager->Current (mUserManager, &CurrentUser); if (CurrentUser == NULL) { DEBUG ((DEBUG_ERROR, "Error: current user does not exist!\n")); return EFI_NOT_READY; } // // Get current user's right information. // Status = GetAccessRight (&CurrentAccessRight); if (EFI_ERROR (Status)) { CurrentAccessRight = EFI_USER_INFO_ACCESS_ENROLL_SELF; } // // Init credential provider information. // Status = InitProviderInfo (); if (EFI_ERROR (Status)) { return Status; } // // Initialize the container for dynamic opcodes. // StartOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (StartOpCodeHandle != NULL); EndOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (EndOpCodeHandle != NULL); // // Create Hii Extend Label OpCode. // StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL) ); StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; StartLabel->Number = LABEL_USER_MANAGE_FUNC; EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL) ); EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; EndLabel->Number = LABEL_END; // // Add user profile option. // if ((CurrentAccessRight == EFI_USER_INFO_ACCESS_MANAGE) || (CurrentAccessRight == EFI_USER_INFO_ACCESS_ENROLL_OTHERS) ) { HiiCreateActionOpCode ( StartOpCodeHandle, // Container for dynamic created opcodes KEY_ADD_USER, // Question ID STRING_TOKEN (STR_ADD_USER_TITLE), // Prompt text STRING_TOKEN (STR_ADD_USER_HELP), // Help text EFI_IFR_FLAG_CALLBACK, // Question flag 0 // Action String ID ); } // // Add modify user profile option. // HiiCreateGotoOpCode ( StartOpCodeHandle, // Container for dynamic created opcodes FORMID_MODIFY_USER, // Target Form ID STRING_TOKEN (STR_MODIFY_USER_TITLE), // Prompt text STRING_TOKEN (STR_MODIFY_USER_HELP), // Help text EFI_IFR_FLAG_CALLBACK, // Question flag KEY_MODIFY_USER // Question ID ); // // Add delete user profile option // if (CurrentAccessRight == EFI_USER_INFO_ACCESS_MANAGE) { HiiCreateGotoOpCode ( StartOpCodeHandle, // Container for dynamic created opcodes FORMID_DEL_USER, // Target Form ID STRING_TOKEN (STR_DELETE_USER_TITLE), // Prompt text STRING_TOKEN (STR_DELETE_USER_HELP), // Help text EFI_IFR_FLAG_CALLBACK, // Question flag KEY_DEL_USER // Question ID ); } HiiUpdateForm ( mCallbackInfo->HiiHandle, // HII handle &gUserProfileManagerGuid, // Formset GUID FORMID_USER_MANAGE, // Form ID StartOpCodeHandle, // Label for where to insert opcodes EndOpCodeHandle // Replace data ); HiiFreeOpCodeHandle (StartOpCodeHandle); HiiFreeOpCodeHandle (EndOpCodeHandle); return EFI_SUCCESS; } break; case EFI_BROWSER_ACTION_FORM_CLOSE: Status = EFI_SUCCESS; break; case EFI_BROWSER_ACTION_CHANGED: { // // Handle the request from form. // if ((Value == NULL) || (ActionRequest == NULL)) { return EFI_INVALID_PARAMETER; } // // Judge first 2 bits. // switch (QuestionId & KEY_FIRST_FORM_MASK) { // // Add user profile operation. // case KEY_ADD_USER: CallAddUser (); break; // // Delete user profile operation. // case KEY_DEL_USER: // // Judge next 2 bits. // switch (QuestionId & KEY_SECOND_FORM_MASK) { // // Delete specified user profile. // case KEY_SELECT_USER: DeleteUser ((UINT8) QuestionId); // // Update select user form after delete a user. // SelectUserToDelete (); break; default: break; } break; // // Modify user profile operation. // case KEY_MODIFY_USER: // // Judge next 2 bits. // switch (QuestionId & KEY_SECOND_FORM_MASK) { // // Enter user profile information form. // case KEY_SELECT_USER: // // Judge next 3 bits. // switch (QuestionId & KEY_MODIFY_INFO_MASK) { // // Modify user name. // case KEY_MODIFY_NAME: ModifyUserName (); // // Update username in parent form. // SelectUserToModify (); break; // // Modify identity policy. // case KEY_MODIFY_IP: // // Judge next 3 bits // switch (QuestionId & KEY_MODIFY_IP_MASK) { // // Change credential provider option. // case KEY_MODIFY_PROV: mProviderChoice = Value->u8; break; // // Change logical connector. // case KEY_MODIFY_CONN: mConncetLogical = Value->u8; break; // // Save option. // case KEY_ADD_IP_OP: AddIdentityPolicyItem (); break; // // Return to user profile information form. // case KEY_IP_RETURN_UIF: SaveIdentityPolicy (); *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; break; default: break; } break; // // Modify access policy. // case KEY_MODIFY_AP: // // Judge next 3 bits. // switch (QuestionId & KEY_MODIFY_AP_MASK) { // // Change access right choice. // case KEY_MODIFY_RIGHT: mAccessInfo.AccessRight = Value->u8; break; // // Change setup choice. // case KEY_MODIFY_SETUP: mAccessInfo.AccessSetup= Value->u8; break; // // Change boot order choice. // case KEY_MODIFY_BOOT: mAccessInfo.AccessBootOrder = Value->u32; break; // // Return to user profile information form. // case KEY_AP_RETURN_UIF: SaveAccessPolicy (); *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; break; default: break; } break; default: break; } break; // // Access policy device path modified. // case KEY_MODIFY_AP_DP: // // Judge next 2 bits. // switch (QuestionId & KEY_MODIFY_DP_MASK) { // // Load permit device path modified. // case KEY_LOAD_PERMIT_MODIFY: QuestionStr = GetStringById (STRING_TOKEN (STR_MOVE_TO_FORBID_LIST)); PromptStr = GetStringById (STRING_TOKEN (STR_PRESS_KEY_CONTINUE)); CreatePopUp ( EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, QuestionStr, L"", PromptStr, NULL ); FreePool (QuestionStr); FreePool (PromptStr); if (Key.UnicodeChar != CHAR_CARRIAGE_RETURN) { break; } AddToForbidLoad ((UINT16)(QuestionId & (KEY_MODIFY_DP_MASK - 1))); DisplayLoadPermit (); break; // // Load forbid device path modified. // case KEY_LOAD_FORBID_MODIFY: QuestionStr = GetStringById (STRING_TOKEN (STR_MOVE_TO_PERMIT_LIST)); PromptStr = GetStringById (STRING_TOKEN (STR_PRESS_KEY_CONTINUE)); CreatePopUp ( EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, QuestionStr, L"", PromptStr, NULL ); FreePool (QuestionStr); FreePool (PromptStr); if (Key.UnicodeChar != CHAR_CARRIAGE_RETURN) { break; } DeleteFromForbidLoad ((UINT16)(QuestionId & (KEY_MODIFY_DP_MASK - 1))); DisplayLoadForbid (); break; // // Connect permit device path modified. // case KEY_CONNECT_PERMIT_MODIFY: break; // // Connect forbid device path modified. // case KEY_CONNECT_FORBID_MODIFY: break; default: break; } break; default: break; } break; default: break; } } break; case EFI_BROWSER_ACTION_CHANGING: { // // Handle the request from form. // if (Value == NULL) { return EFI_INVALID_PARAMETER; } // // Judge first 2 bits. // switch (QuestionId & KEY_FIRST_FORM_MASK) { // // Delete user profile operation. // case KEY_DEL_USER: // // Judge next 2 bits. // switch (QuestionId & KEY_SECOND_FORM_MASK) { // // Enter delete user profile form. // case KEY_ENTER_NEXT_FORM: SelectUserToDelete (); break; default: break; } break; // // Modify user profile operation. // case KEY_MODIFY_USER: // // Judge next 2 bits. // switch (QuestionId & KEY_SECOND_FORM_MASK) { // // Enter modify user profile form. // case KEY_ENTER_NEXT_FORM: SelectUserToModify (); break; // // Enter user profile information form. // case KEY_SELECT_USER: // // Judge next 3 bits. // switch (QuestionId & KEY_MODIFY_INFO_MASK) { // // Display user information form. // case KEY_ENTER_NEXT_FORM: ModifyUserInfo ((UINT8) QuestionId); break; // // Modify identity policy. // case KEY_MODIFY_IP: // // Judge next 3 bits // switch (QuestionId & KEY_MODIFY_IP_MASK) { // // Display identity policy modify form. // case KEY_ENTER_NEXT_FORM: ModifyIdentityPolicy (); break; default: break; } break; // // Modify access policy. // case KEY_MODIFY_AP: // // Judge next 3 bits. // switch (QuestionId & KEY_MODIFY_AP_MASK) { // // Display access policy modify form. // case KEY_ENTER_NEXT_FORM: ModidyAccessPolicy (); break; // // Load device path form. // case KEY_MODIFY_LOAD: // // Judge next 2 bits. // switch (QuestionId & KEY_DISPLAY_DP_MASK) { // // Permit load device path. // case KEY_PERMIT_MODIFY: DisplayLoadPermit (); break; // // Forbid load device path. // case KEY_FORBID_MODIFY: DisplayLoadForbid (); break; default: break; } break; // // Connect device path form. // case KEY_MODIFY_CONNECT: // // Judge next 2 bits. // switch (QuestionId & KEY_DISPLAY_DP_MASK) { // // Permit connect device path. // case KEY_PERMIT_MODIFY: DisplayConnectPermit (); break; // // Forbid connect device path. // case KEY_FORBID_MODIFY: DisplayConnectForbid (); break; default: break; } break; default: break; } break; default: break; } break; default: break; } break; default: break; } } break; default: // // All other action return unsupported. // Status = EFI_UNSUPPORTED; break; } return Status; }