+ Notify function for the ICMP receive token, used to process\r
+ the received ICMP packets.\r
+\r
+ @param Context The PXEBC private data.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+IcmpErrorListenHandlerDpc (\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_IP4_RECEIVE_DATA *RxData;\r
+ EFI_IP4_PROTOCOL *Ip4;\r
+ PXEBC_PRIVATE_DATA *Private;\r
+ EFI_PXE_BASE_CODE_MODE *Mode;\r
+ UINTN Index;\r
+ UINT32 CopiedLen;\r
+ UINT8 *CopiedPointer;\r
+\r
+ Private = (PXEBC_PRIVATE_DATA *) Context;\r
+ Mode = &Private->Mode;\r
+ Status = Private->IcmpErrorRcvToken.Status;\r
+ RxData = Private->IcmpErrorRcvToken.Packet.RxData;\r
+ Ip4 = Private->Ip4;\r
+\r
+ if (Status == EFI_ABORTED) {\r
+ //\r
+ // The reception is actively aborted by the consumer, directly return.\r
+ //\r
+ return;\r
+ }\r
+\r
+ if (EFI_ERROR (Status) || (RxData == NULL)) {\r
+ //\r
+ // Only process the normal packets and the icmp error packets, if RxData is NULL\r
+ // with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although\r
+ // this should be a bug of the low layer (IP).\r
+ //\r
+ goto Resume;\r
+ }\r
+\r
+ if (EFI_IP4 (RxData->Header->SourceAddress) != 0 &&\r
+ !NetIp4IsUnicast (EFI_NTOHL (RxData->Header->SourceAddress), 0)) {\r
+ //\r
+ // The source address is not zero and it's not a unicast IP address, discard it.\r
+ //\r
+ goto CleanUp;\r
+ }\r
+\r
+ if (!EFI_IP4_EQUAL (&RxData->Header->DestinationAddress, &Mode->StationIp.v4)) {\r
+ //\r
+ // The dest address is not equal to Station Ip address, discard it.\r
+ //\r
+ goto CleanUp;\r
+ }\r
+\r
+ //\r
+ // Constructor ICMP error packet\r
+ //\r
+ CopiedLen = 0;\r
+ CopiedPointer = (UINT8 *) &Mode->IcmpError;\r
+\r
+ for (Index = 0; Index < RxData->FragmentCount; Index ++) {\r
+ CopiedLen += RxData->FragmentTable[Index].FragmentLength;\r
+ if (CopiedLen <= sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR)) {\r
+ CopyMem (\r
+ CopiedPointer,\r
+ RxData->FragmentTable[Index].FragmentBuffer,\r
+ RxData->FragmentTable[Index].FragmentLength\r
+ );\r
+ } else {\r
+ CopyMem (\r
+ CopiedPointer,\r
+ RxData->FragmentTable[Index].FragmentBuffer,\r
+ CopiedLen - sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR)\r
+ );\r
+ }\r
+ CopiedPointer += CopiedLen;\r
+ }\r
+\r
+ goto Resume;\r
+\r
+CleanUp:\r
+ gBS->SignalEvent (RxData->RecycleSignal);\r
+\r
+Resume:\r
+ Ip4->Receive (Ip4, &(Private->IcmpErrorRcvToken));\r
+}\r
+\r
+/**\r
+ Request IcmpErrorListenHandlerDpc as a DPC at TPL_CALLBACK\r
+\r
+ @param Event The event signaled.\r
+ @param Context The context passed in by the event notifier.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+IcmpErrorListenHandler (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ //\r
+ // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK\r
+ //\r
+ QueueDpc (TPL_CALLBACK, IcmpErrorListenHandlerDpc, Context);\r
+}\r
+\r
+/**\r
+ Enables the use of the PXE Base Code Protocol functions.\r
+\r
+ This function enables the use of the PXE Base Code Protocol functions. If the\r
+ Started field of the EFI_PXE_BASE_CODE_MODE structure is already TRUE, then\r
+ EFI_ALREADY_STARTED will be returned. If UseIpv6 is TRUE, then IPv6 formatted\r
+ addresses will be used in this session. If UseIpv6 is FALSE, then IPv4 formatted\r
+ addresses will be used in this session. If UseIpv6 is TRUE, and the Ipv6Supported\r
+ field of the EFI_PXE_BASE_CODE_MODE structure is FALSE, then EFI_UNSUPPORTED will\r
+ be returned. If there is not enough memory or other resources to start the PXE\r
+ Base Code Protocol, then EFI_OUT_OF_RESOURCES will be returned. Otherwise, the\r
+ PXE Base Code Protocol will be started, and all of the fields of the EFI_PXE_BASE_CODE_MODE\r
+ structure will be initialized as follows:\r
+ StartedSet to TRUE.\r
+ Ipv6SupportedUnchanged.\r
+ Ipv6AvailableUnchanged.\r
+ UsingIpv6Set to UseIpv6.\r
+ BisSupportedUnchanged.\r
+ BisDetectedUnchanged.\r
+ AutoArpSet to TRUE.\r
+ SendGUIDSet to FALSE.\r
+ TTLSet to DEFAULT_TTL.\r
+ ToSSet to DEFAULT_ToS.\r
+ DhcpCompletedSet to FALSE.\r
+ ProxyOfferReceivedSet to FALSE.\r
+ StationIpSet to an address of all zeros.\r
+ SubnetMaskSet to a subnet mask of all zeros.\r
+ DhcpDiscoverZero-filled.\r
+ DhcpAckZero-filled.\r
+ ProxyOfferZero-filled.\r
+ PxeDiscoverValidSet to FALSE.\r
+ PxeDiscoverZero-filled.\r
+ PxeReplyValidSet to FALSE.\r
+ PxeReplyZero-filled.\r
+ PxeBisReplyValidSet to FALSE.\r
+ PxeBisReplyZero-filled.\r
+ IpFilterSet the Filters field to 0 and the IpCnt field to 0.\r
+ ArpCacheEntriesSet to 0.\r
+ ArpCacheZero-filled.\r
+ RouteTableEntriesSet to 0.\r
+ RouteTableZero-filled.\r
+ IcmpErrorReceivedSet to FALSE.\r
+ IcmpErrorZero-filled.\r
+ TftpErroReceivedSet to FALSE.\r
+ TftpErrorZero-filled.\r
+ MakeCallbacksSet to TRUE if the PXE Base Code Callback Protocol is available.\r
+ Set to FALSE if the PXE Base Code Callback Protocol is not available.\r
+\r
+ @param This Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance.\r
+ @param UseIpv6 Specifies the type of IP addresses that are to be used during the session\r
+ that is being started. Set to TRUE for IPv6 addresses, and FALSE for\r
+ IPv4 addresses.\r
+\r
+ @retval EFI_SUCCESS The PXE Base Code Protocol was started.\r
+ @retval EFI_DEVICE_ERROR The network device encountered an error during this oper\r
+ @retval EFI_UNSUPPORTED UseIpv6 is TRUE, but the Ipv6Supported field of the\r
+ EFI_PXE_BASE_CODE_MODE structure is FALSE.\r
+ @retval EFI_ALREADY_STARTED The PXE Base Code Protocol is already in the started state.\r
+ @retval EFI_INVALID_PARAMETER The This parameter is NULL or does not point to a valid\r
+ EFI_PXE_BASE_CODE_PROTOCOL structure.\r
+ @retval EFI_OUT_OF_RESOURCES Could not allocate enough memory or other resources to start the\r
+ PXE Base Code Protocol.\r