-/**\r
- The event handle for IP4 auto configuration. If IP is asked\r
- to reconfigure the default address. The original default\r
- interface and route table are removed as the default. If there\r
- is active IP children using the default address, the interface\r
- will remain valid until all the children have freed their\r
- references. If IP is signalled when auto configuration is done,\r
- it will configure the default interface and default route table\r
- with the configuration information retrieved by IP4_CONFIGURE.\r
-\r
- @param[in] Context The IP4 service binding instance.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Ip4AutoConfigCallBackDpc (\r
- IN VOID *Context\r
- )\r
-{\r
- EFI_IP4_CONFIG_PROTOCOL *Ip4Config;\r
- EFI_IP4_IPCONFIG_DATA *Data;\r
- EFI_IP4_ROUTE_TABLE *RouteEntry;\r
- IP4_SERVICE *IpSb;\r
- IP4_ROUTE_TABLE *RouteTable;\r
- IP4_INTERFACE *IpIf;\r
- EFI_STATUS Status;\r
- UINTN Len;\r
- UINT32 Index;\r
- IP4_ADDR StationAddress;\r
- IP4_ADDR SubnetMask;\r
- IP4_ADDR SubnetAddress;\r
- IP4_ADDR GatewayAddress;\r
-\r
- IpSb = (IP4_SERVICE *) Context;\r
- NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);\r
-\r
- Ip4Config = IpSb->Ip4Config;\r
-\r
- //\r
- // IP is asked to do the reconfiguration. If the default interface\r
- // has been configured, release the default interface and route\r
- // table, then create a new one. If there are some IP children\r
- // using it, the interface won't be physically freed until all the\r
- // children have released their reference to it. Also remember to\r
- // restart the receive on the default address. IP4 driver only receive\r
- // frames on the default address, and when the default interface is\r
- // freed, Ip4AcceptFrame won't be informed.\r
- //\r
- if (IpSb->ActiveEvent == IpSb->ReconfigEvent) {\r
-\r
- if (IpSb->DefaultInterface->Configured) {\r
- IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
-\r
- if (IpIf == NULL) {\r
- return;\r
- }\r
-\r
- RouteTable = Ip4CreateRouteTable ();\r
-\r
- if (RouteTable == NULL) {\r
- Ip4FreeInterface (IpIf, NULL);\r
- return;\r
- }\r
-\r
- Ip4CancelReceive (IpSb->DefaultInterface);\r
- Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
- Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
-\r
- IpSb->DefaultInterface = IpIf;\r
- InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
-\r
- IpSb->DefaultRouteTable = RouteTable;\r
- Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
- }\r
-\r
- Ip4Config->Stop (Ip4Config);\r
- Ip4Config->Start (Ip4Config, IpSb->DoneEvent, IpSb->ReconfigEvent);\r
- return ;\r
- }\r
-\r
- //\r
- // Get the configure data in two steps: get the length then the data.\r
- //\r
- Len = 0;\r
-\r
- if (Ip4Config->GetData (Ip4Config, &Len, NULL) != EFI_BUFFER_TOO_SMALL) {\r
- return ;\r
- }\r
-\r
- Data = AllocatePool (Len);\r
-\r
- if (Data == NULL) {\r
- return ;\r
- }\r
-\r
- Status = Ip4Config->GetData (Ip4Config, &Len, Data);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto ON_EXIT;\r
- }\r
-\r
- IpIf = IpSb->DefaultInterface;\r
-\r
- //\r
- // If the default address has been configured don't change it.\r
- // This is unlikely to happen if EFI_IP4_CONFIG protocol has\r
- // informed us to reconfigure each time it wants to change the\r
- // configuration parameters.\r
- //\r
- if (IpIf->Configured) {\r
- goto ON_EXIT;\r
- }\r
-\r
- //\r
- // Set the default interface's address, then add a directed\r
- // route for it, that is, the route whose nexthop is zero.\r
- //\r
- StationAddress = EFI_NTOHL (Data->StationAddress);\r
- SubnetMask = EFI_NTOHL (Data->SubnetMask);\r
- Status = Ip4SetAddress (IpIf, StationAddress, SubnetMask);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto ON_EXIT;\r
- }\r
-\r
- Ip4AddRoute (\r
- IpSb->DefaultRouteTable,\r
- StationAddress,\r
- SubnetMask,\r
- IP4_ALLZERO_ADDRESS\r
- );\r
-\r
- //\r
- // Add routes returned by EFI_IP4_CONFIG protocol.\r
- //\r
- for (Index = 0; Index < Data->RouteTableSize; Index++) {\r
- RouteEntry = &Data->RouteTable[Index];\r
-\r
- SubnetAddress = EFI_NTOHL (RouteEntry->SubnetAddress);\r
- SubnetMask = EFI_NTOHL (RouteEntry->SubnetMask);\r
- GatewayAddress = EFI_NTOHL (RouteEntry->GatewayAddress);\r
- Ip4AddRoute (IpSb->DefaultRouteTable, SubnetAddress, SubnetMask, GatewayAddress);\r
- }\r
-\r
- IpSb->State = IP4_SERVICE_CONFIGED;\r
-\r
- Ip4SetVariableData (IpSb);\r
-\r
-ON_EXIT:\r
- FreePool (Data);\r
-}\r
-\r
-/**\r
- Request Ip4AutoConfigCallBackDpc 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
-Ip4AutoConfigCallBack (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- IP4_SERVICE *IpSb;\r
-\r
- IpSb = (IP4_SERVICE *) Context;\r
- IpSb->ActiveEvent = Event;\r
-\r
- //\r
- // Request Ip4AutoConfigCallBackDpc as a DPC at TPL_CALLBACK\r
- //\r
- QueueDpc (TPL_CALLBACK, Ip4AutoConfigCallBackDpc, Context);\r
-}\r
-\r
-\r
-/**\r
- Start the auto configuration for this IP service instance.\r
- It will locates the EFI_IP4_CONFIG_PROTOCOL, then start the\r
- auto configuration.\r
-\r
- @param[in] IpSb The IP4 service instance to configure\r
-\r
- @retval EFI_SUCCESS The auto configuration is successfull started\r
- @retval Others Failed to start auto configuration.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4StartAutoConfig (\r
- IN IP4_SERVICE *IpSb\r
- )\r
-{\r
- EFI_IP4_CONFIG_PROTOCOL *Ip4Config;\r
- EFI_STATUS Status;\r
-\r
- if (IpSb->State > IP4_SERVICE_UNSTARTED) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Create the DoneEvent and ReconfigEvent to call EFI_IP4_CONFIG\r
- //\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_CALLBACK,\r
- Ip4AutoConfigCallBack,\r
- IpSb,\r
- &IpSb->DoneEvent\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- Ip4AutoConfigCallBack,\r
- IpSb,\r
- &IpSb->ReconfigEvent\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto CLOSE_DONE_EVENT;\r
- }\r
-\r
- //\r
- // Open the EFI_IP4_CONFIG protocol then start auto configure\r
- //\r
- Status = gBS->OpenProtocol (\r
- IpSb->Controller,\r
- &gEfiIp4ConfigProtocolGuid,\r
- (VOID **) &Ip4Config,\r
- IpSb->Image,\r
- IpSb->Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_UNSUPPORTED;\r
- goto CLOSE_RECONFIG_EVENT;\r
- }\r
-\r
- Status = Ip4Config->Start (Ip4Config, IpSb->DoneEvent, IpSb->ReconfigEvent);\r
-\r
- if (EFI_ERROR (Status)) {\r
- gBS->CloseProtocol (\r
- IpSb->Controller,\r
- &gEfiIp4ConfigProtocolGuid,\r
- IpSb->Image,\r
- IpSb->Controller\r
- );\r
-\r
- goto CLOSE_RECONFIG_EVENT;\r
- }\r
-\r
- IpSb->Ip4Config = Ip4Config;\r
- IpSb->State = IP4_SERVICE_STARTED;\r
- return Status;\r
-\r
-CLOSE_RECONFIG_EVENT:\r
- gBS->CloseEvent (IpSb->ReconfigEvent);\r
- IpSb->ReconfigEvent = NULL;\r
-\r
-CLOSE_DONE_EVENT:\r
- gBS->CloseEvent (IpSb->DoneEvent);\r
- IpSb->DoneEvent = NULL;\r
-\r
- return Status;\r
-}\r
-\r
-\r