/** 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 a Hii Update data Handle used to call IfrLibUpdateForm. @param ThunkContext The HII Thunk Context. @param FwUpdateData The Framework Update Data. @param UefiOpCodeHandle The UEFI opcode handle. @retval EFI_SUCCESS The UEFI Update Data is created successfully. @retval EFI_UNSUPPORTED There is unsupported opcode in FwUpdateData. @retval EFI_OUT_OF_RESOURCES There is not enough resource. **/ EFI_STATUS FwUpdateDataToUefiUpdateData ( IN HII_THUNK_CONTEXT *ThunkContext, IN CONST EFI_HII_UPDATE_DATA *FwUpdateData, IN VOID *UefiOpCodeHandle ) { FRAMEWORK_EFI_IFR_OP_HEADER *FwOpCode; FRAMEWORK_EFI_IFR_OP_HEADER *NextFwOpCode; UINTN Index; UINTN DataCount; UINT8 *OpCodeBuffer; LIST_ENTRY *StorageList; FORMSET_STORAGE *Storage; FORM_BROWSER_FORMSET *FormSet; CHAR16 *DefaultVarStoreName; UINT16 DefaultVarStoreId; EFI_IFR_VARSTORE_SELECT *SelectVarOp; FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *) &FwUpdateData->Data; FormSet = ThunkContext->FormSet; DefaultVarStoreId = FormSet->DefaultVarStoreId; DefaultVarStoreName = FormSet->OriginalDefaultVarStoreName; for (Index = 0; Index < FwUpdateData->DataCount; Index += DataCount) { switch (FwOpCode->OpCode) { case FRAMEWORK_EFI_IFR_SUBTITLE_OP: OpCodeBuffer = HiiCreateSubTitleOpCode (UefiOpCodeHandle, ((FRAMEWORK_EFI_IFR_SUBTITLE *) FwOpCode)->SubTitle, 0, 0, 0); DataCount = 1; break; case FRAMEWORK_EFI_IFR_TEXT_OP: OpCodeBuffer = F2UCreateTextOpCode (UefiOpCodeHandle, (FRAMEWORK_EFI_IFR_TEXT *) FwOpCode); DataCount = 1; break; case FRAMEWORK_EFI_IFR_REF_OP: OpCodeBuffer = F2UCreateReferenceOpCode (UefiOpCodeHandle, (FRAMEWORK_EFI_IFR_REF *) FwOpCode); DataCount = 1; break; case FRAMEWORK_EFI_IFR_ONE_OF_OP: OpCodeBuffer = F2UCreateOneOfOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_ONE_OF *) FwOpCode, &NextFwOpCode, &DataCount); if (OpCodeBuffer != NULL) { FwOpCode = NextFwOpCode; // // FwOpCode is already updated to point to the next opcode. // continue; } break; case FRAMEWORK_EFI_IFR_ORDERED_LIST_OP: OpCodeBuffer = F2UCreateOrderedListOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_ORDERED_LIST *) FwOpCode, &NextFwOpCode, &DataCount); if (OpCodeBuffer != NULL) { FwOpCode = NextFwOpCode; // // FwOpCode is already updated to point to the next opcode. // continue; } break; case FRAMEWORK_EFI_IFR_CHECKBOX_OP: OpCodeBuffer = F2UCreateCheckBoxOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_CHECKBOX *) FwOpCode); DataCount = 1; break; case FRAMEWORK_EFI_IFR_STRING_OP: OpCodeBuffer = F2UCreateStringOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_STRING *) FwOpCode); DataCount = 1; break; case EFI_IFR_BANNER_OP: OpCodeBuffer = F2UCreateBannerOpCode (UefiOpCodeHandle, (EFI_IFR_BANNER *) FwOpCode); DataCount = 1; break; case EFI_IFR_END_ONE_OF_OP: OpCodeBuffer = HiiCreateEndOpCode (UefiOpCodeHandle); DataCount = 1; break; case FRAMEWORK_EFI_IFR_NUMERIC_OP: OpCodeBuffer = F2UCreateNumericOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_NUMERIC *) FwOpCode); DataCount = 1; break; case EFI_IFR_VARSTORE_SELECT_OP: OpCodeBuffer = (UINT8 *) FwOpCode; SelectVarOp = (EFI_IFR_VARSTORE_SELECT *) FwOpCode; // // Check whether the selected VarId is in StorageList. // StorageList = GetFirstNode (&FormSet->StorageListHead); while (!IsNull (&FormSet->StorageListHead, StorageList)) { Storage = FORMSET_STORAGE_FROM_LINK (StorageList); if (Storage->VarStoreId == SelectVarOp->VarId) { break; } StorageList = GetNextNode (&FormSet->StorageListHead, StorageList); } ASSERT (!IsNull (&FormSet->StorageListHead, StorageList)); // // Change VarStoreId to the selected VarId. // FormSet->DefaultVarStoreId = SelectVarOp->VarId; if (SelectVarOp->VarId == DefaultVarStoreId) { FormSet->OriginalDefaultVarStoreName = DefaultVarStoreName; } DataCount = 1; break; default: ASSERT (FALSE); return EFI_UNSUPPORTED; } if (OpCodeBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpCode + FwOpCode->Length); } // // Revert FromSet default varstore ID. // FormSet->DefaultVarStoreId = DefaultVarStoreId; FormSet->OriginalDefaultVarStoreName = DefaultVarStoreName; return EFI_SUCCESS; }
/** Create UEFI HII Numeric Opcode from a Framework HII Numeric Opcode. @param UefiUpdateDataHandle The newly created UEFI HII opcode is appended to UefiUpdateDataHandle. @param ThunkContext The HII Thunk Context. @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 * F2UCreateNumericOpCode ( IN OUT VOID *UefiUpdateDataHandle, IN HII_THUNK_CONTEXT *ThunkContext, IN CONST FRAMEWORK_EFI_IFR_NUMERIC *FwOpcode ) { EFI_STATUS Status; EFI_IFR_NUMERIC UOpcode; EFI_IFR_DEFAULT UOpcodeDefault; UINT8 *NumbericOpCode; UINT8 *OpcodeBuffer; ZeroMem (&UOpcode, sizeof(UOpcode)); if (FwOpcode->Key == 0) { Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId); if (EFI_ERROR (Status)) { // // Add a new opcode and it will not trigger call back. So we just reuse the FW QuestionId. // UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet); } } else { UOpcode.Question.QuestionId = FwOpcode->Key; } UOpcode.Header.Length = (UINT8) sizeof (UOpcode); UOpcode.Header.OpCode = EFI_IFR_NUMERIC_OP; // // We need to create a nested default value for the UEFI Numeric Opcode. // So turn on the scope. // UOpcode.Header.Scope = 1; UOpcode.Question.Header.Prompt = FwOpcode->Prompt; UOpcode.Question.Header.Help = FwOpcode->Help; UOpcode.Question.VarStoreId = ThunkContext->FormSet->DefaultVarStoreId; UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId; UOpcode.Question.Flags = (UINT8) (FwOpcode->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_RESET_REQUIRED)); // // Framework Numeric values are all in UINT16 and displayed as decimal. // UOpcode.data.u16.MinValue = FwOpcode->Minimum; UOpcode.data.u16.MaxValue = FwOpcode->Maximum; UOpcode.data.u16.Step = FwOpcode->Step; switch (FwOpcode->Width) { case 1: { UOpcode.Flags = EFI_IFR_NUMERIC_SIZE_1 | EFI_IFR_DISPLAY_UINT_DEC; break; } case 2: { UOpcode.Flags = EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC; break; } default: { ASSERT (FALSE); return NULL; } } NumbericOpCode = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode)); if (NumbericOpCode == NULL) { return NULL; } // // We need to create a default value. // ZeroMem (&UOpcodeDefault, sizeof (UOpcodeDefault)); UOpcodeDefault.Header.Length = (UINT8) sizeof (UOpcodeDefault); UOpcodeDefault.Header.OpCode = EFI_IFR_DEFAULT_OP; UOpcodeDefault.DefaultId = 0; switch (FwOpcode->Width) { case 1: { UOpcodeDefault.Type = EFI_IFR_TYPE_NUM_SIZE_8; break; } case 2: { UOpcodeDefault.Type = EFI_IFR_TYPE_NUM_SIZE_16; break; } } CopyMem (&UOpcodeDefault.Value.u8, &FwOpcode->Default, FwOpcode->Width); OpcodeBuffer = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcodeDefault, sizeof(UOpcodeDefault)); if (OpcodeBuffer == NULL) { return NULL; } OpcodeBuffer = HiiCreateEndOpCode (UefiUpdateDataHandle); if (OpcodeBuffer == NULL) { return NULL; } return NumbericOpCode; }
/** Create UEFI HII "Ordered List" Opcode from a Framework HII "Ordered List" Opcode. @param UefiUpdateDataHandle The newly created UEFI HII opcode is appended to UefiUpdateDataHandle. @param ThunkContext The HII Thunk Context. @param FwOpcode The input Framework Opcode. @param NextFwOpcode Returns the position of the next Framework Opcode after EFI_IFR_END_ONE_OF_OP of the "Ordered List". @param OpcodeCount The number of Opcode for the complete Framework "Ordered List" Opcode. @retval NULL There is not enough space left in Buffer to add the opcode. @retval Other A pointer to the created opcode. **/ UINT8 * F2UCreateOrderedListOpCode ( IN OUT VOID *UefiUpdateDataHandle, IN HII_THUNK_CONTEXT *ThunkContext, IN CONST FRAMEWORK_EFI_IFR_ORDERED_LIST *FwOpcode, OUT FRAMEWORK_EFI_IFR_OP_HEADER **NextFwOpcode, OUT UINTN *OpcodeCount ) { EFI_IFR_ORDERED_LIST UOpcode; EFI_STATUS Status; FRAMEWORK_EFI_IFR_OP_HEADER *FwOpHeader; FRAMEWORK_EFI_IFR_ONE_OF_OPTION *FwOneOfOp; UINT8 *OpcodeBuffer; UINT8 *OrderListOpCode; ZeroMem (&UOpcode, sizeof(UOpcode)); *OpcodeCount = 0; UOpcode.Header.Length = (UINT8) sizeof (UOpcode); UOpcode.Header.OpCode = EFI_IFR_ORDERED_LIST_OP; UOpcode.Header.Scope = 1; UOpcode.Question.Header.Prompt = FwOpcode->Prompt; UOpcode.Question.Header.Help = FwOpcode->Help; UOpcode.Question.VarStoreId = ThunkContext->FormSet->DefaultVarStoreId; UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId; UOpcode.MaxContainers = FwOpcode->MaxEntries; // // Go over the Framework IFR binary to get the QuestionId for generated UEFI One Of Option opcode // FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length); while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) { ASSERT (FwOpHeader->OpCode == FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP); FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader; if ((FwOneOfOp->Flags & EFI_IFR_FLAG_INTERACTIVE) != 0) { UOpcode.Question.Flags |= EFI_IFR_FLAG_CALLBACK; if (UOpcode.Question.QuestionId == 0) { Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId); if (EFI_ERROR (Status)) { UOpcode.Question.QuestionId = AssignQuestionId (FwOneOfOp->Key, ThunkContext->FormSet); } } } if ((FwOneOfOp->Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) { UOpcode.Question.Flags |= EFI_IFR_FLAG_RESET_REQUIRED; } FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length); } if (UOpcode.Question.QuestionId == 0) { Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId); if (EFI_ERROR (Status)) { UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet); } } OrderListOpCode = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof(UOpcode)); if (OrderListOpCode == NULL) { return NULL; } *OpcodeCount += 1; FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length); while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) { // // Each entry of Order List in Framework HII is always 1 byte in size // OpcodeBuffer = F2UCreateOneOfOptionOpCode (UefiUpdateDataHandle, (CONST FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader, 1); if (OpcodeBuffer == NULL) { return NULL; } FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length); *OpcodeCount += 1; } OpcodeBuffer = HiiCreateEndOpCode (UefiUpdateDataHandle); if (OpcodeBuffer != NULL) { *NextFwOpcode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpHeader + FwOpHeader->Length); *OpcodeCount += 1; } return OrderListOpCode; }
/** Create UEFI HII "One Of" Opcode from a Framework HII "One Of" Opcode. @param UefiUpdateDataHandle The newly created UEFI HII opcode is appended to UefiUpdateDataHandle. @param ThunkContext The HII Thunk Context. @param FwOpcode The input Framework Opcode. @param NextFwOpcode Returns the position of the next Framework Opcode after EFI_IFR_END_ONE_OF_OP of the "One Of Option". @param OpcodeCount The number of Opcode for the complete Framework "One Of" Opcode. @retval NULL There is not enough space left in Buffer to add the opcode. @retval Other A pointer to the created opcode. **/ UINT8 * F2UCreateOneOfOpCode ( IN OUT VOID *UefiUpdateDataHandle, IN HII_THUNK_CONTEXT *ThunkContext, IN CONST FRAMEWORK_EFI_IFR_ONE_OF *FwOpcode, OUT FRAMEWORK_EFI_IFR_OP_HEADER **NextFwOpcode, OUT UINTN *OpcodeCount ) { EFI_STATUS Status; EFI_IFR_ONE_OF UOpcode; FRAMEWORK_EFI_IFR_OP_HEADER *FwOpHeader; FRAMEWORK_EFI_IFR_ONE_OF_OPTION *FwOneOfOp; UINT8 *OpCodeBuffer; UINT8 *OneOfOpCodeBuffer; ASSERT (NextFwOpcode != NULL); ASSERT (OpcodeCount != NULL); ZeroMem (&UOpcode, sizeof(UOpcode)); *OpcodeCount = 0; UOpcode.Header.Length = (UINT8) sizeof (UOpcode); UOpcode.Header.OpCode = EFI_IFR_ONE_OF_OP; UOpcode.Header.Scope = 1; UOpcode.Question.Header.Prompt = FwOpcode->Prompt; UOpcode.Question.Header.Help = FwOpcode->Help; UOpcode.Question.VarStoreId = ThunkContext->FormSet->DefaultVarStoreId; UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId; // // Go over the Framework IFR binary to get the QuestionId for generated UEFI One Of Option opcode // FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length); while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) { ASSERT (FwOpHeader->OpCode == FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP); FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader; if ((FwOneOfOp->Flags & EFI_IFR_FLAG_INTERACTIVE) != 0) { UOpcode.Question.Flags |= EFI_IFR_FLAG_CALLBACK; if (UOpcode.Question.QuestionId == 0) { Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId); if (EFI_ERROR (Status)) { UOpcode.Question.QuestionId = AssignQuestionId (FwOneOfOp->Key, ThunkContext->FormSet); } } } if ((FwOneOfOp->Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) { UOpcode.Question.Flags |= EFI_IFR_FLAG_RESET_REQUIRED; } FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length); } if (UOpcode.Question.QuestionId == 0) { // // Assign QuestionId if still not assigned. // Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId); if (EFI_ERROR (Status)) { UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet); } } OneOfOpCodeBuffer = HiiCreateRawOpCodes (UefiUpdateDataHandle, (UINT8 *) &UOpcode, sizeof (UOpcode)); if (OneOfOpCodeBuffer == NULL) { return NULL; } *OpcodeCount += 1; // // Go over again the Framework IFR binary to build the UEFI One Of Option opcodes. // FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length); while (FwOpHeader->OpCode != EFI_IFR_END_ONE_OF_OP) { FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader; OpCodeBuffer = F2UCreateOneOfOptionOpCode (UefiUpdateDataHandle, (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader, FwOpcode->Width); if (OpCodeBuffer == NULL) { return NULL; } OpCodeBuffer = CreateGuidOptionKeyOpCode (UefiUpdateDataHandle, UOpcode.Question.QuestionId, FwOneOfOp->Value, FwOneOfOp->Key); if (OpCodeBuffer == NULL) { return NULL; } FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length); *OpcodeCount += 1; } OpCodeBuffer = HiiCreateEndOpCode (UefiUpdateDataHandle); if (OpCodeBuffer != NULL) { *NextFwOpcode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpHeader + FwOpHeader->Length); *OpcodeCount += 1; } return OneOfOpCodeBuffer; }
/** 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); } }
/** Create a Hii Update data Handle used to call IfrLibUpdateForm. @param ThunkContext The HII Thunk Context. @param FwUpdateData The Framework Update Data. @param UefiOpCodeHandle The UEFI opcode hanlde. @retval EFI_SUCCESS The UEFI Update Data is created successfully. @retval EFI_UNSUPPORTED There is unsupported opcode in FwUpdateData. @retval EFI_OUT_OF_RESOURCES There is not enough resource. **/ EFI_STATUS FwUpdateDataToUefiUpdateData ( IN HII_THUNK_CONTEXT *ThunkContext, IN CONST EFI_HII_UPDATE_DATA *FwUpdateData, IN VOID *UefiOpCodeHandle ) { FRAMEWORK_EFI_IFR_OP_HEADER *FwOpCode; FRAMEWORK_EFI_IFR_OP_HEADER *NextFwOpCode; UINTN Index; UINTN DataCount; UINT8 *OpCodeBuffer; FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *) &FwUpdateData->Data; for (Index = 0; Index < FwUpdateData->DataCount; Index += DataCount) { switch (FwOpCode->OpCode) { case FRAMEWORK_EFI_IFR_SUBTITLE_OP: OpCodeBuffer = HiiCreateSubTitleOpCode (UefiOpCodeHandle, ((FRAMEWORK_EFI_IFR_SUBTITLE *) FwOpCode)->SubTitle, 0, 0, 0); DataCount = 1; break; case FRAMEWORK_EFI_IFR_TEXT_OP: OpCodeBuffer = F2UCreateTextOpCode (UefiOpCodeHandle, (FRAMEWORK_EFI_IFR_TEXT *) FwOpCode); DataCount = 1; break; case FRAMEWORK_EFI_IFR_REF_OP: OpCodeBuffer = F2UCreateReferenceOpCode (UefiOpCodeHandle, (FRAMEWORK_EFI_IFR_REF *) FwOpCode); DataCount = 1; break; case FRAMEWORK_EFI_IFR_ONE_OF_OP: OpCodeBuffer = F2UCreateOneOfOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_ONE_OF *) FwOpCode, &NextFwOpCode, &DataCount); if (OpCodeBuffer != NULL) { FwOpCode = NextFwOpCode; // // FwOpCode is already updated to point to the next opcode. // continue; } break; case FRAMEWORK_EFI_IFR_ORDERED_LIST_OP: OpCodeBuffer = F2UCreateOrderedListOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_ORDERED_LIST *) FwOpCode, &NextFwOpCode, &DataCount); if (OpCodeBuffer != NULL) { FwOpCode = NextFwOpCode; // // FwOpCode is already updated to point to the next opcode. // continue; } break; case FRAMEWORK_EFI_IFR_CHECKBOX_OP: OpCodeBuffer = F2UCreateCheckBoxOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_CHECKBOX *) FwOpCode); DataCount = 1; break; case FRAMEWORK_EFI_IFR_STRING_OP: OpCodeBuffer = F2UCreateStringOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_STRING *) FwOpCode); DataCount = 1; break; case EFI_IFR_BANNER_OP: OpCodeBuffer = F2UCreateBannerOpCode (UefiOpCodeHandle, (EFI_IFR_BANNER *) FwOpCode); DataCount = 1; break; case EFI_IFR_END_ONE_OF_OP: OpCodeBuffer = HiiCreateEndOpCode (UefiOpCodeHandle); DataCount = 1; break; case FRAMEWORK_EFI_IFR_NUMERIC_OP: OpCodeBuffer = F2UCreateNumericOpCode (UefiOpCodeHandle, ThunkContext, (FRAMEWORK_EFI_IFR_NUMERIC *) FwOpCode); DataCount = 1; break; default: ASSERT (FALSE); return EFI_UNSUPPORTED; } if (OpCodeBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpCode + FwOpCode->Length); } return EFI_SUCCESS; }