/** Build the EFI_IFR_DATA_ARRAY which will be used to pass to EFI_FORM_CALLBACK_PROTOCOL.Callback. Check definition of EFI_IFR_DATA_ARRAY for details. ASSERT if the Question Type is not EFI_IFR_TYPE_NUM_SIZE_* or EFI_IFR_TYPE_STRING. @param ConfigAccess Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL @param QuestionId The Question ID. @param Type The Question Type. @param Value The Question Value. @param NvMapAllocated On output indicates if a buffer is allocated for NvMap. @return A pointer to EFI_IFR_DATA_ARRAY. The caller must free this buffer allocated. **/ EFI_IFR_DATA_ARRAY * CreateIfrDataArray ( IN CONFIG_ACCESS_PRIVATE *ConfigAccess, IN EFI_QUESTION_ID QuestionId, IN UINT8 Type, IN EFI_IFR_TYPE_VALUE *Value, OUT BOOLEAN *NvMapAllocated ) { EFI_IFR_DATA_ARRAY *IfrDataArray; EFI_IFR_DATA_ENTRY *IfrDataEntry; UINTN BrowserDataSize; FORMSET_STORAGE *BufferStorage; UINTN Size; EFI_STRING String; FORM_BROWSER_STATEMENT *Statement; *NvMapAllocated = FALSE; String = NULL; switch (Type) { case EFI_IFR_TYPE_NUM_SIZE_8: case EFI_IFR_TYPE_NUM_SIZE_16: case EFI_IFR_TYPE_NUM_SIZE_32: case EFI_IFR_TYPE_NUM_SIZE_64: case EFI_IFR_TYPE_BOOLEAN: Size = sizeof (*Value); break; case EFI_IFR_TYPE_STRING: if (Value->string == 0) { Size = 0; } else { String = HiiGetString (ConfigAccess->ThunkContext->UefiHiiHandle, Value->string, NULL); ASSERT (String != NULL); Size = StrSize (String); } break; case EFI_IFR_TYPE_ACTION: case EFI_IFR_TYPE_UNDEFINED: Size = 0; break; default: ASSERT (FALSE); Size = 0; break; } IfrDataArray = AllocateZeroPool (sizeof (EFI_IFR_DATA_ARRAY) + sizeof (EFI_IFR_DATA_ENTRY) + Size); ASSERT (IfrDataArray != NULL); IfrDataArray->EntryCount = 1; IfrDataEntry = (EFI_IFR_DATA_ENTRY *) (IfrDataArray + 1); Statement = GetStorageFromQuestionId (ConfigAccess->ThunkContext->FormSet, QuestionId); if (Statement == NULL || Statement->Storage == NULL) { // // The QuestionId is not associated with a Buffer Storage. // Try to get the first Buffer Storage then. // BufferStorage = GetFirstStorageOfFormSet (ConfigAccess->ThunkContext->FormSet); } else { BufferStorage = Statement->Storage; IfrDataEntry->OpCode = Statement->Operand; } if (BufferStorage != NULL) { BrowserDataSize = BufferStorage->Size; IfrDataEntry->Length = (UINT8) (sizeof (EFI_IFR_DATA_ENTRY) + Size); if (ConfigAccess->ThunkContext->NvMapOverride == NULL) { *NvMapAllocated = TRUE; IfrDataArray->NvRamMap = AllocateZeroPool (BrowserDataSize); } else { *NvMapAllocated = FALSE; IfrDataArray->NvRamMap = ConfigAccess->ThunkContext->NvMapOverride; } ASSERT (HiiGetBrowserData (&BufferStorage->Guid, BufferStorage->Name, BrowserDataSize, (UINT8 *) IfrDataArray->NvRamMap)); switch (Type) { case EFI_IFR_TYPE_NUM_SIZE_8: case EFI_IFR_TYPE_NUM_SIZE_16: case EFI_IFR_TYPE_NUM_SIZE_32: case EFI_IFR_TYPE_NUM_SIZE_64: case EFI_IFR_TYPE_BOOLEAN: CopyMem (&IfrDataEntry->Data, &(Value->u8), sizeof (*Value)); break; case EFI_IFR_TYPE_STRING: if (Size != 0) { ASSERT (String != NULL); StrCpy ((CHAR16 *) &IfrDataEntry->Data, String); FreePool (String); } break; case EFI_IFR_TYPE_ACTION: case EFI_IFR_TYPE_UNDEFINED: break; default: ASSERT (FALSE); break; } // // Need to fiil in the information for the rest of field for EFI_IFR_DATA_ENTRY. // It seems that no implementation is found to use other fields. Leave them uninitialized for now. // //UINT8 OpCode; // Likely a string, numeric, or one-of //UINT8 Length; // Length of the EFI_IFR_DATA_ENTRY packet //UINT16 Flags; // Flags settings to determine what behavior is desired from the browser after the callback //VOID *Data; // The data in the form based on the op-code type - this is not a pointer to the data, the data follows immediately // If the OpCode is a OneOf or Numeric type - Data is a UINT16 value // If the OpCode is a String type - Data is a CHAR16[x] type // If the OpCode is a Checkbox type - Data is a UINT8 value // If the OpCode is a NV Access type - Data is a FRAMEWORK_EFI_IFR_NV_DATA structure } return IfrDataArray; }
/** This function processes the results of changes in configuration. When user select a interactive opcode, this callback will be triggered. Based on the Question(QuestionId) that triggers the callback, the corresponding actions is performed. It handles: 1) the addition of boot option. 2) the addition of driver option. 3) exit from file browser 4) update of file content if a dir is selected. 5) boot the file if a file is selected in "boot from file" @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 EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. @retval EFI_DEVICE_ERROR The variable could not be saved. @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. @retval EFI_INVALID_PARAMETER If paramter Value or ActionRequest is NULL. **/ EFI_STATUS EFIAPI FileExplorerCallback ( 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 ) { BMM_CALLBACK_DATA *Private; FILE_EXPLORER_NV_DATA *NvRamMap; EFI_STATUS Status; if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { // // Do nothing for other UEFI Action. Only do call back when data is changed. // return EFI_UNSUPPORTED; } Status = EFI_SUCCESS; Private = FE_CALLBACK_DATA_FROM_THIS (This); *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; // // Retrieve uncommitted data from Form Browser // NvRamMap = &Private->FeFakeNvData; HiiGetBrowserData (&mFileExplorerGuid, mFileExplorerStorageName, sizeof (FILE_EXPLORER_NV_DATA), (UINT8 *) NvRamMap); if (Action == EFI_BROWSER_ACTION_CHANGED) { if ((Value == NULL) || (ActionRequest == NULL)) { return EFI_INVALID_PARAMETER; } if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) { // // Apply changes and exit formset // if (FileExplorerStateAddBootOption == Private->FeCurrentState) { Status = Var_UpdateBootOption (Private, NvRamMap); if (EFI_ERROR (Status)) { return Status; } BOpt_GetBootOptions (Private); CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu); } else if (FileExplorerStateAddDriverOptionState == Private->FeCurrentState) { Status = Var_UpdateDriverOption ( Private, Private->FeHiiHandle, NvRamMap->DescriptionData, NvRamMap->OptionalData, NvRamMap->ForceReconnect ); if (EFI_ERROR (Status)) { return Status; } BOpt_GetDriverOptions (Private); CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu); } *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT || QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) { // // Discard changes and exit formset // NvRamMap->OptionalData[0] = 0x0000; NvRamMap->DescriptionData[0] = 0x0000; *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; } else if (QuestionId < FILE_OPTION_OFFSET) { // // Exit File Explorer formset // *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; } } else if (Action == EFI_BROWSER_ACTION_CHANGING) { if (Value == NULL) { return EFI_INVALID_PARAMETER; } if (QuestionId >= FILE_OPTION_OFFSET) { UpdateFileExplorer (Private, QuestionId); } } return Status; }
/** This function processes the results of changes in configuration. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @param[in] Action Specifies the type of action taken by the browser. @param[in] QuestionId A unique value which is sent to the original exporting driver so that it can identify the type of data to expect. @param[in] Type The type of value for the question. @param[in] Value A pointer to the data being sent to the original exporting driver. @param[out] ActionRequest On return, points to the action requested by the callback function. @retval EFI_SUCCESS The callback successfully handled the action. @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. @retval EFI_DEVICE_ERROR The variable could not be saved. @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. **/ EFI_STATUS EFIAPI VlanCallback ( 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 ) { VLAN_CONFIG_PRIVATE_DATA *PrivateData; VLAN_CONFIGURATION *Configuration; EFI_VLAN_CONFIG_PROTOCOL *VlanConfig; UINTN Index; EFI_HANDLE VlanHandle; PrivateData = VLAN_CONFIG_PRIVATE_DATA_FROM_THIS (This); if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) { return EFI_SUCCESS; } if ((Action != EFI_BROWSER_ACTION_CHANGED) && (Action != EFI_BROWSER_ACTION_CHANGING)) { // // All other action return unsupported. // return EFI_UNSUPPORTED; } // // Get Browser data // Configuration = AllocateZeroPool (sizeof (VLAN_CONFIGURATION)); ASSERT (Configuration != NULL); HiiGetBrowserData (&gVlanConfigFormSetGuid, mVlanStorageName, sizeof (VLAN_CONFIGURATION), (UINT8 *) Configuration); VlanConfig = PrivateData->VlanConfig; if (Action == EFI_BROWSER_ACTION_CHANGED) { switch (QuestionId) { case VLAN_ADD_QUESTION_ID: // // Add a VLAN // VlanConfig->Set (VlanConfig, Configuration->VlanId, Configuration->Priority); VlanUpdateForm (PrivateData); // // Connect the newly created VLAN device // VlanHandle = NetLibGetVlanHandle (PrivateData->ControllerHandle, Configuration->VlanId); if (VlanHandle == NULL) { // // There may be no child handle created for VLAN ID 0, connect the parent handle // VlanHandle = PrivateData->ControllerHandle; } gBS->ConnectController (VlanHandle, NULL, NULL, TRUE); // // Clear UI data // *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; Configuration->VlanId = 0; Configuration->Priority = 0; break; case VLAN_REMOVE_QUESTION_ID: // // Remove VLAN // ASSERT (PrivateData->NumberOfVlan <= MAX_VLAN_NUMBER); for (Index = 0; Index < PrivateData->NumberOfVlan; Index++) { if (Configuration->VlanList[Index] != 0) { // // Checkbox is selected, need remove this VLAN // VlanConfig->Remove (VlanConfig, PrivateData->VlanId[Index]); } } VlanUpdateForm (PrivateData); if (PrivateData->NumberOfVlan == 0) { // // No VLAN device now, connect the physical NIC handle. // Note: PrivateData->NumberOfVlan has been updated by VlanUpdateForm() // gBS->ConnectController (PrivateData->ControllerHandle, NULL, NULL, TRUE); } *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; ZeroMem (Configuration->VlanList, MAX_VLAN_NUMBER); break; default: break; } } else if (Action == EFI_BROWSER_ACTION_CHANGING) { switch (QuestionId) { case VLAN_UPDATE_QUESTION_ID: // // Update current VLAN list into Form. // VlanUpdateForm (PrivateData); break; default: break; } } HiiSetBrowserData (&gVlanConfigFormSetGuid, mVlanStorageName, sizeof (VLAN_CONFIGURATION), (UINT8 *) Configuration, NULL); FreePool (Configuration); return EFI_SUCCESS; }
/** This function processes the results of changes in configuration. When user select a interactive opcode, this callback will be triggered. Based on the Question(QuestionId) that triggers the callback, the corresponding actions is performed. It handles: 1) the addition of boot option. 2) the addition of driver option. 3) exit from file browser 4) update of file content if a dir is selected. 5) boot the file if a file is selected in "boot from file" @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 EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. @retval EFI_DEVICE_ERROR The variable could not be saved. @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. @retval EFI_INVALID_PARAMETER If paramter Value or ActionRequest is NULL. **/ EFI_STATUS EFIAPI FileExplorerCallback ( 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 ) { BMM_CALLBACK_DATA *Private; FILE_EXPLORER_NV_DATA *NvRamMap; EFI_STATUS Status; if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { // // All other action return unsupported. // return EFI_UNSUPPORTED; } Status = EFI_SUCCESS; Private = FE_CALLBACK_DATA_FROM_THIS (This); // // Retrieve uncommitted data from Form Browser // NvRamMap = &Private->FeFakeNvData; HiiGetBrowserData (&gFileExploreFormSetGuid, mFileExplorerStorageName, sizeof (FILE_EXPLORER_NV_DATA), (UINT8 *) NvRamMap); if (Action == EFI_BROWSER_ACTION_CHANGED) { if ((Value == NULL) || (ActionRequest == NULL)) { return EFI_INVALID_PARAMETER; } if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT) { NvRamMap->BootOptionChanged = FALSE; *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; } else if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) { NvRamMap->DriverOptionChanged = FALSE; *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) { // // Discard changes and exit formset // NvRamMap->DriverOptionalData[0] = 0x0000; NvRamMap->DriverDescriptionData[0] = 0x0000; NvRamMap->DriverOptionChanged = FALSE; *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT) { // // Discard changes and exit formset // NvRamMap->BootOptionalData[0] = 0x0000; NvRamMap->BootDescriptionData[0] = 0x0000; NvRamMap->BootOptionChanged = FALSE; *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; } else if (QuestionId == KEY_VALUE_BOOT_DESCRIPTION || QuestionId == KEY_VALUE_BOOT_OPTION) { NvRamMap->BootOptionChanged = TRUE; } else if (QuestionId == KEY_VALUE_DRIVER_DESCRIPTION || QuestionId == KEY_VALUE_DRIVER_OPTION) { NvRamMap->DriverOptionChanged = TRUE; } else if (QuestionId < FILE_OPTION_OFFSET) { // // Exit File Explorer formset // *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; } else if (QuestionId >= FILE_OPTION_OFFSET && QuestionId < FILE_OPTION_GOTO_OFFSET) { // // Update forms may return TRUE or FALSE, need to check here. // if (UpdateFileExplorer (Private, QuestionId)) { *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; } } } else if (Action == EFI_BROWSER_ACTION_CHANGING) { if (Value == NULL) { return EFI_INVALID_PARAMETER; } if (QuestionId >= FILE_OPTION_GOTO_OFFSET) { // // function will always return FALSE, no need to check here. // UpdateFileExplorer (Private, QuestionId); } } // // Pass changed uncommitted data back to Form Browser // HiiSetBrowserData (&gFileExploreFormSetGuid, mFileExplorerStorageName, sizeof (FILE_EXPLORER_NV_DATA), (UINT8 *) NvRamMap, NULL); return Status; }
/** Adjust question value when one question value has been changed. @param QuestionId The question id for the value changed question. @param Value The value for the changed question. **/ VOID AdjustOptionValue ( IN UINT16 QuestionId, IN EFI_IFR_TYPE_VALUE *Value ) { UINTN Number; BBS_TYPE BbsType; LEGACY_DEV_ORDER_ENTRY *DevOrder; UINT16 *Default; LEGACY_BOOT_NV_DATA *CurrentNVMap; UINT16 *CurrentVal; UINTN Index; UINTN Index2; UINTN Index3; UINTN NewValuePos; UINTN OldValue; UINTN NewValue; UINT8 *DisMap; UINTN Pos; UINTN Bit; Number = 0; BbsType = BBS_UNKNOWN; CurrentVal = 0; DevOrder = NULL; Default = NULL; NewValue = 0; NewValuePos = 0; // // Update Select FD/HD/CD/NET/BEV Order Form // ASSERT ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)); CurrentNVMap = &mLegacyBootOptionPrivate->MaintainMapData->CurrentNvData; HiiGetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeof (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap); DisMap = mLegacyBootOptionPrivate->MaintainMapData->DisableMap; if (QuestionId >= LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyFDMenu.MenuNumber; BbsType = BBS_FLOPPY; CurrentVal = CurrentNVMap->LegacyFD; Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyFD; } else if (QuestionId >= LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_HD_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyHDMenu.MenuNumber; BbsType = BBS_HARDDISK; CurrentVal = CurrentNVMap->LegacyHD; Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyHD; } else if (QuestionId >= LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_CD_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyCDMenu.MenuNumber; BbsType = BBS_CDROM; CurrentVal = CurrentNVMap->LegacyCD; Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyCD; } else if (QuestionId >= LEGACY_NET_QUESTION_ID && QuestionId < LEGACY_NET_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyNETMenu.MenuNumber; BbsType = BBS_EMBED_NETWORK; CurrentVal = CurrentNVMap->LegacyNET; Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyNET; } else if (QuestionId >= LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyBEVMenu.MenuNumber; BbsType = BBS_BEV_DEVICE; CurrentVal = CurrentNVMap->LegacyBEV; Default = mLegacyBootOptionPrivate->MaintainMapData->LastTimeNvData.LegacyBEV; } // // First, find the different position // if there is change, it should be only one // for (Index = 0; Index < Number; Index++) { if (CurrentVal[Index] != Default[Index]) { OldValue = Default[Index]; NewValue = CurrentVal[Index]; break; } } if (Index != Number) { // // there is change, now process // if (0xFF == NewValue) { // // This item will be disable // Just move the items behind this forward to overlap it // Pos = OldValue / 8; Bit = 7 - (OldValue % 8); DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); for (Index2 = Index; Index2 < Number - 1; Index2++) { CurrentVal[Index2] = CurrentVal[Index2 + 1]; } CurrentVal[Index2] = 0xFF; } else { for (Index2 = 0; Index2 < Number; Index2++) { if (Index2 == Index) { continue; } if (Default[Index2] == NewValue) { // // If NewValue is in OldLegacyDev array // remember its old position // NewValuePos = Index2; break; } } if (Index2 != Number) { // // We will change current item to an existing item // (It's hard to describe here, please read code, it's like a cycle-moving) // for (Index2 = NewValuePos; Index2 != Index;) { if (NewValuePos < Index) { CurrentVal[Index2] = Default[Index2 + 1]; Index2++; } else { CurrentVal[Index2] = Default[Index2 - 1]; Index2--; } } } else { // // If NewValue is not in OldlegacyDev array, we are changing to a disabled item // so we should modify DisMap to reflect the change // Pos = NewValue / 8; Bit = 7 - (NewValue % 8); DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit))); if (0xFF != OldValue) { // // Because NewValue is a item that was disabled before // so after changing the OldValue should be disabled // actually we are doing a swap of enable-disable states of two items // Pos = OldValue / 8; Bit = 7 - (OldValue % 8); DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); } } } // // To prevent DISABLE appears in the middle of the list // we should perform a re-ordering // Index3 = Index; Index = 0; while (Index < Number) { if (0xFF != CurrentVal[Index]) { Index++; continue; } Index2 = Index; Index2++; while (Index2 < Number) { if (0xFF != CurrentVal[Index2]) { break; } Index2++; } if (Index2 < Number) { CurrentVal[Index] = CurrentVal[Index2]; CurrentVal[Index2] = 0xFF; } Index++; } // // Return correct question value. // Value->u16 = CurrentVal[Index3]; CopyMem (Default, CurrentVal, sizeof (UINT16) * Number); } // // Pass changed uncommitted data back to Form Browser // HiiSetBrowserData (&mLegacyBootOptionGuid, mLegacyBootStorageName, sizeof (LEGACY_BOOT_NV_DATA), (UINT8 *) CurrentNVMap, NULL); }
/** This function is called to provide results data to the driver. This data consists of a unique key that is used to identify which data is either being passed back or being asked for. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @param[in] Action Specifies the type of action taken by the browser. @param[in] QuestionId A unique value which is sent to the original exporting driver so that it can identify the type of data to expect. The format of the data tends to vary based on the opcode that enerated the callback. @param[in] Type The type of value for the question. @param[in] Value A pointer to the data being sent to the original exporting driver. @param[out] ActionRequest On return, points to the action requested by the callback function. @retval EFI_SUCCESS The callback successfully handled the action. @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. @retval EFI_DEVICE_ERROR The variable could not be saved. @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.Currently not implemented. @retval EFI_INVALID_PARAMETERS Passing in wrong parameter. @retval Others Other errors as indicated. **/ EFI_STATUS EFIAPI Ip4FormCallback ( 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 ) { IP4_CONFIG_INSTANCE *Ip4ConfigInstance; CHAR8 Ip4String[IP4_STR_MAX_SIZE]; IP4_CONFIG_IFR_NVDATA *IfrFormNvData; EFI_IP_ADDRESS HostIp; EFI_IP_ADDRESS SubnetMask; EFI_IP_ADDRESS Gateway; EFI_STATUS Status; EFI_INPUT_KEY Key; Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This); IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA)); if (IfrFormNvData == NULL) { return EFI_OUT_OF_RESOURCES; } // // Retrive uncommitted data from Browser // if (!HiiGetBrowserData (&mNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE, sizeof (IP4_CONFIG_IFR_NVDATA), (UINT8 *) IfrFormNvData)) { FreePool (IfrFormNvData); return EFI_NOT_FOUND; } Status = EFI_SUCCESS; switch (QuestionId) { case KEY_ENABLE: if (IfrFormNvData->Configure == 0) { Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = FALSE; } else { Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = TRUE; } break; case KEY_DHCP_ENABLE: if (IfrFormNvData->DhcpEnable == 0) { Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = FALSE; } else { Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = TRUE; } break; case KEY_LOCAL_IP: UnicodeStrToAsciiStr (IfrFormNvData->StationAddress, Ip4String); Status = Ip4AsciiStrToIp (Ip4String, &HostIp.v4); if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) { CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL); Status = EFI_INVALID_PARAMETER; } else { CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, &HostIp.v4, sizeof (HostIp.v4)); } break; case KEY_SUBNET_MASK: UnicodeStrToAsciiStr (IfrFormNvData->SubnetMask, Ip4String); Status = Ip4AsciiStrToIp (Ip4String, &SubnetMask.v4); if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) { CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid SubnetMask!", NULL); Status = EFI_INVALID_PARAMETER; } else { CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4)); } break; case KEY_GATE_WAY: UnicodeStrToAsciiStr (IfrFormNvData->GatewayAddress, Ip4String); Status = Ip4AsciiStrToIp (Ip4String, &Gateway.v4); if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) { CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL); Status = EFI_INVALID_PARAMETER; } else { CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, &Gateway.v4, sizeof (Gateway.v4)); } break; case KEY_SAVE_CHANGES: Status = Ip4ConfigConvertIfrNvDataToDeviceConfigData (Ip4ConfigInstance); *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; break; default: break; } if (!EFI_ERROR (Status)) { // // Pass changed uncommitted data back to Form Browser // HiiSetBrowserData (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, sizeof (IP4_CONFIG_IFR_NVDATA), (UINT8 *) IfrFormNvData, NULL); } FreePool (IfrFormNvData); return Status; }
/** This function is called to provide results data to the driver. This data consists of a unique key that is used to identify which data is either being passed back or being asked for. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @param[in] Action Specifies the type of action taken by the browser. @param[in] QuestionId A unique value which is sent to the original exporting driver so that it can identify the type of data to expect. The format of the data tends to vary based on the opcode that enerated the callback. @param[in] Type The type of value for the question. @param[in] Value A pointer to the data being sent to the original exporting driver. @param[out] ActionRequest On return, points to the action requested by the callback function. @retval EFI_SUCCESS The callback successfully handled the action. @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. @retval EFI_DEVICE_ERROR The variable could not be saved. @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.Currently not implemented. @retval EFI_INVALID_PARAMETERS Passing in wrong parameter. @retval Others Other errors as indicated. **/ EFI_STATUS EFIAPI Ip4FormCallback ( 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; IP4_CONFIG2_INSTANCE *Instance; IP4_CONFIG2_IFR_NVDATA *IfrFormNvData; IP4_FORM_CALLBACK_INFO *Private; EFI_IP_ADDRESS StationAddress; EFI_IP_ADDRESS SubnetMask; EFI_IP_ADDRESS Gateway; IP4_ADDR Ip; EFI_IPv4_ADDRESS *DnsAddress; UINTN DnsCount; UINTN Index; EFI_INPUT_KEY Key; IfrFormNvData = NULL; DnsCount = 0; DnsAddress = NULL; if (Action == EFI_BROWSER_ACTION_CHANGED) { Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(This); Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK(Private); IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA)); if (IfrFormNvData == NULL) { return EFI_OUT_OF_RESOURCES; } // // Retrieve uncommitted data from Browser // if (!HiiGetBrowserData (&gIp4Config2NvDataGuid, mIp4Config2StorageName, sizeof (IP4_CONFIG2_IFR_NVDATA), (UINT8 *) IfrFormNvData)) { FreePool (IfrFormNvData); return EFI_NOT_FOUND; } Status = EFI_SUCCESS; switch (QuestionId) { case KEY_LOCAL_IP: Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4); if (EFI_ERROR (Status) || IP4_IS_UNSPECIFIED (NTOHL (StationAddress.Addr[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (StationAddress.Addr[0]))) { CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL); Status = EFI_INVALID_PARAMETER; } break; case KEY_SUBNET_MASK: Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4); if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) { CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL); Status = EFI_INVALID_PARAMETER; } break; case KEY_GATE_WAY: Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4); if (EFI_ERROR (Status) || IP4_IS_LOCAL_BROADCAST(NTOHL(Gateway.Addr[0]))) { CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL); Status = EFI_INVALID_PARAMETER; } break; case KEY_DNS: Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount); if (!EFI_ERROR (Status) && DnsCount > 0) { for (Index = 0; Index < DnsCount; Index ++) { CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR)); if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) { CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL); Status = EFI_INVALID_PARAMETER; break; } } } else { if (EFI_ERROR (Status)) { CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL); } } if(DnsAddress != NULL) { FreePool(DnsAddress); } break; case KEY_SAVE_CHANGES: Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Instance); *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; break; default: break; } FreePool (IfrFormNvData); return Status; } // // All other action return unsupported. // return EFI_UNSUPPORTED; }
/** This function processes the results of changes in 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 EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. @retval EFI_DEVICE_ERROR The variable could not be saved. @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid. **/ EFI_STATUS EFIAPI BootMaintCallback ( 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 ) { BMM_CALLBACK_DATA *Private; BM_MENU_ENTRY *NewMenuEntry; BMM_FAKE_NV_DATA *CurrentFakeNVMap; EFI_STATUS Status; UINTN OldValue; UINTN NewValue; UINTN Number; UINTN Pos; UINTN Bit; UINT16 NewValuePos; UINT16 Index3; UINT16 Index2; UINT16 Index; UINT8 *OldLegacyDev; UINT8 *NewLegacyDev; UINT8 *DisMap; if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { // // All other action return unsupported. // return EFI_UNSUPPORTED; } Status = EFI_SUCCESS; OldValue = 0; NewValue = 0; Number = 0; OldLegacyDev = NULL; NewLegacyDev = NULL; NewValuePos = 0; DisMap = NULL; Private = BMM_CALLBACK_DATA_FROM_THIS (This); // // Retrive uncommitted data from Form Browser // CurrentFakeNVMap = &Private->BmmFakeNvData; HiiGetBrowserData (&gBootMaintFormSetGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap); if (Action == EFI_BROWSER_ACTION_CHANGING) { if (Value == NULL) { return EFI_INVALID_PARAMETER; } UpdatePageId (Private, QuestionId); // // need to be subtituded. // // Update Select FD/HD/CD/NET/BEV Order Form // if ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)) { DisMap = Private->BmmOldFakeNVData.DisableMap; if (QuestionId >= LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyFDMenu.MenuNumber; OldLegacyDev = Private->BmmOldFakeNVData.LegacyFD; NewLegacyDev = CurrentFakeNVMap->LegacyFD; } else if (QuestionId >= LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_HD_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyHDMenu.MenuNumber; OldLegacyDev = Private->BmmOldFakeNVData.LegacyHD; NewLegacyDev = CurrentFakeNVMap->LegacyHD; } else if (QuestionId >= LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_CD_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyCDMenu.MenuNumber; OldLegacyDev = Private->BmmOldFakeNVData.LegacyCD; NewLegacyDev = CurrentFakeNVMap->LegacyCD; } else if (QuestionId >= LEGACY_NET_QUESTION_ID && QuestionId < LEGACY_NET_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyNETMenu.MenuNumber; OldLegacyDev = Private->BmmOldFakeNVData.LegacyNET; NewLegacyDev = CurrentFakeNVMap->LegacyNET; } else if (QuestionId >= LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER) { Number = (UINT16) LegacyBEVMenu.MenuNumber; OldLegacyDev = Private->BmmOldFakeNVData.LegacyBEV; NewLegacyDev = CurrentFakeNVMap->LegacyBEV; } // // First, find the different position // if there is change, it should be only one // for (Index = 0; Index < Number; Index++) { if (OldLegacyDev[Index] != NewLegacyDev[Index]) { OldValue = OldLegacyDev[Index]; NewValue = NewLegacyDev[Index]; break; } } if (Index != Number) { // // there is change, now process // if (0xFF == NewValue) { // // This item will be disable // Just move the items behind this forward to overlap it // Pos = OldValue / 8; Bit = 7 - (OldValue % 8); DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); for (Index2 = Index; Index2 < Number - 1; Index2++) { NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1]; } NewLegacyDev[Index2] = 0xFF; } else { for (Index2 = 0; Index2 < Number; Index2++) { if (Index2 == Index) { continue; } if (OldLegacyDev[Index2] == NewValue) { // // If NewValue is in OldLegacyDev array // remember its old position // NewValuePos = Index2; break; } } if (Index2 != Number) { // // We will change current item to an existing item // (It's hard to describe here, please read code, it's like a cycle-moving) // for (Index2 = NewValuePos; Index2 != Index;) { if (NewValuePos < Index) { NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1]; Index2++; } else { NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1]; Index2--; } } } else { // // If NewValue is not in OldlegacyDev array, we are changing to a disabled item // so we should modify DisMap to reflect the change // Pos = NewValue / 8; Bit = 7 - (NewValue % 8); DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit))); if (0xFF != OldValue) { // // Because NewValue is a item that was disabled before // so after changing the OldValue should be disabled // actually we are doing a swap of enable-disable states of two items // Pos = OldValue / 8; Bit = 7 - (OldValue % 8); DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit)); } } } // // To prevent DISABLE appears in the middle of the list // we should perform a re-ordering // Index3 = Index; Index = 0; while (Index < Number) { if (0xFF != NewLegacyDev[Index]) { Index++; continue; } Index2 = Index; Index2++; while (Index2 < Number) { if (0xFF != NewLegacyDev[Index2]) { break; } Index2++; } if (Index2 < Number) { NewLegacyDev[Index] = NewLegacyDev[Index2]; NewLegacyDev[Index2] = 0xFF; } Index++; } CopyMem ( OldLegacyDev, NewLegacyDev, Number ); // // Return correct question value. // Value->u8 = NewLegacyDev[Index3]; } } if (QuestionId < FILE_OPTION_OFFSET) { if (QuestionId < CONFIG_OPTION_OFFSET) { switch (QuestionId) { case KEY_VALUE_BOOT_FROM_FILE: Private->FeCurrentState = FileExplorerStateBootFromFile; break; case FORM_BOOT_ADD_ID: Private->FeCurrentState = FileExplorerStateAddBootOption; break; case FORM_DRV_ADD_FILE_ID: Private->FeCurrentState = FileExplorerStateAddDriverOptionState; break; case FORM_DRV_ADD_HANDLE_ID: CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private); UpdateDrvAddHandlePage (Private); break; case FORM_BOOT_DEL_ID: CleanUpPage (FORM_BOOT_DEL_ID, Private); UpdateBootDelPage (Private); break; case FORM_BOOT_CHG_ID: case FORM_DRV_CHG_ID: UpdatePageBody (QuestionId, Private); break; case FORM_DRV_DEL_ID: CleanUpPage (FORM_DRV_DEL_ID, Private); UpdateDrvDelPage (Private); break; case FORM_BOOT_NEXT_ID: CleanUpPage (FORM_BOOT_NEXT_ID, Private); UpdateBootNextPage (Private); break; case FORM_TIME_OUT_ID: CleanUpPage (FORM_TIME_OUT_ID, Private); UpdateTimeOutPage (Private); break; case FORM_CON_IN_ID: case FORM_CON_OUT_ID: case FORM_CON_ERR_ID: UpdatePageBody (QuestionId, Private); break; case FORM_CON_MODE_ID: CleanUpPage (FORM_CON_MODE_ID, Private); UpdateConModePage (Private); break; case FORM_CON_COM_ID: CleanUpPage (FORM_CON_COM_ID, Private); UpdateConCOMPage (Private); break; case FORM_SET_FD_ORDER_ID: case FORM_SET_HD_ORDER_ID: case FORM_SET_CD_ORDER_ID: case FORM_SET_NET_ORDER_ID: case FORM_SET_BEV_ORDER_ID: CleanUpPage (QuestionId, Private); UpdateSetLegacyDeviceOrderPage (QuestionId, Private); break; default: break; } } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) { Index2 = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET); Private->CurrentTerminal = Index2; CleanUpPage (FORM_CON_COM_SETUP_ID, Private); UpdateTerminalPage (Private); } else if (QuestionId >= HANDLE_OPTION_OFFSET) { Index2 = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET); NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index2); ASSERT (NewMenuEntry != NULL); Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private); Private->MenuEntry = NewMenuEntry; Private->LoadContext->FilePathList = Private->HandleContext->DevicePath; UpdateDriverAddHandleDescPage (Private); } } } else if (Action == EFI_BROWSER_ACTION_CHANGED) { if ((Value == NULL) || (ActionRequest == NULL)) { return EFI_INVALID_PARAMETER; } switch (QuestionId) { case KEY_VALUE_SAVE_AND_EXIT: case KEY_VALUE_NO_SAVE_AND_EXIT: if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) { Status = ApplyChangeHandler (Private, CurrentFakeNVMap, Private->BmmPreviousPageId); if (EFI_ERROR (Status)) { return Status; } } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) { DiscardChangeHandler (Private, CurrentFakeNVMap); } // // Tell browser not to ask for confirmation of changes, // since we have already applied or discarded. // *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; break; case FORM_RESET: gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); return EFI_UNSUPPORTED; default: break; } } // // Pass changed uncommitted data back to Form Browser // HiiSetBrowserData (&gBootMaintFormSetGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap, NULL); return EFI_SUCCESS; }
/** This function processes the results of changes in 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 EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. @retval EFI_DEVICE_ERROR The variable could not be saved. @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid. **/ EFI_STATUS EFIAPI BootMaintCallback ( 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 ) { BMM_CALLBACK_DATA *Private; BM_MENU_ENTRY *NewMenuEntry; BMM_FAKE_NV_DATA *CurrentFakeNVMap; EFI_STATUS Status; UINTN OldValue; UINTN NewValue; UINTN Number; UINTN Index; // //Chech whether exit from FileExplorer and reenter BM,if yes,reclaim string depositories // if (Action == EFI_BROWSER_ACTION_FORM_OPEN){ if(mEnterFileExplorer ){ ReclaimStringDepository(); mEnterFileExplorer = FALSE; } } if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { // // Do nothing for other UEFI Action. Only do call back when data is changed. // return EFI_UNSUPPORTED; } OldValue = 0; NewValue = 0; Number = 0; Private = BMM_CALLBACK_DATA_FROM_THIS (This); // // Retrive uncommitted data from Form Browser // CurrentFakeNVMap = &Private->BmmFakeNvData; HiiGetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap); if (Action == EFI_BROWSER_ACTION_CHANGING) { if (Value == NULL) { return EFI_INVALID_PARAMETER; } UpdatePageId (Private, QuestionId); if (QuestionId < FILE_OPTION_OFFSET) { if (QuestionId < CONFIG_OPTION_OFFSET) { switch (QuestionId) { case FORM_BOOT_ADD_ID: // Leave Bm and enter FileExplorer. Private->FeCurrentState = FileExplorerStateAddBootOption; Private->FeDisplayContext = FileExplorerDisplayUnknown; ReclaimStringDepository (); UpdateFileExplorer(Private, 0); mEnterFileExplorer = TRUE; break; case FORM_DRV_ADD_FILE_ID: // Leave Bm and enter FileExplorer. Private->FeCurrentState = FileExplorerStateAddDriverOptionState; Private->FeDisplayContext = FileExplorerDisplayUnknown; ReclaimStringDepository (); UpdateFileExplorer(Private, 0); mEnterFileExplorer = TRUE; break; case FORM_DRV_ADD_HANDLE_ID: CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private); UpdateDrvAddHandlePage (Private); break; case FORM_BOOT_DEL_ID: CleanUpPage (FORM_BOOT_DEL_ID, Private); UpdateBootDelPage (Private); break; case FORM_BOOT_CHG_ID: case FORM_DRV_CHG_ID: UpdatePageBody (QuestionId, Private); break; case FORM_DRV_DEL_ID: CleanUpPage (FORM_DRV_DEL_ID, Private); UpdateDrvDelPage (Private); break; case FORM_BOOT_NEXT_ID: CleanUpPage (FORM_BOOT_NEXT_ID, Private); UpdateBootNextPage (Private); break; case FORM_TIME_OUT_ID: CleanUpPage (FORM_TIME_OUT_ID, Private); UpdateTimeOutPage (Private); break; case FORM_CON_IN_ID: case FORM_CON_OUT_ID: case FORM_CON_ERR_ID: UpdatePageBody (QuestionId, Private); break; case FORM_CON_MODE_ID: CleanUpPage (FORM_CON_MODE_ID, Private); UpdateConModePage (Private); break; case FORM_CON_COM_ID: CleanUpPage (FORM_CON_COM_ID, Private); UpdateConCOMPage (Private); break; default: break; } } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) { Index = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET); Private->CurrentTerminal = Index; CleanUpPage (FORM_CON_COM_SETUP_ID, Private); UpdateTerminalPage (Private); } else if (QuestionId >= HANDLE_OPTION_OFFSET) { Index = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET); NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index); ASSERT (NewMenuEntry != NULL); Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private); Private->MenuEntry = NewMenuEntry; Private->LoadContext->FilePathList = Private->HandleContext->DevicePath; UpdateDriverAddHandleDescPage (Private); } } if (QuestionId == KEY_VALUE_BOOT_FROM_FILE){ // Leave Bm and enter FileExplorer. Private->FeCurrentState = FileExplorerStateBootFromFile; Private->FeDisplayContext = FileExplorerDisplayUnknown; ReclaimStringDepository (); UpdateFileExplorer(Private, 0); mEnterFileExplorer = TRUE; } } else if (Action == EFI_BROWSER_ACTION_CHANGED) { if ((Value == NULL) || (ActionRequest == NULL)) { return EFI_INVALID_PARAMETER; } switch (QuestionId) { case KEY_VALUE_SAVE_AND_EXIT: case KEY_VALUE_NO_SAVE_AND_EXIT: if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) { Status = ApplyChangeHandler (Private, CurrentFakeNVMap, Private->BmmPreviousPageId); if (EFI_ERROR (Status)) { return Status; } } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) { DiscardChangeHandler (Private, CurrentFakeNVMap); } // // Tell browser not to ask for confirmation of changes, // since we have already applied or discarded. // *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; break; case FORM_RESET: gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); return EFI_UNSUPPORTED; default: break; } } // // Pass changed uncommitted data back to Form Browser // HiiSetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap, NULL); return EFI_SUCCESS; }
/** This function processes the results of changes in 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 EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. @retval EFI_DEVICE_ERROR The variable could not be saved. @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid. **/ EFI_STATUS EFIAPI BootMaintCallback ( 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 ) { BMM_CALLBACK_DATA *Private; BM_MENU_ENTRY *NewMenuEntry; BMM_FAKE_NV_DATA *CurrentFakeNVMap; UINTN Index; EFI_DEVICE_PATH_PROTOCOL * File; if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) { // // Do nothing for other UEFI Action. Only do call back when data is changed. // return EFI_UNSUPPORTED; } Private = BMM_CALLBACK_DATA_FROM_THIS (This); // // Retrive uncommitted data from Form Browser // CurrentFakeNVMap = &Private->BmmFakeNvData; HiiGetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap); if (Action == EFI_BROWSER_ACTION_CHANGING) { if (Value == NULL) { return EFI_INVALID_PARAMETER; } UpdatePageId (Private, QuestionId); if (QuestionId < FILE_OPTION_OFFSET) { if (QuestionId < CONFIG_OPTION_OFFSET) { switch (QuestionId) { case FORM_BOOT_ADD_ID: // Leave BMM and enter FileExplorer. ChooseFile (NULL, L".efi", CreateBootOptionFromFile, &File); break; case FORM_DRV_ADD_FILE_ID: // Leave BMM and enter FileExplorer. ChooseFile (NULL, L".efi", CreateDriverOptionFromFile, &File); break; case FORM_DRV_ADD_HANDLE_ID: CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private); UpdateDrvAddHandlePage (Private); break; case FORM_BOOT_DEL_ID: CleanUpPage (FORM_BOOT_DEL_ID, Private); UpdateBootDelPage (Private); break; case FORM_BOOT_CHG_ID: case FORM_DRV_CHG_ID: UpdatePageBody (QuestionId, Private); break; case FORM_DRV_DEL_ID: CleanUpPage (FORM_DRV_DEL_ID, Private); UpdateDrvDelPage (Private); break; case FORM_CON_IN_ID: case FORM_CON_OUT_ID: case FORM_CON_ERR_ID: UpdatePageBody (QuestionId, Private); break; case FORM_CON_MODE_ID: CleanUpPage (FORM_CON_MODE_ID, Private); UpdateConModePage (Private); break; case FORM_CON_COM_ID: CleanUpPage (FORM_CON_COM_ID, Private); UpdateConCOMPage (Private); break; default: break; } } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) { Index = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET); Private->CurrentTerminal = Index; CleanUpPage (FORM_CON_COM_SETUP_ID, Private); UpdateTerminalPage (Private); } else if (QuestionId >= HANDLE_OPTION_OFFSET) { Index = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET); NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index); ASSERT (NewMenuEntry != NULL); Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private); Private->MenuEntry = NewMenuEntry; Private->LoadContext->FilePathList = Private->HandleContext->DevicePath; UpdateDriverAddHandleDescPage (Private); } } if (QuestionId == KEY_VALUE_BOOT_FROM_FILE){ // Leave BMM and enter FileExplorer. ChooseFile (NULL, L".efi", BootFromFile, &File); } } else if (Action == EFI_BROWSER_ACTION_CHANGED) { if ((Value == NULL) || (ActionRequest == NULL)) { return EFI_INVALID_PARAMETER; } if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_BOOT) { CurrentFakeNVMap->BootOptionChanged = FALSE; *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; } else if (QuestionId == KEY_VALUE_SAVE_AND_EXIT_DRIVER) { CurrentFakeNVMap->DriverOptionChanged = FALSE; *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_DRIVER) { // // Discard changes and exit formset // CurrentFakeNVMap->DriverOptionalData[0] = 0x0000; CurrentFakeNVMap->DriverDescriptionData[0] = 0x0000; CurrentFakeNVMap->DriverOptionChanged = FALSE; CurrentFakeNVMap->ForceReconnect = TRUE; *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT_BOOT) { // // Discard changes and exit formset // CurrentFakeNVMap->BootOptionalData[0] = 0x0000; CurrentFakeNVMap->BootDescriptionData[0] = 0x0000; CurrentFakeNVMap->BootOptionChanged = FALSE; *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; } else if (QuestionId == KEY_VALUE_BOOT_DESCRIPTION || QuestionId == KEY_VALUE_BOOT_OPTION) { CurrentFakeNVMap->BootOptionChanged = TRUE; } else if (QuestionId == KEY_VALUE_DRIVER_DESCRIPTION || QuestionId == KEY_VALUE_DRIVER_OPTION) { CurrentFakeNVMap->DriverOptionChanged = TRUE; } if ((QuestionId >= BOOT_OPTION_DEL_QUESTION_ID) && (QuestionId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) { if (Value->b){ // // Means user try to delete this boot option but not press F10 or "Commit Changes and Exit" menu. // CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = TRUE; } else { // // Means user remove the old check status. // CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = FALSE; } } else if ((QuestionId >= DRIVER_OPTION_DEL_QUESTION_ID) && (QuestionId < DRIVER_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) { if (Value->b){ CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = TRUE; } else { CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = FALSE; } } else { switch (QuestionId) { case KEY_VALUE_SAVE_AND_EXIT: case KEY_VALUE_NO_SAVE_AND_EXIT: if (QuestionId == KEY_VALUE_SAVE_AND_EXIT) { *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; } else if (QuestionId == KEY_VALUE_NO_SAVE_AND_EXIT) { DiscardChangeHandler (Private, CurrentFakeNVMap); *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; } break; case FORM_RESET: gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); return EFI_UNSUPPORTED; default: break; } } } // // Pass changed uncommitted data back to Form Browser // HiiSetBrowserData (&mBootMaintGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap, NULL); return EFI_SUCCESS; }