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