/** Convert the IFR data into the network configuration data and set the IP configure parameters for the NIC. @param[in] IfrFormNvData The IFR NV data. @param[in, out] Instance The IP4 config2 instance. @retval EFI_SUCCESS The configure parameter for this NIC was set successfully. @retval EFI_INVALID_PARAMETER The address information for setting is invalid. @retval Others Other errors as indicated. **/ EFI_STATUS Ip4Config2ConvertIfrNvDataToConfigNvData ( IN IP4_CONFIG2_IFR_NVDATA *IfrFormNvData, IN OUT IP4_CONFIG2_INSTANCE *Instance ) { EFI_STATUS Status; EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2; IP4_CONFIG2_NVDATA *Ip4NvData; EFI_IP_ADDRESS StationAddress; EFI_IP_ADDRESS SubnetMask; EFI_IP_ADDRESS Gateway; IP4_ADDR Ip; EFI_IPv4_ADDRESS *DnsAddress; UINTN DnsCount; UINTN Index; EFI_EVENT TimeoutEvent; EFI_EVENT SetAddressEvent; BOOLEAN IsAddressOk; UINTN DataSize; EFI_INPUT_KEY Key; Status = EFI_SUCCESS; Ip4Cfg2 = &Instance->Ip4Config2; Ip4NvData = &Instance->Ip4NvData; DnsCount = 0; DnsAddress = NULL; TimeoutEvent = NULL; SetAddressEvent = NULL; if (Instance == NULL || IfrFormNvData == NULL) { return EFI_INVALID_PARAMETER; } if (IfrFormNvData->Configure != TRUE) { return EFI_SUCCESS; } if (IfrFormNvData->DhcpEnable == TRUE) { Ip4NvData->Policy = Ip4Config2PolicyDhcp; Status = Ip4Cfg2->SetData ( Ip4Cfg2, Ip4Config2DataTypePolicy, sizeof (EFI_IP4_CONFIG2_POLICY), &Ip4NvData->Policy ); if (EFI_ERROR(Status)) { return Status; } } else { // // Get Ip4NvData from IfrFormNvData if it is valid. // Ip4NvData->Policy = Ip4Config2PolicyStatic; 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); return EFI_INVALID_PARAMETER; } Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4); if (EFI_ERROR (Status) || (SubnetMask.Addr[0] != 0 && !NetIp4IsUnicast (NTOHL (StationAddress.Addr[0]), NTOHL (SubnetMask.Addr[0]))) || !Ip4StationAddressValid (NTOHL (StationAddress.Addr[0]), NTOHL (SubnetMask.Addr[0]))) { CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL); return EFI_INVALID_PARAMETER; } Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4); if (EFI_ERROR (Status) || (Gateway.Addr[0] != 0 && SubnetMask.Addr[0] != 0 && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL (SubnetMask.Addr[0])))) { CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL); return EFI_INVALID_PARAMETER; } 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); FreePool(DnsAddress); return EFI_INVALID_PARAMETER; } } } else { if (EFI_ERROR (Status)) { CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL); } } if (Ip4NvData->ManualAddress != NULL) { FreePool(Ip4NvData->ManualAddress); } Ip4NvData->ManualAddressCount = 1; Ip4NvData->ManualAddress = AllocateZeroPool(sizeof(EFI_IP4_CONFIG2_MANUAL_ADDRESS)); if (Ip4NvData->ManualAddress == NULL) { if (DnsAddress != NULL) { FreePool(DnsAddress); } return EFI_OUT_OF_RESOURCES; } CopyMem(&Ip4NvData->ManualAddress->Address, &StationAddress.v4, sizeof(EFI_IPv4_ADDRESS)); CopyMem(&Ip4NvData->ManualAddress->SubnetMask, &SubnetMask.v4, sizeof(EFI_IPv4_ADDRESS)); if (Ip4NvData->GatewayAddress != NULL) { FreePool(Ip4NvData->GatewayAddress); } Ip4NvData->GatewayAddressCount = 1; Ip4NvData->GatewayAddress = AllocateZeroPool(sizeof(EFI_IPv4_ADDRESS)); if (Ip4NvData->GatewayAddress == NULL) { if (DnsAddress != NULL) { FreePool(DnsAddress); } return EFI_OUT_OF_RESOURCES; } CopyMem(Ip4NvData->GatewayAddress, &Gateway.v4, sizeof(EFI_IPv4_ADDRESS)); if (Ip4NvData->DnsAddress != NULL) { FreePool(Ip4NvData->DnsAddress); } Ip4NvData->DnsAddressCount = (UINT32) DnsCount; Ip4NvData->DnsAddress = DnsAddress; // // Setting Ip4NvData. // Status = Ip4Cfg2->SetData ( Ip4Cfg2, Ip4Config2DataTypePolicy, sizeof (EFI_IP4_CONFIG2_POLICY), &Ip4NvData->Policy ); if (EFI_ERROR(Status)) { return Status; } // // Create events & timers for asynchronous settings. // Status = gBS->CreateEvent ( EVT_TIMER, TPL_CALLBACK, NULL, NULL, &TimeoutEvent ); if (EFI_ERROR (Status)) { return EFI_OUT_OF_RESOURCES; } Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, Ip4Config2ManualAddressNotify, &IsAddressOk, &SetAddressEvent ); if (EFI_ERROR (Status)) { goto Exit; } IsAddressOk = FALSE; Status = Ip4Cfg2->RegisterDataNotify ( Ip4Cfg2, Ip4Config2DataTypeManualAddress, SetAddressEvent ); if (EFI_ERROR (Status)) { goto Exit; } // // Set ManualAddress. // DataSize = Ip4NvData->ManualAddressCount * sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS); Status = Ip4Cfg2->SetData ( Ip4Cfg2, Ip4Config2DataTypeManualAddress, DataSize, (VOID *) Ip4NvData->ManualAddress ); if (Status == EFI_NOT_READY) { gBS->SetTimer (TimeoutEvent, TimerRelative, 50000000); while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) { if (IsAddressOk) { Status = EFI_SUCCESS; break; } } } Ip4Cfg2->UnregisterDataNotify ( Ip4Cfg2, Ip4Config2DataTypeManualAddress, SetAddressEvent ); if (EFI_ERROR (Status)) { goto Exit; } // // Set gateway. // DataSize = Ip4NvData->GatewayAddressCount * sizeof (EFI_IPv4_ADDRESS); Status = Ip4Cfg2->SetData ( Ip4Cfg2, Ip4Config2DataTypeGateway, DataSize, Ip4NvData->GatewayAddress ); if (EFI_ERROR (Status)) { goto Exit; } // // Set DNS addresses. // if (Ip4NvData->DnsAddressCount > 0 && Ip4NvData->DnsAddress != NULL) { DataSize = Ip4NvData->DnsAddressCount * sizeof (EFI_IPv4_ADDRESS); Status = Ip4Cfg2->SetData ( Ip4Cfg2, Ip4Config2DataTypeDnsServer, DataSize, Ip4NvData->DnsAddress ); if (EFI_ERROR (Status)) { goto Exit; } } } Exit: if (SetAddressEvent != NULL) { gBS->CloseEvent (SetAddressEvent); } if (TimeoutEvent != NULL) { gBS->CloseEvent (TimeoutEvent); } 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 ) { 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; }