X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FNetwork%2FIp4Dxe%2FIp4Config2Impl.c;fp=MdeModulePkg%2FUniversal%2FNetwork%2FIp4Dxe%2FIp4Config2Impl.c;h=0000000000000000000000000000000000000000;hb=4542f8b8135f1f1ee5654e25139be9769e139ddd;hp=9dca48ddd6458044b089ed6b492ee29b8a365a0d;hpb=c0fd7f734e2d33e22215899b40a47b843129541d;p=mirror_edk2.git diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c deleted file mode 100644 index 9dca48ddd6..0000000000 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c +++ /dev/null @@ -1,2168 +0,0 @@ -/** @file - The implementation of EFI IPv4 Configuration II Protocol. - - Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
- (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
- - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include "Ip4Impl.h" - -LIST_ENTRY mIp4Config2InstanceList = {&mIp4Config2InstanceList, &mIp4Config2InstanceList}; - -/** - The event process routine when the DHCPv4 service binding protocol is installed - in the system. - - @param[in] Event Not used. - @param[in] Context Pointer to the IP4 config2 instance data. - -**/ -VOID -EFIAPI -Ip4Config2OnDhcp4SbInstalled ( - IN EFI_EVENT Event, - IN VOID *Context - ); - -/** - Destroy the Dhcp4 child in IP4_CONFIG2_INSTANCE and release the resources. - - @param[in, out] Instance The buffer of IP4 config2 instance to be freed. - - @retval EFI_SUCCESS The child was successfully destroyed. - @retval Others Failed to destroy the child. - -**/ -EFI_STATUS -Ip4Config2DestroyDhcp4 ( - IN OUT IP4_CONFIG2_INSTANCE *Instance - ) -{ - IP4_SERVICE *IpSb; - EFI_STATUS Status; - EFI_DHCP4_PROTOCOL *Dhcp4; - - Dhcp4 = Instance->Dhcp4; - ASSERT (Dhcp4 != NULL); - - Dhcp4->Stop (Dhcp4); - Dhcp4->Configure (Dhcp4, NULL); - Instance->Dhcp4 = NULL; - - IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); - - // - // Close DHCPv4 protocol and destroy the child. - // - Status = gBS->CloseProtocol ( - Instance->Dhcp4Handle, - &gEfiDhcp4ProtocolGuid, - IpSb->Image, - IpSb->Controller - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = NetLibDestroyServiceChild ( - IpSb->Controller, - IpSb->Image, - &gEfiDhcp4ServiceBindingProtocolGuid, - Instance->Dhcp4Handle - ); - - Instance->Dhcp4Handle = NULL; - - return Status; -} - -/** - Update the current policy to NewPolicy. During the transition - period, the default router list - and address list in all interfaces will be released. - - @param[in] IpSb The IP4 service binding instance. - @param[in] NewPolicy The new policy to be updated to. - -**/ -VOID -Ip4Config2OnPolicyChanged ( - IN IP4_SERVICE *IpSb, - IN EFI_IP4_CONFIG2_POLICY NewPolicy - ) -{ - IP4_INTERFACE *IpIf; - IP4_ROUTE_TABLE *RouteTable; - - // - // Currently there are only two policies: static and dhcp. Regardless of - // what transition is going on, i.e., static -> dhcp and dhcp -> - // static, we have to free default router table and all addresses. - // - - if (IpSb->DefaultInterface != NULL) { - if (IpSb->DefaultRouteTable != NULL) { - Ip4FreeRouteTable (IpSb->DefaultRouteTable); - IpSb->DefaultRouteTable = NULL; - } - - Ip4CancelReceive (IpSb->DefaultInterface); - - Ip4FreeInterface (IpSb->DefaultInterface, NULL); - IpSb->DefaultInterface = NULL; - } - - Ip4CleanAssembleTable (&IpSb->Assemble); - - // - // Create new default interface and route table. - // - IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image); - if (IpIf == NULL) { - return ; - } - - RouteTable = Ip4CreateRouteTable (); - if (RouteTable == NULL) { - Ip4FreeInterface (IpIf, NULL); - return ; - } - - IpSb->DefaultInterface = IpIf; - InsertHeadList (&IpSb->Interfaces, &IpIf->Link); - IpSb->DefaultRouteTable = RouteTable; - Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb); - - if (IpSb->State == IP4_SERVICE_CONFIGED || IpSb->State == IP4_SERVICE_STARTED) { - IpSb->State = IP4_SERVICE_UNSTARTED; - } - - // - // Start the dhcp configuration. - // - if (NewPolicy == Ip4Config2PolicyDhcp) { - Ip4StartAutoConfig (&IpSb->Ip4Config2Instance); - } - -} - -/** - Signal the registered event. It is the callback routine for NetMapIterate. - - @param[in] Map Points to the list of registered event. - @param[in] Item The registered event. - @param[in] Arg Not used. - - @retval EFI_SUCCESS The event was signaled successfully. -**/ -EFI_STATUS -EFIAPI -Ip4Config2SignalEvent ( - IN NET_MAP *Map, - IN NET_MAP_ITEM *Item, - IN VOID *Arg - ) -{ - gBS->SignalEvent ((EFI_EVENT) Item->Key); - - return EFI_SUCCESS; -} - -/** - Read the configuration data from variable storage according to the VarName and - gEfiIp4Config2ProtocolGuid. It checks the integrity of variable data. If the - data is corrupted, it clears the variable data to ZERO. Othewise, it outputs the - configuration data to IP4_CONFIG2_INSTANCE. - - @param[in] VarName The pointer to the variable name - @param[in, out] Instance The pointer to the IP4 config2 instance data. - - @retval EFI_NOT_FOUND The variable can not be found or already corrupted. - @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation. - @retval EFI_SUCCESS The configuration data was retrieved successfully. - -**/ -EFI_STATUS -Ip4Config2ReadConfigData ( - IN CHAR16 *VarName, - IN OUT IP4_CONFIG2_INSTANCE *Instance - ) -{ - EFI_STATUS Status; - UINTN VarSize; - IP4_CONFIG2_VARIABLE *Variable; - IP4_CONFIG2_DATA_ITEM *DataItem; - UINTN Index; - IP4_CONFIG2_DATA_RECORD DataRecord; - CHAR8 *Data; - - // - // Try to read the configuration variable. - // - VarSize = 0; - Status = gRT->GetVariable ( - VarName, - &gEfiIp4Config2ProtocolGuid, - NULL, - &VarSize, - NULL - ); - - if (Status == EFI_BUFFER_TOO_SMALL) { - // - // Allocate buffer and read the config variable. - // - Variable = AllocatePool (VarSize); - if (Variable == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Status = gRT->GetVariable ( - VarName, - &gEfiIp4Config2ProtocolGuid, - NULL, - &VarSize, - Variable - ); - if (EFI_ERROR (Status) || (UINT16) (~NetblockChecksum ((UINT8 *) Variable, (UINT32) VarSize)) != 0) { - // - // GetVariable still error or the variable is corrupted. - // Fall back to the default value. - // - FreePool (Variable); - - // - // Remove the problematic variable and return EFI_NOT_FOUND, a new - // variable will be set again. - // - gRT->SetVariable ( - VarName, - &gEfiIp4Config2ProtocolGuid, - IP4_CONFIG2_VARIABLE_ATTRIBUTE, - 0, - NULL - ); - - return EFI_NOT_FOUND; - } - - - for (Index = 0; Index < Variable->DataRecordCount; Index++) { - - CopyMem (&DataRecord, &Variable->DataRecord[Index], sizeof (DataRecord)); - - DataItem = &Instance->DataItem[DataRecord.DataType]; - if (DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED) && - (DataItem->DataSize != DataRecord.DataSize) - ) { - // - // Perhaps a corrupted data record... - // - continue; - } - - if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED)) { - // - // This data item has variable length data. - // - DataItem->Data.Ptr = AllocatePool (DataRecord.DataSize); - if (DataItem->Data.Ptr == NULL) { - // - // no memory resource - // - continue; - } - } - - Data = (CHAR8 *) Variable + DataRecord.Offset; - CopyMem (DataItem->Data.Ptr, Data, DataRecord.DataSize); - - DataItem->DataSize = DataRecord.DataSize; - DataItem->Status = EFI_SUCCESS; - } - - FreePool (Variable); - return EFI_SUCCESS; - } - - return Status; -} - -/** - Write the configuration data from IP4_CONFIG2_INSTANCE to variable storage. - - @param[in] VarName The pointer to the variable name. - @param[in] Instance The pointer to the IP4 config2 instance data. - - @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation. - @retval EFI_SUCCESS The configuration data is written successfully. - -**/ -EFI_STATUS -Ip4Config2WriteConfigData ( - IN CHAR16 *VarName, - IN IP4_CONFIG2_INSTANCE *Instance - ) -{ - UINTN Index; - UINTN VarSize; - IP4_CONFIG2_DATA_ITEM *DataItem; - IP4_CONFIG2_VARIABLE *Variable; - IP4_CONFIG2_DATA_RECORD *DataRecord; - CHAR8 *Heap; - EFI_STATUS Status; - - VarSize = sizeof (IP4_CONFIG2_VARIABLE) - sizeof (IP4_CONFIG2_DATA_RECORD); - - for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) { - - DataItem = &Instance->DataItem[Index]; - if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_VOLATILE) && !EFI_ERROR (DataItem->Status)) { - - VarSize += sizeof (IP4_CONFIG2_DATA_RECORD) + DataItem->DataSize; - } - } - - Variable = AllocatePool (VarSize); - if (Variable == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Heap = (CHAR8 *) Variable + VarSize; - Variable->DataRecordCount = 0; - - for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) { - - DataItem = &Instance->DataItem[Index]; - if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_VOLATILE) && !EFI_ERROR (DataItem->Status)) { - - Heap -= DataItem->DataSize; - CopyMem (Heap, DataItem->Data.Ptr, DataItem->DataSize); - - DataRecord = &Variable->DataRecord[Variable->DataRecordCount]; - DataRecord->DataType = (EFI_IP4_CONFIG2_DATA_TYPE) Index; - DataRecord->DataSize = (UINT32) DataItem->DataSize; - DataRecord->Offset = (UINT16) (Heap - (CHAR8 *) Variable); - - Variable->DataRecordCount++; - } - } - - Variable->Checksum = 0; - Variable->Checksum = (UINT16) ~NetblockChecksum ((UINT8 *) Variable, (UINT32) VarSize); - - Status = gRT->SetVariable ( - VarName, - &gEfiIp4Config2ProtocolGuid, - IP4_CONFIG2_VARIABLE_ATTRIBUTE, - VarSize, - Variable - ); - - FreePool (Variable); - - return Status; -} - - -/** - Build a EFI_IP4_ROUTE_TABLE to be returned to the caller of GetModeData. - The EFI_IP4_ROUTE_TABLE is clumsy to use in the internal operation of the - IP4 driver. - - @param[in] IpSb The IP4 service binding instance. - @param[out] Table The built IP4 route table. - - @retval EFI_SUCCESS The route table is successfully build - @retval EFI_NOT_FOUND Failed to allocate the memory for the rotue table. - -**/ -EFI_STATUS -Ip4Config2BuildDefaultRouteTable ( - IN IP4_SERVICE *IpSb, - OUT EFI_IP4_ROUTE_TABLE *Table - ) -{ - LIST_ENTRY *Entry; - IP4_ROUTE_ENTRY *RtEntry; - UINT32 Count; - INT32 Index; - - if (IpSb->DefaultRouteTable == NULL) { - return EFI_NOT_FOUND; - } - - Count = IpSb->DefaultRouteTable->TotalNum; - - if (Count == 0) { - return EFI_NOT_FOUND; - } - - // - // Copy the route entry to EFI route table. Keep the order of - // route entry copied from most specific to default route. That - // is, interlevel the route entry from the instance's route area - // and those from the default route table's route area. - // - Count = 0; - - for (Index = IP4_MASK_MAX; Index >= 0; Index--) { - - NET_LIST_FOR_EACH (Entry, &(IpSb->DefaultRouteTable->RouteArea[Index])) { - RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link); - - EFI_IP4 (Table[Count].SubnetAddress) = HTONL (RtEntry->Dest & RtEntry->Netmask); - EFI_IP4 (Table[Count].SubnetMask) = HTONL (RtEntry->Netmask); - EFI_IP4 (Table[Count].GatewayAddress) = HTONL (RtEntry->NextHop); - - Count++; - } - - } - - return EFI_SUCCESS; -} - -/** - The event process routine when the DHCPv4 service binding protocol is installed - in the system. - - @param[in] Event Not used. - @param[in] Context The pointer to the IP4 config2 instance data. - -**/ -VOID -EFIAPI -Ip4Config2OnDhcp4SbInstalled ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - IP4_CONFIG2_INSTANCE *Instance; - - Instance = (IP4_CONFIG2_INSTANCE *) Context; - - if ((Instance->Dhcp4Handle != NULL) || (Instance->Policy != Ip4Config2PolicyDhcp)) { - // - // The DHCP4 child is already created or the policy is no longer DHCP. - // - return ; - } - - Ip4StartAutoConfig (Instance); -} - -/** - Set the station address and subnetmask for the default interface. - - @param[in] IpSb The pointer to the IP4 service binding instance. - @param[in] StationAddress Ip address to be set. - @param[in] SubnetMask Subnet to be set. - - @retval EFI_SUCCESS Set default address successful. - @retval Others Some errors occur in setting. - -**/ -EFI_STATUS -Ip4Config2SetDefaultAddr ( - IN IP4_SERVICE *IpSb, - IN IP4_ADDR StationAddress, - IN IP4_ADDR SubnetMask - ) -{ - EFI_STATUS Status; - IP4_INTERFACE *IpIf; - IP4_PROTOCOL *Ip4Instance; - EFI_ARP_PROTOCOL *Arp; - LIST_ENTRY *Entry; - IP4_ADDR Subnet; - IP4_ROUTE_TABLE *RouteTable; - - IpIf = IpSb->DefaultInterface; - ASSERT (IpIf != NULL); - - if ((IpIf->Ip == StationAddress) && (IpIf->SubnetMask == SubnetMask)) { - IpSb->State = IP4_SERVICE_CONFIGED; - return EFI_SUCCESS; - } - - if (IpSb->Reconfig) { - // - // The default address is changed, free the previous interface first. - // - if (IpSb->DefaultRouteTable != NULL) { - Ip4FreeRouteTable (IpSb->DefaultRouteTable); - IpSb->DefaultRouteTable = NULL; - } - - Ip4CancelReceive (IpSb->DefaultInterface); - Ip4FreeInterface (IpSb->DefaultInterface, NULL); - IpSb->DefaultInterface = NULL; - // - // Create new default interface and route table. - // - IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image); - if (IpIf == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - RouteTable = Ip4CreateRouteTable (); - if (RouteTable == NULL) { - Ip4FreeInterface (IpIf, NULL); - return EFI_OUT_OF_RESOURCES; - } - - IpSb->DefaultInterface = IpIf; - InsertHeadList (&IpSb->Interfaces, &IpIf->Link); - IpSb->DefaultRouteTable = RouteTable; - Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb); - } - - if (IpSb->State == IP4_SERVICE_CONFIGED) { - IpSb->State = IP4_SERVICE_UNSTARTED; - } - - Status = Ip4SetAddress (IpIf, StationAddress, SubnetMask); - if (EFI_ERROR (Status)) { - return Status; - } - - if (IpIf->Arp != NULL) { - // - // A non-NULL IpIf->Arp here means a new ARP child is created when setting default address, - // but some IP children may have referenced the default interface before it is configured, - // these IP instances also consume this ARP protocol so they need to open it BY_CHILD_CONTROLLER. - // - Arp = NULL; - NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) { - Ip4Instance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, AddrLink, IP4_PROTOCOL_SIGNATURE); - Status = gBS->OpenProtocol ( - IpIf->ArpHandle, - &gEfiArpProtocolGuid, - (VOID **) &Arp, - gIp4DriverBinding.DriverBindingHandle, - Ip4Instance->Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - if (EFI_ERROR (Status)) { - return Status; - } - } - } - - // - // Add a route for the connected network. - // - Subnet = StationAddress & SubnetMask; - - Ip4AddRoute ( - IpSb->DefaultRouteTable, - Subnet, - SubnetMask, - IP4_ALLZERO_ADDRESS - ); - - IpSb->State = IP4_SERVICE_CONFIGED; - IpSb->Reconfig = FALSE; - - return EFI_SUCCESS; -} - -/** - Set the station address, subnetmask and gateway address for the default interface. - - @param[in] Instance The pointer to the IP4 config2 instance data. - @param[in] StationAddress Ip address to be set. - @param[in] SubnetMask Subnet to be set. - @param[in] GatewayAddress Gateway to be set. - - @retval EFI_SUCCESS Set default If successful. - @retval Others Errors occur as indicated. - -**/ -EFI_STATUS -Ip4Config2SetDefaultIf ( - IN IP4_CONFIG2_INSTANCE *Instance, - IN IP4_ADDR StationAddress, - IN IP4_ADDR SubnetMask, - IN IP4_ADDR GatewayAddress - ) -{ - EFI_STATUS Status; - IP4_SERVICE *IpSb; - - IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); - - // - // Check whether the StationAddress/SubnetMask pair is valid. - // - if (!Ip4StationAddressValid (StationAddress, SubnetMask)) { - return EFI_INVALID_PARAMETER; - } - - Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Create a route if there is a default router. - // - if (GatewayAddress != IP4_ALLZERO_ADDRESS) { - Ip4AddRoute ( - IpSb->DefaultRouteTable, - IP4_ALLZERO_ADDRESS, - IP4_ALLZERO_ADDRESS, - GatewayAddress - ); - } - - return EFI_SUCCESS; -} - - -/** - Release all the DHCP related resources. - - @param Instance The IP4 config2 instance. - - @return None - -**/ -VOID -Ip4Config2CleanDhcp4 ( - IN IP4_CONFIG2_INSTANCE *Instance - ) -{ - IP4_SERVICE *IpSb; - - IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); - - if (Instance->Dhcp4 != NULL) { - Instance->Dhcp4->Stop (Instance->Dhcp4); - - gBS->CloseProtocol ( - Instance->Dhcp4Handle, - &gEfiDhcp4ProtocolGuid, - IpSb->Image, - IpSb->Controller - ); - - Instance->Dhcp4 = NULL; - } - - if (Instance->Dhcp4Handle != NULL) { - NetLibDestroyServiceChild ( - IpSb->Controller, - IpSb->Image, - &gEfiDhcp4ServiceBindingProtocolGuid, - Instance->Dhcp4Handle - ); - - Instance->Dhcp4Handle = NULL; - } - - if (Instance->Dhcp4Event != NULL) { - gBS->CloseEvent (Instance->Dhcp4Event); - Instance->Dhcp4Event = NULL; - } -} - -/** - This worker function sets the DNS server list for the EFI IPv4 network - stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL - manages. The DNS server addresses must be unicast IPv4 addresses. - - @param[in] Instance The pointer to the IP4 config2 instance data. - @param[in] DataSize The size of the buffer pointed to by Data in bytes. - @param[in] Data The data buffer to set, points to an array of - EFI_IPv4_ADDRESS instances. - - @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type. - @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid. - @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation. - @retval EFI_ABORTED The DNS server addresses to be set equal the current - configuration. - @retval EFI_SUCCESS The specified configuration data for the EFI IPv4 - network stack was set. - -**/ -EFI_STATUS -Ip4Config2SetDnsServerWorker ( - IN IP4_CONFIG2_INSTANCE *Instance, - IN UINTN DataSize, - IN VOID *Data - ) -{ - UINTN OldIndex; - UINTN NewIndex; - EFI_IPv4_ADDRESS *OldDns; - EFI_IPv4_ADDRESS *NewDns; - UINTN OldDnsCount; - UINTN NewDnsCount; - IP4_CONFIG2_DATA_ITEM *Item; - BOOLEAN OneAdded; - VOID *Tmp; - IP4_ADDR DnsAddress; - - if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) { - return EFI_BAD_BUFFER_SIZE; - } - - Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer]; - NewDns = (EFI_IPv4_ADDRESS *) Data; - OldDns = Item->Data.DnsServers; - NewDnsCount = DataSize / sizeof (EFI_IPv4_ADDRESS); - OldDnsCount = Item->DataSize / sizeof (EFI_IPv4_ADDRESS); - OneAdded = FALSE; - - if (NewDnsCount != OldDnsCount) { - Tmp = AllocatePool (DataSize); - if (Tmp == NULL) { - return EFI_OUT_OF_RESOURCES; - } - } else { - Tmp = NULL; - } - - for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) { - CopyMem (&DnsAddress, NewDns + NewIndex, sizeof (IP4_ADDR)); - if (IP4_IS_UNSPECIFIED (NTOHL (DnsAddress)) || IP4_IS_LOCAL_BROADCAST (NTOHL (DnsAddress))) { - // - // The dns server address must be unicast. - // - if (Tmp != NULL) { - FreePool (Tmp); - } - return EFI_INVALID_PARAMETER; - } - - if (OneAdded) { - // - // If any address in the new setting is not in the old settings, skip the - // comparision below. - // - continue; - } - - for (OldIndex = 0; OldIndex < OldDnsCount; OldIndex++) { - if (EFI_IP4_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) { - // - // If found break out. - // - break; - } - } - - if (OldIndex == OldDnsCount) { - OneAdded = TRUE; - } - } - - if (!OneAdded && (DataSize == Item->DataSize)) { - // - // No new item is added and the size is the same. - // - Item->Status = EFI_SUCCESS; - return EFI_ABORTED; - } else { - if (Tmp != NULL) { - if (Item->Data.Ptr != NULL) { - FreePool (Item->Data.Ptr); - } - Item->Data.Ptr = Tmp; - } - - CopyMem (Item->Data.Ptr, Data, DataSize); - Item->DataSize = DataSize; - Item->Status = EFI_SUCCESS; - return EFI_SUCCESS; - } -} - - - -/** - Callback function when DHCP process finished. It will save the - retrieved IP configure parameter from DHCP to the NVRam. - - @param Event The callback event - @param Context Opaque context to the callback - - @return None - -**/ -VOID -EFIAPI -Ip4Config2OnDhcp4Complete ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - IP4_CONFIG2_INSTANCE *Instance; - EFI_DHCP4_MODE_DATA Dhcp4Mode; - EFI_STATUS Status; - IP4_ADDR StationAddress; - IP4_ADDR SubnetMask; - IP4_ADDR GatewayAddress; - UINT32 Index; - UINT32 OptionCount; - EFI_DHCP4_PACKET_OPTION **OptionList; - - Instance = (IP4_CONFIG2_INSTANCE *) Context; - ASSERT (Instance->Dhcp4 != NULL); - - // - // Get the DHCP retrieved parameters - // - Status = Instance->Dhcp4->GetModeData (Instance->Dhcp4, &Dhcp4Mode); - - if (EFI_ERROR (Status)) { - goto Exit; - } - - if (Dhcp4Mode.State == Dhcp4Bound) { - StationAddress = EFI_NTOHL (Dhcp4Mode.ClientAddress); - SubnetMask = EFI_NTOHL (Dhcp4Mode.SubnetMask); - GatewayAddress = EFI_NTOHL (Dhcp4Mode.RouterAddress); - - Status = Ip4Config2SetDefaultIf (Instance, StationAddress, SubnetMask, GatewayAddress); - if (EFI_ERROR (Status)) { - goto Exit; - } - - // - // Parse the ACK to get required DNS server information. - // - OptionCount = 0; - OptionList = NULL; - - Status = Instance->Dhcp4->Parse (Instance->Dhcp4, Dhcp4Mode.ReplyPacket, &OptionCount, OptionList); - if (Status != EFI_BUFFER_TOO_SMALL) { - goto Exit; - } - - OptionList = AllocateZeroPool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *)); - if (OptionList == NULL) { - goto Exit; - } - - Status = Instance->Dhcp4->Parse (Instance->Dhcp4, Dhcp4Mode.ReplyPacket, &OptionCount, OptionList); - if (EFI_ERROR (Status)) { - FreePool (OptionList); - goto Exit; - } - - for (Index = 0; Index < OptionCount; Index++) { - // - // Look for DNS Server opcode (6). - // - if (OptionList[Index]->OpCode == DHCP4_TAG_DNS_SERVER) { - if (((OptionList[Index]->Length & 0x3) != 0) || (OptionList[Index]->Length == 0)) { - break; - } - - Ip4Config2SetDnsServerWorker (Instance, OptionList[Index]->Length, &OptionList[Index]->Data[0]); - break; - } - } - - FreePool (OptionList); - - Instance->DhcpSuccess = TRUE; - } - -Exit: - Ip4Config2CleanDhcp4 (Instance); - DispatchDpc (); -} - - -/** - Start the DHCP configuration for this IP service instance. - It will locates the EFI_IP4_CONFIG2_PROTOCOL, then start the - DHCP configuration. - - @param[in] Instance The IP4 config2 instance to configure - - @retval EFI_SUCCESS The auto configuration is successfully started - @retval Others Failed to start auto configuration. - -**/ -EFI_STATUS -Ip4StartAutoConfig ( - IN IP4_CONFIG2_INSTANCE *Instance - ) -{ - IP4_SERVICE *IpSb; - EFI_DHCP4_PROTOCOL *Dhcp4; - EFI_DHCP4_MODE_DATA Dhcp4Mode; - EFI_DHCP4_PACKET_OPTION *OptionList[1]; - IP4_CONFIG2_DHCP4_OPTION ParaList; - EFI_STATUS Status; - - IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); - - if (IpSb->State > IP4_SERVICE_UNSTARTED) { - return EFI_SUCCESS; - } - - // - // A host must not invoke DHCP configuration if it is already - // participating in the DHCP configuraiton process. - // - if (Instance->Dhcp4Handle != NULL) { - return EFI_SUCCESS; - } - - Status = NetLibCreateServiceChild ( - IpSb->Controller, - IpSb->Image, - &gEfiDhcp4ServiceBindingProtocolGuid, - &Instance->Dhcp4Handle - ); - - if (Status == EFI_UNSUPPORTED) { - // - // No DHCPv4 Service Binding protocol, register a notify. - // - if (Instance->Dhcp4SbNotifyEvent == NULL) { - Instance->Dhcp4SbNotifyEvent = EfiCreateProtocolNotifyEvent ( - &gEfiDhcp4ServiceBindingProtocolGuid, - TPL_CALLBACK, - Ip4Config2OnDhcp4SbInstalled, - (VOID *) Instance, - &Instance->Registration - ); - } - } - - if (EFI_ERROR (Status)) { - return Status; - } - - if (Instance->Dhcp4SbNotifyEvent != NULL) { - gBS->CloseEvent (Instance->Dhcp4SbNotifyEvent); - } - - Status = gBS->OpenProtocol ( - Instance->Dhcp4Handle, - &gEfiDhcp4ProtocolGuid, - (VOID **) &Instance->Dhcp4, - IpSb->Image, - IpSb->Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - NetLibDestroyServiceChild ( - IpSb->Controller, - IpSb->Image, - &gEfiDhcp4ServiceBindingProtocolGuid, - Instance->Dhcp4Handle - ); - - Instance->Dhcp4Handle = NULL; - - return Status; - } - - // - // Check the current DHCP status, if the DHCP process has - // already finished, return now. - // - Dhcp4 = Instance->Dhcp4; - Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode); - if (Dhcp4Mode.State == Dhcp4Bound) { - Ip4Config2OnDhcp4Complete (NULL, Instance); - - return EFI_SUCCESS; - } - - // - // Try to start the DHCP process. Use most of the current - // DHCP configuration to avoid problems if some DHCP client - // yields the control of this DHCP service to us. - // - ParaList.Head.OpCode = DHCP4_TAG_PARA_LIST; - ParaList.Head.Length = 3; - ParaList.Head.Data[0] = DHCP4_TAG_NETMASK; - ParaList.Route = DHCP4_TAG_ROUTER; - ParaList.Dns = DHCP4_TAG_DNS_SERVER; - OptionList[0] = &ParaList.Head; - Dhcp4Mode.ConfigData.OptionCount = 1; - Dhcp4Mode.ConfigData.OptionList = OptionList; - - Status = Dhcp4->Configure (Dhcp4, &Dhcp4Mode.ConfigData); - if (EFI_ERROR (Status)) { - gBS->CloseProtocol ( - Instance->Dhcp4Handle, - &gEfiDhcp4ProtocolGuid, - IpSb->Image, - IpSb->Controller - ); - - NetLibDestroyServiceChild ( - IpSb->Controller, - IpSb->Image, - &gEfiDhcp4ServiceBindingProtocolGuid, - Instance->Dhcp4Handle - ); - - Instance->Dhcp4 = NULL; - - Instance->Dhcp4Handle = NULL; - - return Status; - } - - // - // Start the DHCP process - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, - Ip4Config2OnDhcp4Complete, - Instance, - &Instance->Dhcp4Event - ); - if (EFI_ERROR (Status)) { - Ip4Config2DestroyDhcp4 (Instance); - return Status; - } - - Status = Dhcp4->Start (Dhcp4, Instance->Dhcp4Event); - if (EFI_ERROR (Status)) { - Ip4Config2DestroyDhcp4 (Instance); - gBS->CloseEvent (Instance->Dhcp4Event); - Instance->Dhcp4Event = NULL; - - return Status; - } - - IpSb->State = IP4_SERVICE_STARTED; - DispatchDpc (); - - return EFI_SUCCESS; -} - - - -/** - The work function is to get the interface information of the communication - device this IP4_CONFIG2_INSTANCE manages. - - @param[in] Instance Pointer to the IP4 config2 instance data. - @param[in, out] DataSize On input, in bytes, the size of Data. On output, in - bytes, the size of buffer required to store the specified - configuration data. - @param[in] Data The data buffer in which the configuration data is returned. - Ignored if DataSize is ZERO. - - @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified - configuration data, and the required size is - returned in DataSize. - @retval EFI_SUCCESS The specified configuration data was obtained. - -**/ -EFI_STATUS -Ip4Config2GetIfInfo ( - IN IP4_CONFIG2_INSTANCE *Instance, - IN OUT UINTN *DataSize, - IN VOID *Data OPTIONAL - ) -{ - IP4_SERVICE *IpSb; - UINTN Length; - IP4_CONFIG2_DATA_ITEM *Item; - EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo; - IP4_ADDR Address; - - IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); - Length = sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO); - - if (IpSb->DefaultRouteTable != NULL) { - Length += IpSb->DefaultRouteTable->TotalNum * sizeof (EFI_IP4_ROUTE_TABLE); - } - - if (*DataSize < Length) { - *DataSize = Length; - return EFI_BUFFER_TOO_SMALL; - } - - // - // Copy the fixed size part of the interface info. - // - Item = &Instance->DataItem[Ip4Config2DataTypeInterfaceInfo]; - IfInfo = (EFI_IP4_CONFIG2_INTERFACE_INFO *) Data; - CopyMem (IfInfo, Item->Data.Ptr, sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO)); - - // - // Update the address info. - // - if (IpSb->DefaultInterface != NULL) { - Address = HTONL (IpSb->DefaultInterface->Ip); - CopyMem (&IfInfo->StationAddress, &Address, sizeof (EFI_IPv4_ADDRESS)); - Address = HTONL (IpSb->DefaultInterface->SubnetMask); - CopyMem (&IfInfo->SubnetMask, &Address, sizeof (EFI_IPv4_ADDRESS)); - } - - if (IpSb->DefaultRouteTable != NULL) { - IfInfo->RouteTableSize = IpSb->DefaultRouteTable->TotalNum; - IfInfo->RouteTable = (EFI_IP4_ROUTE_TABLE *) ((UINT8 *) Data + sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO)); - - Ip4Config2BuildDefaultRouteTable (IpSb, IfInfo->RouteTable); - } - - return EFI_SUCCESS; -} - -/** - The work function is to set the general configuration policy for the EFI IPv4 network - stack that is running on the communication device managed by this IP4_CONFIG2_INSTANCE. - The policy will affect other configuration settings. - - @param[in] Instance Pointer to the IP4 config2 instance data. - @param[in] DataSize Size of the buffer pointed to by Data in bytes. - @param[in] Data The data buffer to set. - - @retval EFI_INVALID_PARAMETER The to be set policy is invalid. - @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type. - @retval EFI_ABORTED The new policy equals the current policy. - @retval EFI_SUCCESS The specified configuration data for the EFI IPv6 - network stack was set. - -**/ -EFI_STATUS -Ip4Config2SetPolicy ( - IN IP4_CONFIG2_INSTANCE *Instance, - IN UINTN DataSize, - IN VOID *Data - ) -{ - EFI_IP4_CONFIG2_POLICY NewPolicy; - IP4_CONFIG2_DATA_ITEM *DataItem; - IP4_SERVICE *IpSb; - - if (DataSize != sizeof (EFI_IP4_CONFIG2_POLICY)) { - return EFI_BAD_BUFFER_SIZE; - } - - NewPolicy = *((EFI_IP4_CONFIG2_POLICY *) Data); - - if (NewPolicy >= Ip4Config2PolicyMax) { - return EFI_INVALID_PARAMETER; - } - - if (NewPolicy == Instance->Policy) { - if (NewPolicy != Ip4Config2PolicyDhcp || Instance->DhcpSuccess) { - return EFI_ABORTED; - } - } else { - // - // The policy is changed. Clean the ManualAddress, Gateway and DnsServers, - // shrink the variable data size, and fire up all the related events. - // - DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress]; - if (DataItem->Data.Ptr != NULL) { - FreePool (DataItem->Data.Ptr); - } - DataItem->Data.Ptr = NULL; - DataItem->DataSize = 0; - DataItem->Status = EFI_NOT_FOUND; - NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL); - - DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway]; - if (DataItem->Data.Ptr != NULL) { - FreePool (DataItem->Data.Ptr); - } - DataItem->Data.Ptr = NULL; - DataItem->DataSize = 0; - DataItem->Status = EFI_NOT_FOUND; - NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL); - - DataItem = &Instance->DataItem[Ip4Config2DataTypeDnsServer]; - if (DataItem->Data.Ptr != NULL) { - FreePool (DataItem->Data.Ptr); - } - DataItem->Data.Ptr = NULL; - DataItem->DataSize = 0; - DataItem->Status = EFI_NOT_FOUND; - NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL); - - if (NewPolicy == Ip4Config2PolicyDhcp) { - SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_VOLATILE); - } else { - // - // The policy is changed from dhcp to static. Stop the DHCPv4 process - // and destroy the DHCPv4 child. - // - if (Instance->Dhcp4Handle != NULL) { - Ip4Config2DestroyDhcp4 (Instance); - } - - // - // Close the event. - // - if (Instance->Dhcp4Event != NULL) { - gBS->CloseEvent (Instance->Dhcp4Event); - Instance->Dhcp4Event = NULL; - } - } - } - - IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); - Ip4Config2OnPolicyChanged (IpSb, NewPolicy); - - Instance->Policy = NewPolicy; - - return EFI_SUCCESS; -} - -/** - The work function is to set the station addresses manually for the EFI IPv4 - network stack. It is only configurable when the policy is Ip4Config2PolicyStatic. - - @param[in] Instance Pointer to the IP4 config2 instance data. - @param[in] DataSize Size of the buffer pointed to by Data in bytes. - @param[in] Data The data buffer to set. - - @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type. - @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set - under the current policy. - @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid. - @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation. - @retval EFI_NOT_READY An asynchrous process is invoked to set the specified - configuration data, and the process is not finished. - @retval EFI_ABORTED The manual addresses to be set equal current - configuration. - @retval EFI_SUCCESS The specified configuration data for the EFI IPv6 - network stack was set. - -**/ -EFI_STATUS -Ip4Config2SetManualAddress ( - IN IP4_CONFIG2_INSTANCE *Instance, - IN UINTN DataSize, - IN VOID *Data - ) -{ - EFI_IP4_CONFIG2_MANUAL_ADDRESS NewAddress; - IP4_CONFIG2_DATA_ITEM *DataItem; - EFI_STATUS Status; - IP4_ADDR StationAddress; - IP4_ADDR SubnetMask; - VOID *Ptr; - IP4_SERVICE *IpSb; - IP4_INTERFACE *IpIf; - IP4_ROUTE_TABLE *RouteTable; - - DataItem = NULL; - Status = EFI_SUCCESS; - Ptr = NULL; - IpIf = NULL; - RouteTable = NULL; - - IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); - - ASSERT (Instance->DataItem[Ip4Config2DataTypeManualAddress].Status != EFI_NOT_READY); - - if ((DataSize != 0) && ((DataSize % sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS)) != 0)) { - return EFI_BAD_BUFFER_SIZE; - } - - if (Instance->Policy != Ip4Config2PolicyStatic) { - return EFI_WRITE_PROTECTED; - } - - DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress]; - - if (Data != NULL && DataSize != 0) { - NewAddress = *((EFI_IP4_CONFIG2_MANUAL_ADDRESS *) Data); - - StationAddress = EFI_NTOHL (NewAddress.Address); - SubnetMask = EFI_NTOHL (NewAddress.SubnetMask); - - // - // Check whether the StationAddress/SubnetMask pair is valid. - // - if (!Ip4StationAddressValid (StationAddress, SubnetMask)) { - return EFI_INVALID_PARAMETER; - } - - // - // Store the new data, and init the DataItem status to EFI_NOT_READY because - // we may have an asynchronous configuration process. - // - Ptr = AllocateCopyPool (DataSize, Data); - if (Ptr == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - if (DataItem->Data.Ptr != NULL) { - FreePool (DataItem->Data.Ptr); - } - - DataItem->Data.Ptr = Ptr; - DataItem->DataSize = DataSize; - DataItem->Status = EFI_NOT_READY; - - IpSb->Reconfig = TRUE; - Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask); - - DataItem->Status = Status; - - if (EFI_ERROR (DataItem->Status) && DataItem->Status != EFI_NOT_READY) { - if (Ptr != NULL) { - FreePool (Ptr); - } - DataItem->Data.Ptr = NULL; - } - } else { - // - // DataSize is 0 and Data is NULL, clean up the manual address. - // - if (DataItem->Data.Ptr != NULL) { - FreePool (DataItem->Data.Ptr); - } - DataItem->Data.Ptr = NULL; - DataItem->DataSize = 0; - DataItem->Status = EFI_NOT_FOUND; - - // - // Free the default router table and Interface, clean up the assemble table. - // - if (IpSb->DefaultInterface != NULL) { - if (IpSb->DefaultRouteTable != NULL) { - Ip4FreeRouteTable (IpSb->DefaultRouteTable); - IpSb->DefaultRouteTable = NULL; - } - - Ip4CancelReceive (IpSb->DefaultInterface); - - Ip4FreeInterface (IpSb->DefaultInterface, NULL); - IpSb->DefaultInterface = NULL; - } - - Ip4CleanAssembleTable (&IpSb->Assemble); - - // - // Create new default interface and route table. - // - IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image); - if (IpIf == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - RouteTable = Ip4CreateRouteTable (); - if (RouteTable == NULL) { - Ip4FreeInterface (IpIf, NULL); - return EFI_OUT_OF_RESOURCES; - } - - IpSb->DefaultInterface = IpIf; - InsertHeadList (&IpSb->Interfaces, &IpIf->Link); - IpSb->DefaultRouteTable = RouteTable; - Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb); - - // - // Reset the State to unstarted. - // - if (IpSb->State == IP4_SERVICE_CONFIGED || IpSb->State == IP4_SERVICE_STARTED) { - IpSb->State = IP4_SERVICE_UNSTARTED; - } - } - - return Status; -} - -/** - The work function is to set the gateway addresses manually for the EFI IPv4 - network stack that is running on the communication device that this EFI IPv4 - Configuration Protocol manages. It is not configurable when the policy is - Ip4Config2PolicyDhcp. The gateway addresses must be unicast IPv4 addresses. - - @param[in] Instance The pointer to the IP4 config2 instance data. - @param[in] DataSize The size of the buffer pointed to by Data in bytes. - @param[in] Data The data buffer to set. This points to an array of - EFI_IPv6_ADDRESS instances. - - @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type. - @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set - under the current policy. - @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid. - @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to complete the operation. - @retval EFI_ABORTED The manual gateway addresses to be set equal the - current configuration. - @retval EFI_SUCCESS The specified configuration data for the EFI IPv6 - network stack was set. - -**/ -EFI_STATUS -Ip4Config2SetGateway ( - IN IP4_CONFIG2_INSTANCE *Instance, - IN UINTN DataSize, - IN VOID *Data - ) -{ - IP4_SERVICE *IpSb; - IP4_CONFIG2_DATA_ITEM *DataItem; - IP4_ADDR Gateway; - - UINTN Index1; - UINTN Index2; - EFI_IPv4_ADDRESS *OldGateway; - EFI_IPv4_ADDRESS *NewGateway; - UINTN OldGatewayCount; - UINTN NewGatewayCount; - BOOLEAN OneRemoved; - BOOLEAN OneAdded; - VOID *Tmp; - - OldGateway = NULL; - NewGateway = NULL; - OneRemoved = FALSE; - OneAdded = FALSE; - Tmp = NULL; - - if ((DataSize != 0) && (DataSize % sizeof (EFI_IPv4_ADDRESS) != 0)) { - return EFI_BAD_BUFFER_SIZE; - } - - if (Instance->Policy != Ip4Config2PolicyStatic) { - return EFI_WRITE_PROTECTED; - } - - IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); - - DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway]; - OldGateway = DataItem->Data.Gateway; - OldGatewayCount = DataItem->DataSize / sizeof (EFI_IPv4_ADDRESS); - - for (Index1 = 0; Index1 < OldGatewayCount; Index1++) { - // - // Remove the old route entry. - // - CopyMem (&Gateway, OldGateway + Index1, sizeof (IP4_ADDR)); - Ip4DelRoute ( - IpSb->DefaultRouteTable, - IP4_ALLZERO_ADDRESS, - IP4_ALLZERO_ADDRESS, - NTOHL (Gateway) - ); - OneRemoved = TRUE; - } - - if (Data != NULL && DataSize != 0) { - NewGateway = (EFI_IPv4_ADDRESS *) Data; - NewGatewayCount = DataSize / sizeof (EFI_IPv4_ADDRESS); - for (Index1 = 0; Index1 < NewGatewayCount; Index1++) { - CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR)); - - if ((IpSb->DefaultInterface->SubnetMask != 0) && - !NetIp4IsUnicast (NTOHL (Gateway), IpSb->DefaultInterface->SubnetMask)) { - return EFI_INVALID_PARAMETER; - } - - for (Index2 = Index1 + 1; Index2 < NewGatewayCount; Index2++) { - if (EFI_IP4_EQUAL (NewGateway + Index1, NewGateway + Index2)) { - return EFI_INVALID_PARAMETER; - } - } - } - - if (NewGatewayCount != OldGatewayCount) { - Tmp = AllocatePool (DataSize); - if (Tmp == NULL) { - return EFI_OUT_OF_RESOURCES; - } - } else { - Tmp = NULL; - } - - for (Index1 = 0; Index1 < NewGatewayCount; Index1++) { - // - // Add the new route entry. - // - CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR)); - Ip4AddRoute ( - IpSb->DefaultRouteTable, - IP4_ALLZERO_ADDRESS, - IP4_ALLZERO_ADDRESS, - NTOHL (Gateway) - ); - - OneAdded = TRUE; - } - - if (!OneRemoved && !OneAdded) { - DataItem->Status = EFI_SUCCESS; - return EFI_ABORTED; - } else { - if (Tmp != NULL) { - if (DataItem->Data.Ptr != NULL) { - FreePool (DataItem->Data.Ptr); - } - DataItem->Data.Ptr = Tmp; - } - - CopyMem (DataItem->Data.Ptr, Data, DataSize); - DataItem->DataSize = DataSize; - DataItem->Status = EFI_SUCCESS; - } - } else { - // - // DataSize is 0 and Data is NULL, clean up the Gateway address. - // - if (DataItem->Data.Ptr != NULL) { - FreePool (DataItem->Data.Ptr); - } - DataItem->Data.Ptr = NULL; - DataItem->DataSize = 0; - DataItem->Status = EFI_NOT_FOUND; - } - - return EFI_SUCCESS; -} - -/** - The work function is to set the DNS server list for the EFI IPv4 network - stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL - manages. It is not configurable when the policy is Ip4Config2PolicyDhcp. - The DNS server addresses must be unicast IPv4 addresses. - - @param[in] Instance The pointer to the IP4 config2 instance data. - @param[in] DataSize The size of the buffer pointed to by Data in bytes. - @param[in] Data The data buffer to set, points to an array of - EFI_IPv4_ADDRESS instances. - - @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type. - @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set - under the current policy. - @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid. - @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation. - @retval EFI_ABORTED The DNS server addresses to be set equal the current - configuration. - @retval EFI_SUCCESS The specified configuration data for the EFI IPv4 - network stack was set. - -**/ -EFI_STATUS -Ip4Config2SetDnsServer ( - IN IP4_CONFIG2_INSTANCE *Instance, - IN UINTN DataSize, - IN VOID *Data - ) -{ - EFI_STATUS Status; - IP4_CONFIG2_DATA_ITEM *Item; - - Status = EFI_SUCCESS; - Item = NULL; - - if (Instance->Policy != Ip4Config2PolicyStatic) { - return EFI_WRITE_PROTECTED; - } - - Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer]; - - if (DATA_ATTRIB_SET (Item->Attribute, DATA_ATTRIB_VOLATILE)) { - REMOVE_DATA_ATTRIB (Item->Attribute, DATA_ATTRIB_VOLATILE); - } - - if (Data != NULL && DataSize != 0) { - Status = Ip4Config2SetDnsServerWorker (Instance, DataSize, Data); - } else { - // - // DataSize is 0 and Data is NULL, clean up the DnsServer address. - // - if (Item->Data.Ptr != NULL) { - FreePool (Item->Data.Ptr); - } - Item->Data.Ptr = NULL; - Item->DataSize = 0; - Item->Status = EFI_NOT_FOUND; - } - - return Status; -} - -/** - Generate the operational state of the interface this IP4 config2 instance manages - and output in EFI_IP4_CONFIG2_INTERFACE_INFO. - - @param[in] IpSb The pointer to the IP4 service binding instance. - @param[out] IfInfo The pointer to the IP4 config2 interface information structure. - -**/ -VOID -Ip4Config2InitIfInfo ( - IN IP4_SERVICE *IpSb, - OUT EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo - ) -{ - UnicodeSPrint ( - IfInfo->Name, - EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE, - L"eth%d", - IpSb->Ip4Config2Instance.IfIndex - ); - - IfInfo->IfType = IpSb->SnpMode.IfType; - IfInfo->HwAddressSize = IpSb->SnpMode.HwAddressSize; - CopyMem (&IfInfo->HwAddress, &IpSb->SnpMode.CurrentAddress, IfInfo->HwAddressSize); -} - - - -/** - Set the configuration for the EFI IPv4 network stack running on the communication - device this EFI_IP4_CONFIG2_PROTOCOL instance manages. - - This function is used to set the configuration data of type DataType for the EFI - IPv4 network stack that is running on the communication device that this EFI IPv4 - Configuration Protocol instance manages. - - DataSize is used to calculate the count of structure instances in the Data for - a DataType in which multiple structure instances are allowed. - - This function is always non-blocking. When setting some type of configuration data, - an asynchronous process is invoked to check the correctness of the data, such as - performing Duplicate Address Detection on the manually set local IPv4 addresses. - EFI_NOT_READY is returned immediately to indicate that such an asynchronous process - is invoked, and the process is not finished yet. The caller wanting to get the result - of the asynchronous process is required to call RegisterDataNotify() to register an - event on the specified configuration data. Once the event is signaled, the caller - can call GetData() to obtain the configuration data and know the result. - For other types of configuration data that do not require an asynchronous configuration - process, the result of the operation is immediately returned. - - @param[in] This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance. - @param[in] DataType The type of data to set. - @param[in] DataSize Size of the buffer pointed to by Data in bytes. - @param[in] Data The data buffer to set. The type of the data buffer is - associated with the DataType. - - @retval EFI_SUCCESS The specified configuration data for the EFI IPv6 - network stack was set successfully. - @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: - - This is NULL. - - One or more fields in Data and DataSize do not match the - requirement of the data type indicated by DataType. - @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified - configuration data cannot be set under the current policy. - @retval EFI_ACCESS_DENIED Another set operation on the specified configuration - data is already in process. - @retval EFI_NOT_READY An asynchronous process was invoked to set the specified - configuration data, and the process is not finished yet. - @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type - indicated by DataType. - @retval EFI_UNSUPPORTED This DataType is not supported. - @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. - @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred. - -**/ -EFI_STATUS -EFIAPI -EfiIp4Config2SetData ( - IN EFI_IP4_CONFIG2_PROTOCOL *This, - IN EFI_IP4_CONFIG2_DATA_TYPE DataType, - IN UINTN DataSize, - IN VOID *Data - ) -{ - EFI_TPL OldTpl; - EFI_STATUS Status; - IP4_CONFIG2_INSTANCE *Instance; - IP4_SERVICE *IpSb; - - if ((This == NULL) || (Data == NULL && DataSize != 0) || (Data != NULL && DataSize == 0)) { - return EFI_INVALID_PARAMETER; - } - - if (DataType >= Ip4Config2DataTypeMaximum) { - return EFI_UNSUPPORTED; - } - - Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This); - IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); - NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE); - - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - Status = Instance->DataItem[DataType].Status; - if (Status != EFI_NOT_READY) { - - if (Instance->DataItem[DataType].SetData == NULL) { - // - // This type of data is readonly. - // - Status = EFI_WRITE_PROTECTED; - } else { - - Status = Instance->DataItem[DataType].SetData (Instance, DataSize, Data); - if (!EFI_ERROR (Status)) { - // - // Fire up the events registered with this type of data. - // - NetMapIterate (&Instance->DataItem[DataType].EventMap, Ip4Config2SignalEvent, NULL); - Ip4Config2WriteConfigData (IpSb->MacString, Instance); - } else if (Status == EFI_ABORTED) { - // - // The SetData is aborted because the data to set is the same with - // the one maintained. - // - Status = EFI_SUCCESS; - NetMapIterate (&Instance->DataItem[DataType].EventMap, Ip4Config2SignalEvent, NULL); - } - } - } else { - // - // Another asynchornous process is on the way. - // - Status = EFI_ACCESS_DENIED; - } - - gBS->RestoreTPL (OldTpl); - - return Status; -} - -/** - Get the configuration data for the EFI IPv4 network stack running on the communication - device that this EFI_IP4_CONFIG2_PROTOCOL instance manages. - - This function returns the configuration data of type DataType for the EFI IPv4 network - stack running on the communication device that this EFI IPv4 Configuration Protocol instance - manages. - - The caller is responsible for allocating the buffer used to return the specified - configuration data. The required size will be returned to the caller if the size of - the buffer is too small. - - EFI_NOT_READY is returned if the specified configuration data is not ready due to an - asynchronous configuration process already in progress. The caller can call RegisterDataNotify() - to register an event on the specified configuration data. Once the asynchronous configuration - process is finished, the event will be signaled, and a subsequent GetData() call will return - the specified configuration data. - - @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance. - @param[in] DataType The type of data to get. - @param[in, out] DataSize On input, in bytes, the size of Data. On output, in bytes, the - size of buffer required to store the specified configuration data. - @param[in] Data The data buffer in which the configuration data is returned. The - type of the data buffer is associated with the DataType. - This is an optional parameter that may be NULL. - - @retval EFI_SUCCESS The specified configuration data was obtained successfully. - @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE: - - This is NULL. - - DataSize is NULL. - - Data is NULL if *DataSize is not zero. - @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data, - and the required size is returned in DataSize. - @retval EFI_NOT_READY The specified configuration data is not ready due to an - asynchronous configuration process already in progress. - @retval EFI_NOT_FOUND The specified configuration data is not found. - -**/ -EFI_STATUS -EFIAPI -EfiIp4Config2GetData ( - IN EFI_IP4_CONFIG2_PROTOCOL *This, - IN EFI_IP4_CONFIG2_DATA_TYPE DataType, - IN OUT UINTN *DataSize, - IN VOID *Data OPTIONAL - ) -{ - EFI_TPL OldTpl; - EFI_STATUS Status; - IP4_CONFIG2_INSTANCE *Instance; - IP4_CONFIG2_DATA_ITEM *DataItem; - - if ((This == NULL) || (DataSize == NULL) || ((*DataSize != 0) && (Data == NULL))) { - return EFI_INVALID_PARAMETER; - } - - if (DataType >= Ip4Config2DataTypeMaximum) { - return EFI_NOT_FOUND; - } - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This); - DataItem = &Instance->DataItem[DataType]; - - Status = Instance->DataItem[DataType].Status; - if (!EFI_ERROR (Status)) { - - if (DataItem->GetData != NULL) { - - Status = DataItem->GetData (Instance, DataSize, Data); - } else if (*DataSize < Instance->DataItem[DataType].DataSize) { - // - // Update the buffer length. - // - *DataSize = Instance->DataItem[DataType].DataSize; - Status = EFI_BUFFER_TOO_SMALL; - } else { - - *DataSize = Instance->DataItem[DataType].DataSize; - CopyMem (Data, Instance->DataItem[DataType].Data.Ptr, *DataSize); - } - } - - gBS->RestoreTPL (OldTpl); - - return Status; -} - -/** - Register an event that is signaled whenever a configuration process on the specified - configuration data is done. - - This function registers an event that is to be signaled whenever a configuration - process on the specified configuration data is performed. An event can be registered - for a different DataType simultaneously. The caller is responsible for determining - which type of configuration data causes the signaling of the event in such an event. - - @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance. - @param[in] DataType The type of data to unregister the event for. - @param[in] Event The event to register. - - @retval EFI_SUCCESS The notification event for the specified configuration data is - registered. - @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL. - @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not - supported. - @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. - @retval EFI_ACCESS_DENIED The Event is already registered for the DataType. - -**/ -EFI_STATUS -EFIAPI -EfiIp4Config2RegisterDataNotify ( - IN EFI_IP4_CONFIG2_PROTOCOL *This, - IN EFI_IP4_CONFIG2_DATA_TYPE DataType, - IN EFI_EVENT Event - ) -{ - EFI_TPL OldTpl; - EFI_STATUS Status; - IP4_CONFIG2_INSTANCE *Instance; - NET_MAP *EventMap; - NET_MAP_ITEM *Item; - - if ((This == NULL) || (Event == NULL)) { - return EFI_INVALID_PARAMETER; - } - - if (DataType >= Ip4Config2DataTypeMaximum) { - return EFI_UNSUPPORTED; - } - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This); - EventMap = &Instance->DataItem[DataType].EventMap; - - // - // Check whether this event is already registered for this DataType. - // - Item = NetMapFindKey (EventMap, Event); - if (Item == NULL) { - - Status = NetMapInsertTail (EventMap, Event, NULL); - - if (EFI_ERROR (Status)) { - - Status = EFI_OUT_OF_RESOURCES; - } - - } else { - - Status = EFI_ACCESS_DENIED; - } - - gBS->RestoreTPL (OldTpl); - - return Status; -} - -/** - Remove a previously registered event for the specified configuration data. - - @param This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance. - @param DataType The type of data to remove from the previously - registered event. - @param Event The event to be unregistered. - - @retval EFI_SUCCESS The event registered for the specified - configuration data was removed. - @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL. - @retval EFI_NOT_FOUND The Event has not been registered for the - specified DataType. - -**/ -EFI_STATUS -EFIAPI -EfiIp4Config2UnregisterDataNotify ( - IN EFI_IP4_CONFIG2_PROTOCOL *This, - IN EFI_IP4_CONFIG2_DATA_TYPE DataType, - IN EFI_EVENT Event - ) -{ - EFI_TPL OldTpl; - EFI_STATUS Status; - IP4_CONFIG2_INSTANCE *Instance; - NET_MAP_ITEM *Item; - - if ((This == NULL) || (Event == NULL)) { - return EFI_INVALID_PARAMETER; - } - - if (DataType >= Ip4Config2DataTypeMaximum) { - return EFI_NOT_FOUND; - } - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This); - - Item = NetMapFindKey (&Instance->DataItem[DataType].EventMap, Event); - if (Item != NULL) { - - NetMapRemoveItem (&Instance->DataItem[DataType].EventMap, Item, NULL); - Status = EFI_SUCCESS; - } else { - - Status = EFI_NOT_FOUND; - } - - gBS->RestoreTPL (OldTpl); - - return Status; -} - -/** - Initialize an IP4_CONFIG2_INSTANCE. - - @param[out] Instance The buffer of IP4_CONFIG2_INSTANCE to be initialized. - - @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation. - @retval EFI_SUCCESS The IP4_CONFIG2_INSTANCE initialized successfully. - -**/ -EFI_STATUS -Ip4Config2InitInstance ( - OUT IP4_CONFIG2_INSTANCE *Instance - ) -{ - IP4_SERVICE *IpSb; - IP4_CONFIG2_INSTANCE *TmpInstance; - LIST_ENTRY *Entry; - EFI_STATUS Status; - UINTN Index; - UINT16 IfIndex; - IP4_CONFIG2_DATA_ITEM *DataItem; - - - IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); - - Instance->Signature = IP4_CONFIG2_INSTANCE_SIGNATURE; - - - // - // Determine the index of this interface. - // - IfIndex = 0; - NET_LIST_FOR_EACH (Entry, &mIp4Config2InstanceList) { - TmpInstance = NET_LIST_USER_STRUCT_S (Entry, IP4_CONFIG2_INSTANCE, Link, IP4_CONFIG2_INSTANCE_SIGNATURE); - - if (TmpInstance->IfIndex > IfIndex) { - // - // There is a sequence hole because some interface is down. - // - break; - } - - IfIndex++; - } - - Instance->IfIndex = IfIndex; - NetListInsertBefore (Entry, &Instance->Link); - - for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) { - // - // Initialize the event map for each data item. - // - NetMapInit (&Instance->DataItem[Index].EventMap); - } - - - // - // Initialize each data type: associate storage and set data size for the - // fixed size data types, hook the SetData function, set the data attribute. - // - DataItem = &Instance->DataItem[Ip4Config2DataTypeInterfaceInfo]; - DataItem->GetData = Ip4Config2GetIfInfo; - DataItem->Data.Ptr = &Instance->InterfaceInfo; - DataItem->DataSize = sizeof (Instance->InterfaceInfo); - SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED | DATA_ATTRIB_VOLATILE); - Ip4Config2InitIfInfo (IpSb, &Instance->InterfaceInfo); - - DataItem = &Instance->DataItem[Ip4Config2DataTypePolicy]; - DataItem->SetData = Ip4Config2SetPolicy; - DataItem->Data.Ptr = &Instance->Policy; - DataItem->DataSize = sizeof (Instance->Policy); - Instance->Policy = Ip4Config2PolicyStatic; - SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED); - - DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress]; - DataItem->SetData = Ip4Config2SetManualAddress; - DataItem->Status = EFI_NOT_FOUND; - - DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway]; - DataItem->SetData = Ip4Config2SetGateway; - DataItem->Status = EFI_NOT_FOUND; - - DataItem = &Instance->DataItem[Ip4Config2DataTypeDnsServer]; - DataItem->SetData = Ip4Config2SetDnsServer; - DataItem->Status = EFI_NOT_FOUND; - - Instance->Configured = TRUE; - - // - // Try to read the config data from NV variable. - // If not found, write initialized config data into NV variable - // as a default config data. - // - Status = Ip4Config2ReadConfigData (IpSb->MacString, Instance); - if (Status == EFI_NOT_FOUND) { - Status = Ip4Config2WriteConfigData (IpSb->MacString, Instance); - } - - if (EFI_ERROR (Status)) { - return Status; - } - - Instance->Ip4Config2.SetData = EfiIp4Config2SetData; - Instance->Ip4Config2.GetData = EfiIp4Config2GetData; - Instance->Ip4Config2.RegisterDataNotify = EfiIp4Config2RegisterDataNotify; - Instance->Ip4Config2.UnregisterDataNotify = EfiIp4Config2UnregisterDataNotify; - - // - // Publish the IP4 configuration form - // - return Ip4Config2FormInit (Instance); -} - - -/** - Release an IP4_CONFIG2_INSTANCE. - - @param[in, out] Instance The buffer of IP4_CONFIG2_INSTANCE to be freed. - -**/ -VOID -Ip4Config2CleanInstance ( - IN OUT IP4_CONFIG2_INSTANCE *Instance - ) -{ - UINTN Index; - IP4_CONFIG2_DATA_ITEM *DataItem; - - if (Instance->DeclineAddress != NULL) { - FreePool (Instance->DeclineAddress); - } - - if (!Instance->Configured) { - return ; - } - - if (Instance->Dhcp4Handle != NULL) { - - Ip4Config2DestroyDhcp4 (Instance); - } - - // - // Close the event. - // - if (Instance->Dhcp4Event != NULL) { - gBS->CloseEvent (Instance->Dhcp4Event); - Instance->Dhcp4Event = NULL; - } - - for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) { - - DataItem = &Instance->DataItem[Index]; - - if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED)) { - if (DataItem->Data.Ptr != NULL) { - FreePool (DataItem->Data.Ptr); - } - DataItem->Data.Ptr = NULL; - DataItem->DataSize = 0; - } - - NetMapClean (&Instance->DataItem[Index].EventMap); - } - - Ip4Config2FormUnload (Instance); - - RemoveEntryList (&Instance->Link); -} - -/** - The event handle for IP4 auto reconfiguration. The original default - interface and route table will be removed as the default. - - @param[in] Context The IP4 service binding instance. - -**/ -VOID -EFIAPI -Ip4AutoReconfigCallBackDpc ( - IN VOID *Context - ) -{ - IP4_SERVICE *IpSb; - - IpSb = (IP4_SERVICE *) Context; - NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE); - - if (IpSb->State > IP4_SERVICE_UNSTARTED) { - IpSb->State = IP4_SERVICE_UNSTARTED; - } - - IpSb->Reconfig = TRUE; - - Ip4StartAutoConfig (&IpSb->Ip4Config2Instance); - - return ; -} - - -/** - Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK. - - @param Event The event that is signalled. - @param Context The IP4 service binding instance. - -**/ -VOID -EFIAPI -Ip4AutoReconfigCallBack ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - // - // Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK - // - QueueDpc (TPL_CALLBACK, Ip4AutoReconfigCallBackDpc, Context); -} -