]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.c
1. Add DPC protocol and DpcLib library in MdeModulePkg.
[mirror_edk2.git] / MdeModulePkg / Library / DxeIpIoLib / DxeIpIoLib.c
CommitLineData
cbf316f2 1/** @file\r
2\r
3Copyright (c) 2005 - 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 IpIo.c\r
15\r
16Abstract:\r
17\r
18 The implementation of the IpIo layer.\r
19\r
20\r
21**/\r
22\r
23#include <PiDxe.h>\r
24\r
25#include <Protocol/Udp4.h>\r
26\r
27#include <Library/IpIoLib.h>\r
28#include <Library/BaseLib.h>\r
29#include <Library/DebugLib.h>\r
30#include <Library/UefiBootServicesTableLib.h>\r
31#include <Library/MemoryAllocationLib.h>\r
b61439a7 32#include <Library/BaseMemoryLib.h>\r
cbf316f2 33\r
34\r
35#define NET_PROTO_HDR(Buf, Type) ((Type *) ((Buf)->BlockOp[0].Head))\r
36#define ICMP_ERRLEN(IpHdr) \\r
37 (sizeof(IP4_ICMP_HEAD) + EFI_IP4_HEADER_LEN(IpHdr) + 8)\r
38\r
39NET_LIST_ENTRY mActiveIpIoList = {\r
40 &mActiveIpIoList,\r
41 &mActiveIpIoList\r
42};\r
43\r
44EFI_IP4_CONFIG_DATA mIpIoDefaultIpConfigData = {\r
45 EFI_IP_PROTO_UDP,\r
46 FALSE,\r
47 TRUE,\r
48 FALSE,\r
49 FALSE,\r
50 FALSE,\r
84b5c78e 51 {{0, 0, 0, 0}},\r
52 {{0, 0, 0, 0}},\r
cbf316f2 53 0,\r
54 255,\r
55 FALSE,\r
56 FALSE,\r
57 0,\r
58 0\r
59};\r
60\r
01750eb0 61STATIC ICMP_ERROR_INFO mIcmpErrMap[10] = {\r
62 {FALSE, TRUE},\r
63 {FALSE, TRUE},\r
64 {TRUE, TRUE},\r
65 {TRUE, TRUE},\r
66 {TRUE, TRUE},\r
67 {FALSE, TRUE},\r
68 {FALSE, TRUE},\r
69 {FALSE, TRUE},\r
70 {FALSE, FALSE},\r
71 {FALSE, TRUE}\r
72};\r
73\r
36ee91ca 74STATIC\r
75VOID\r
76EFIAPI\r
77IpIoTransmitHandlerDpc (\r
78 IN VOID *Context\r
79 );\r
80\r
cbf316f2 81STATIC\r
82VOID\r
83EFIAPI\r
84IpIoTransmitHandler (\r
85 IN EFI_EVENT Event,\r
86 IN VOID *Context\r
87 );\r
88\r
89\r
90/**\r
91 This function create an ip child ,open the IP protocol, return the opened\r
92 Ip protocol to Interface.\r
93\r
94 @param ControllerHandle The controller handle.\r
95 @param ImageHandle The image handle.\r
96 @param ChildHandle Pointer to the buffer to save the ip child handle.\r
97 @param Interface Pointer used to get the ip protocol interface.\r
98\r
99 @retval EFI_SUCCESS The ip child is created and the ip protocol\r
100 interface is retrieved.\r
101 @retval other The required operation failed.\r
102\r
103**/\r
104STATIC\r
105EFI_STATUS\r
106IpIoCreateIpChildOpenProtocol (\r
107 IN EFI_HANDLE ControllerHandle,\r
108 IN EFI_HANDLE ImageHandle,\r
109 IN EFI_HANDLE *ChildHandle,\r
110 OUT VOID **Interface\r
111 )\r
112{\r
113 EFI_STATUS Status;\r
114\r
115 //\r
116 // Create an ip child.\r
117 //\r
118 Status = NetLibCreateServiceChild (\r
119 ControllerHandle,\r
120 ImageHandle,\r
121 &gEfiIp4ServiceBindingProtocolGuid,\r
122 ChildHandle\r
123 );\r
124 if (EFI_ERROR (Status)) {\r
125 return Status;\r
126 }\r
127\r
128 //\r
129 // Open the ip protocol installed on the *ChildHandle.\r
130 //\r
131 Status = gBS->OpenProtocol (\r
132 *ChildHandle,\r
133 &gEfiIp4ProtocolGuid,\r
134 Interface,\r
135 ImageHandle,\r
136 ControllerHandle,\r
137 EFI_OPEN_PROTOCOL_BY_DRIVER\r
138 );\r
139 if (EFI_ERROR (Status)) {\r
140 //\r
141 // On failure, destroy the ip child.\r
142 //\r
143 NetLibDestroyServiceChild (\r
144 ControllerHandle,\r
145 ImageHandle,\r
146 &gEfiIp4ServiceBindingProtocolGuid,\r
147 *ChildHandle\r
148 );\r
149 }\r
150\r
151 return Status;\r
152}\r
153\r
154\r
155/**\r
156 This function close the previously openned ip protocol and destroy the ip child.\r
157\r
158 @param ControllerHandle The controller handle.\r
159 @param ImageHandle the image handle.\r
160 @param ChildHandle The child handle of the ip child.\r
161\r
162 @retval EFI_SUCCESS The ip protocol is closed and the relevant ip child\r
163 is destroyed.\r
164 @retval other The required operation failed.\r
165\r
166**/\r
167STATIC\r
168EFI_STATUS\r
169IpIoCloseProtocolDestroyIpChild (\r
170 IN EFI_HANDLE ControllerHandle,\r
171 IN EFI_HANDLE ImageHandle,\r
172 IN EFI_HANDLE ChildHandle\r
173 )\r
174{\r
175 EFI_STATUS Status;\r
176\r
177 //\r
178 // Close the previously openned ip protocol.\r
179 //\r
180 gBS->CloseProtocol (\r
181 ChildHandle,\r
182 &gEfiIp4ProtocolGuid,\r
183 ImageHandle,\r
184 ControllerHandle\r
185 );\r
186\r
187 //\r
188 // Destroy the ip child.\r
189 //\r
190 Status = NetLibDestroyServiceChild (\r
191 ControllerHandle,\r
192 ImageHandle,\r
193 &gEfiIp4ServiceBindingProtocolGuid,\r
194 ChildHandle\r
195 );\r
196\r
197 return Status;\r
198}\r
199\r
200\r
201/**\r
202 Handle ICMP packets.\r
203\r
204 @param IpIo Pointer to the IP_IO instance.\r
205 @param Pkt Pointer to the ICMP packet.\r
206 @param Session Pointer to the net session of this ICMP packet.\r
207\r
208 @retval EFI_SUCCESS The ICMP packet is handled successfully.\r
209 @retval EFI_ABORTED This type of ICMP packet is not supported.\r
210\r
211**/\r
212STATIC\r
213EFI_STATUS\r
214IpIoIcmpHandler (\r
215 IN IP_IO *IpIo,\r
216 IN NET_BUF *Pkt,\r
217 IN EFI_NET_SESSION_DATA *Session\r
218 )\r
219{\r
220 IP4_ICMP_ERROR_HEAD *IcmpHdr;\r
221 EFI_IP4_HEADER *IpHdr;\r
222 ICMP_ERROR IcmpErr;\r
223 UINT8 *PayLoadHdr;\r
224 UINT8 Type;\r
225 UINT8 Code;\r
226 UINT32 TrimBytes;\r
227\r
228 IcmpHdr = NET_PROTO_HDR (Pkt, IP4_ICMP_ERROR_HEAD);\r
229 IpHdr = (EFI_IP4_HEADER *) (&IcmpHdr->IpHead);\r
230\r
231 //\r
232 // Check the ICMP packet length.\r
233 //\r
234 if (Pkt->TotalSize < ICMP_ERRLEN (IpHdr)) {\r
235\r
236 return EFI_ABORTED;\r
237 }\r
238\r
239 Type = IcmpHdr->Head.Type;\r
240 Code = IcmpHdr->Head.Code;\r
241\r
242 //\r
243 // Analyze the ICMP Error in this ICMP pkt\r
244 //\r
245 switch (Type) {\r
246 case ICMP_TYPE_UNREACH:\r
247 switch (Code) {\r
248 case ICMP_CODE_UNREACH_NET:\r
249 case ICMP_CODE_UNREACH_HOST:\r
250 case ICMP_CODE_UNREACH_PROTOCOL:\r
251 case ICMP_CODE_UNREACH_PORT:\r
252 case ICMP_CODE_UNREACH_SRCFAIL:\r
4eb65aff 253 IcmpErr = (ICMP_ERROR) (ICMP_ERR_UNREACH_NET + Code);\r
cbf316f2 254\r
255 break;\r
256\r
257 case ICMP_CODE_UNREACH_NEEDFRAG:\r
258 IcmpErr = ICMP_ERR_MSGSIZE;\r
259\r
260 break;\r
261\r
262 case ICMP_CODE_UNREACH_NET_UNKNOWN:\r
263 case ICMP_CODE_UNREACH_NET_PROHIB:\r
264 case ICMP_CODE_UNREACH_TOSNET:\r
265 IcmpErr = ICMP_ERR_UNREACH_NET;\r
266\r
267 break;\r
268\r
269 case ICMP_CODE_UNREACH_HOST_UNKNOWN:\r
270 case ICMP_CODE_UNREACH_ISOLATED:\r
271 case ICMP_CODE_UNREACH_HOST_PROHIB:\r
272 case ICMP_CODE_UNREACH_TOSHOST:\r
273 IcmpErr = ICMP_ERR_UNREACH_HOST;\r
274\r
275 break;\r
276\r
277 default:\r
278 return EFI_ABORTED;\r
279\r
280 break;\r
281 }\r
282\r
283 break;\r
284\r
285 case ICMP_TYPE_TIMXCEED:\r
286 if (Code > 1) {\r
287 return EFI_ABORTED;\r
288 }\r
289\r
4eb65aff 290 IcmpErr = (ICMP_ERROR) (Code + ICMP_ERR_TIMXCEED_INTRANS);\r
cbf316f2 291\r
292 break;\r
293\r
294 case ICMP_TYPE_PARAMPROB:\r
295 if (Code > 1) {\r
296 return EFI_ABORTED;\r
297 }\r
298\r
299 IcmpErr = ICMP_ERR_PARAMPROB;\r
300\r
301 break;\r
302\r
303 case ICMP_TYPE_SOURCEQUENCH:\r
304 if (Code != 0) {\r
305 return EFI_ABORTED;\r
306 }\r
307\r
308 IcmpErr = ICMP_ERR_QUENCH;\r
309\r
310 break;\r
311\r
312 default:\r
313 return EFI_ABORTED;\r
314\r
315 break;\r
316 }\r
317\r
318 //\r
319 // Notify user the ICMP pkt only containing payload except\r
320 // IP and ICMP header\r
321 //\r
322 PayLoadHdr = (UINT8 *) ((UINT8 *) IpHdr + EFI_IP4_HEADER_LEN (IpHdr));\r
323 TrimBytes = (UINT32) (PayLoadHdr - (UINT8 *) IcmpHdr);\r
324\r
325 NetbufTrim (Pkt, TrimBytes, TRUE);\r
326\r
327 IpIo->PktRcvdNotify (EFI_ICMP_ERROR, IcmpErr, Session, Pkt, IpIo->RcvdContext);\r
328\r
329 return EFI_SUCCESS;\r
330}\r
331\r
332\r
333/**\r
334 Ext free function for net buffer. This function is\r
335 called when the net buffer is freed. It is used to\r
336 signal the recycle event to notify IP to recycle the\r
337 data buffer.\r
338\r
339 @param Event The event to be signaled.\r
340\r
341 @return None.\r
342\r
343**/\r
344STATIC\r
345VOID\r
346IpIoExtFree (\r
347 IN VOID *Event\r
348 )\r
349{\r
350 gBS->SignalEvent ((EFI_EVENT) Event);\r
351}\r
352\r
353\r
354/**\r
355 Create a send entry to wrap a packet before sending\r
356 out it through IP.\r
357\r
358 @param IpIo Pointer to the IP_IO instance.\r
359 @param Pkt Pointer to the packet.\r
360 @param Sender Pointer to the IP sender.\r
361 @param NotifyData Pointer to the notify data.\r
362 @param Dest Pointer to the destination IP address.\r
363 @param Override Pointer to the overriden IP_IO data.\r
364\r
365 @return Pointer to the data structure created to wrap the packet. If NULL,\r
366 @return resource limit occurred.\r
367\r
368**/\r
369STATIC\r
370IP_IO_SEND_ENTRY *\r
371IpIoCreateSndEntry (\r
372 IN IP_IO *IpIo,\r
373 IN NET_BUF *Pkt,\r
374 IN EFI_IP4_PROTOCOL *Sender,\r
375 IN VOID *Context OPTIONAL,\r
376 IN VOID *NotifyData OPTIONAL,\r
377 IN IP4_ADDR Dest,\r
378 IN IP_IO_OVERRIDE *Override\r
379 )\r
380{\r
381 IP_IO_SEND_ENTRY *SndEntry;\r
382 EFI_IP4_COMPLETION_TOKEN *SndToken;\r
383 EFI_IP4_TRANSMIT_DATA *TxData;\r
384 EFI_STATUS Status;\r
385 EFI_IP4_OVERRIDE_DATA *OverrideData;\r
34edf2ae 386 volatile UINT32 Index;\r
cbf316f2 387\r
388 //\r
389 // Allocate resource for SndEntry\r
390 //\r
391 SndEntry = NetAllocatePool (sizeof (IP_IO_SEND_ENTRY));\r
392 if (NULL == SndEntry) {\r
393 return NULL;\r
394 }\r
395\r
396 //\r
397 // Allocate resource for SndToken\r
398 //\r
399 SndToken = NetAllocatePool (sizeof (EFI_IP4_COMPLETION_TOKEN));\r
400 if (NULL == SndToken) {\r
401 goto ReleaseSndEntry;\r
402 }\r
403\r
404 Status = gBS->CreateEvent (\r
405 EVT_NOTIFY_SIGNAL,\r
406 NET_TPL_EVENT,\r
407 IpIoTransmitHandler,\r
408 SndEntry,\r
409 &(SndToken->Event)\r
410 );\r
411 if (EFI_ERROR (Status)) {\r
412 goto ReleaseSndToken;\r
413 }\r
414\r
415 //\r
416 // Allocate resource for TxData\r
417 //\r
418 TxData = NetAllocatePool (\r
419 sizeof (EFI_IP4_TRANSMIT_DATA) +\r
420 sizeof (EFI_IP4_FRAGMENT_DATA) * (Pkt->BlockOpNum - 1)\r
421 );\r
422\r
423 if (NULL == TxData) {\r
424 goto ReleaseEvent;\r
425 }\r
426\r
427 //\r
428 // Allocate resource for OverrideData if needed\r
429 //\r
430 OverrideData = NULL;\r
431 if (NULL != Override) {\r
432\r
433 OverrideData = NetAllocatePool (sizeof (EFI_IP4_OVERRIDE_DATA));\r
434 if (NULL == OverrideData) {\r
435 goto ReleaseResource;\r
436 }\r
437 //\r
438 // Set the fields of OverrideData\r
439 //\r
36ee91ca 440 CopyMem (OverrideData, Override, sizeof (*OverrideData));\r
cbf316f2 441 }\r
442\r
443 //\r
444 // Set the fields of TxData\r
445 //\r
b61439a7 446 NetCopyMem (&TxData->DestinationAddress, &Dest, sizeof (EFI_IPv4_ADDRESS));\r
cbf316f2 447 TxData->OverrideData = OverrideData;\r
448 TxData->OptionsLength = 0;\r
449 TxData->OptionsBuffer = NULL;\r
450 TxData->TotalDataLength = Pkt->TotalSize;\r
451 TxData->FragmentCount = Pkt->BlockOpNum;\r
452\r
cbf316f2 453\r
34edf2ae 454 for (Index = 0; Index < Pkt->BlockOpNum; Index++) {\r
cbf316f2 455 TxData->FragmentTable[Index].FragmentBuffer = Pkt->BlockOp[Index].Head;\r
456 TxData->FragmentTable[Index].FragmentLength = Pkt->BlockOp[Index].Size;\r
457 }\r
458\r
459 //\r
460 // Set the fields of SndToken\r
461 //\r
462 SndToken->Packet.TxData = TxData;\r
463\r
464 //\r
465 // Set the fields of SndEntry\r
466 //\r
467 SndEntry->IpIo = IpIo;\r
468 SndEntry->Ip = Sender;\r
469 SndEntry->Context = Context;\r
470 SndEntry->NotifyData = NotifyData;\r
471\r
472 SndEntry->Pkt = Pkt;\r
473 NET_GET_REF (Pkt);\r
474\r
475 SndEntry->SndToken = SndToken;\r
476\r
477 NetListInsertTail (&IpIo->PendingSndList, &SndEntry->Entry);\r
478\r
479 return SndEntry;\r
480\r
481ReleaseResource:\r
482 NetFreePool (TxData);\r
483\r
484ReleaseEvent:\r
485 gBS->CloseEvent (SndToken->Event);\r
486\r
487ReleaseSndToken:\r
488 NetFreePool (SndToken);\r
489\r
490ReleaseSndEntry:\r
491 NetFreePool (SndEntry);\r
492\r
493 return NULL;\r
494}\r
495\r
496\r
497/**\r
498 Destroy the SndEntry.\r
499\r
500 @param SndEntry Pointer to the send entry to be destroyed.\r
501\r
502 @return None.\r
503\r
504**/\r
505STATIC\r
506VOID\r
507IpIoDestroySndEntry (\r
508 IN IP_IO_SEND_ENTRY *SndEntry\r
509 )\r
510{\r
511 EFI_IP4_TRANSMIT_DATA *TxData;\r
512\r
513 TxData = SndEntry->SndToken->Packet.TxData;\r
514\r
515 if (NULL != TxData->OverrideData) {\r
516 NetFreePool (TxData->OverrideData);\r
517 }\r
518\r
519 NetFreePool (TxData);\r
520 NetbufFree (SndEntry->Pkt);\r
521 gBS->CloseEvent (SndEntry->SndToken->Event);\r
522\r
523 NetFreePool (SndEntry->SndToken);\r
524 NetListRemoveEntry (&SndEntry->Entry);\r
525\r
526 NetFreePool (SndEntry);\r
527}\r
528\r
529\r
530/**\r
531 Notify function for IP transmit token.\r
532\r
cbf316f2 533 @param Context The context passed in by the event notifier.\r
534\r
535 @return None.\r
536\r
537**/\r
538STATIC\r
539VOID\r
540EFIAPI\r
36ee91ca 541IpIoTransmitHandlerDpc (\r
cbf316f2 542 IN VOID *Context\r
543 )\r
544{\r
545 IP_IO *IpIo;\r
546 IP_IO_SEND_ENTRY *SndEntry;\r
547\r
548 SndEntry = (IP_IO_SEND_ENTRY *) Context;\r
549\r
550 IpIo = SndEntry->IpIo;\r
551\r
552 if (IpIo->PktSentNotify && SndEntry->NotifyData) {\r
553 IpIo->PktSentNotify (\r
554 SndEntry->SndToken->Status,\r
555 SndEntry->Context,\r
556 SndEntry->Ip,\r
557 SndEntry->NotifyData\r
558 );\r
559 }\r
560\r
561 IpIoDestroySndEntry (SndEntry);\r
562}\r
563\r
36ee91ca 564/**\r
565 Notify function for IP transmit token.\r
566\r
567 @param Event The event signaled.\r
568 @param Context The context passed in by the event notifier.\r
569\r
570 @return None.\r
571\r
572**/\r
573\r
574STATIC\r
575VOID\r
576EFIAPI\r
577IpIoTransmitHandler (\r
578 IN EFI_EVENT Event,\r
579 IN VOID *Context\r
580 )\r
581{\r
582 //\r
583 // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK\r
584 //\r
585 NetLibQueueDpc (TPL_CALLBACK, IpIoTransmitHandlerDpc, Context);\r
586}\r
587\r
cbf316f2 588\r
589/**\r
590 The dummy handler for the dummy IP receive token.\r
591\r
cbf316f2 592 @param Context The context passed in by the event notifier.\r
593\r
594 @return None.\r
595\r
596**/\r
597STATIC\r
598VOID\r
599EFIAPI\r
36ee91ca 600IpIoDummyHandlerDpc (\r
cbf316f2 601 IN VOID *Context\r
602 )\r
603{\r
604 IP_IO_IP_INFO *IpInfo;\r
605 EFI_IP4_COMPLETION_TOKEN *DummyToken;\r
606\r
cbf316f2 607 IpInfo = (IP_IO_IP_INFO *) Context;\r
608 DummyToken = &(IpInfo->DummyRcvToken);\r
609\r
36ee91ca 610 if (EFI_ABORTED == DummyToken->Status) {\r
611 //\r
612 // The reception is actively aborted by the consumer, directly return.\r
613 //\r
614 return;\r
615 } else if (EFI_SUCCESS == DummyToken->Status) {\r
cbf316f2 616 ASSERT (DummyToken->Packet.RxData);\r
617\r
618 gBS->SignalEvent (DummyToken->Packet.RxData->RecycleSignal);\r
619 }\r
620\r
621 IpInfo->Ip->Receive (IpInfo->Ip, DummyToken);\r
622}\r
623\r
624\r
625/**\r
36ee91ca 626 Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK.\r
cbf316f2 627\r
628 @param Event The event signaled.\r
629 @param Context The context passed in by the event notifier.\r
630\r
631 @return None.\r
632\r
633**/\r
634STATIC\r
635VOID\r
636EFIAPI\r
36ee91ca 637IpIoDummyHandler (\r
cbf316f2 638 IN EFI_EVENT Event,\r
639 IN VOID *Context\r
640 )\r
36ee91ca 641{\r
642 //\r
643 // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK\r
644 //\r
645 NetLibQueueDpc (TPL_CALLBACK, IpIoDummyHandlerDpc, Context);\r
646}\r
647\r
648\r
649/**\r
650 Notify function for the IP receive token, used to process\r
651 the received IP packets.\r
652\r
653 @param Context The context passed in by the event notifier.\r
654\r
655 @return None.\r
656\r
657**/\r
658STATIC\r
659VOID\r
660EFIAPI\r
661IpIoListenHandlerDpc (\r
662 IN VOID *Context\r
663 )\r
cbf316f2 664{\r
665 IP_IO *IpIo;\r
666 EFI_STATUS Status;\r
667 EFI_IP4_RECEIVE_DATA *RxData;\r
668 EFI_IP4_PROTOCOL *Ip;\r
669 EFI_NET_SESSION_DATA Session;\r
670 NET_BUF *Pkt;\r
671\r
672 IpIo = (IP_IO *) Context;\r
673\r
674 Ip = IpIo->Ip;\r
675 Status = IpIo->RcvToken.Status;\r
676 RxData = IpIo->RcvToken.Packet.RxData;\r
677\r
36ee91ca 678 if (EFI_ABORTED == Status) {\r
679 //\r
680 // The reception is actively aborted by the consumer, directly return.\r
681 //\r
682 return;\r
683 }\r
684\r
cbf316f2 685 if (((EFI_SUCCESS != Status) && (EFI_ICMP_ERROR != Status)) || (NULL == RxData)) {\r
686 //\r
687 // Only process the normal packets and the icmp error packets, if RxData is NULL\r
688 // with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although\r
689 // this should be a bug of the low layer (IP).\r
690 //\r
691 goto Resume;\r
692 }\r
693\r
694 if (NULL == IpIo->PktRcvdNotify) {\r
695 goto CleanUp;\r
696 }\r
697\r
698 if ((EFI_IP4 (RxData->Header->SourceAddress) != 0) &&\r
699 !Ip4IsUnicast (EFI_NTOHL (RxData->Header->SourceAddress), 0)) {\r
700 //\r
701 // The source address is not zero and it's not a unicast IP address, discard it.\r
702 //\r
703 goto CleanUp;\r
704 }\r
705\r
706 //\r
707 // Create a netbuffer representing packet\r
708 //\r
709 Pkt = NetbufFromExt (\r
710 (NET_FRAGMENT *) RxData->FragmentTable,\r
711 RxData->FragmentCount,\r
712 0,\r
713 0,\r
714 IpIoExtFree,\r
715 RxData->RecycleSignal\r
716 );\r
717 if (NULL == Pkt) {\r
718 goto CleanUp;\r
719 }\r
720\r
721 //\r
722 // Create a net session\r
723 //\r
724 Session.Source = EFI_IP4 (RxData->Header->SourceAddress);\r
725 Session.Dest = EFI_IP4 (RxData->Header->DestinationAddress);\r
726 Session.IpHdr = RxData->Header;\r
727\r
728 if (EFI_SUCCESS == Status) {\r
729\r
4eb65aff 730 IpIo->PktRcvdNotify (EFI_SUCCESS, (ICMP_ERROR) 0, &Session, Pkt, IpIo->RcvdContext);\r
cbf316f2 731 } else {\r
732 //\r
733 // Status is EFI_ICMP_ERROR\r
734 //\r
735 Status = IpIoIcmpHandler (IpIo, Pkt, &Session);\r
736 if (EFI_ERROR (Status)) {\r
737 NetbufFree (Pkt);\r
738 }\r
739 }\r
740\r
741 goto Resume;\r
742\r
743CleanUp:\r
744 gBS->SignalEvent (RxData->RecycleSignal);\r
745\r
746Resume:\r
747 Ip->Receive (Ip, &(IpIo->RcvToken));\r
748}\r
749\r
750\r
36ee91ca 751/**\r
752 Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK\r
753\r
754 @param Event The event signaled.\r
755 @param Context The context passed in by the event notifier.\r
756\r
757 @return None.\r
758\r
759**/\r
760STATIC\r
761VOID\r
762EFIAPI\r
763IpIoListenHandler (\r
764 IN EFI_EVENT Event,\r
765 IN VOID *Context\r
766 )\r
767{\r
768 //\r
769 // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK\r
770 //\r
771 NetLibQueueDpc (TPL_CALLBACK, IpIoListenHandlerDpc, Context);\r
772}\r
773\r
774\r
cbf316f2 775/**\r
776 Create a new IP_IO instance.\r
777\r
778 @param Image The image handle of an IP_IO consumer protocol.\r
779 @param Controller The controller handle of an IP_IO consumer protocol\r
780 installed on.\r
781\r
782 @return Pointer to a newly created IP_IO instance.\r
783\r
784**/\r
785IP_IO *\r
786IpIoCreate (\r
787 IN EFI_HANDLE Image,\r
788 IN EFI_HANDLE Controller\r
789 )\r
790{\r
791 EFI_STATUS Status;\r
792 IP_IO *IpIo;\r
793\r
794 IpIo = NetAllocateZeroPool (sizeof (IP_IO));\r
795 if (NULL == IpIo) {\r
796 return NULL;\r
797 }\r
798\r
799 NetListInit (&(IpIo->PendingSndList));\r
800 NetListInit (&(IpIo->IpList));\r
801 IpIo->Controller = Controller;\r
802 IpIo->Image = Image;\r
803\r
804 Status = gBS->CreateEvent (\r
805 EVT_NOTIFY_SIGNAL,\r
806 NET_TPL_EVENT,\r
807 IpIoListenHandler,\r
808 IpIo,\r
809 &(IpIo->RcvToken.Event)\r
810 );\r
811 if (EFI_ERROR (Status)) {\r
812 goto ReleaseIpIo;\r
813 }\r
814\r
815 //\r
816 // Create an IP child and open IP protocol\r
817 //\r
818 Status = IpIoCreateIpChildOpenProtocol (\r
819 Controller,\r
820 Image,\r
821 &IpIo->ChildHandle,\r
822 (VOID **)&(IpIo->Ip)\r
823 );\r
824 if (EFI_ERROR (Status)) {\r
825 goto ReleaseIpIo;\r
826 }\r
827\r
828 return IpIo;\r
829\r
830ReleaseIpIo:\r
831\r
832 if (NULL != IpIo->RcvToken.Event) {\r
833 gBS->CloseEvent (IpIo->RcvToken.Event);\r
834 }\r
835\r
836 NetFreePool (IpIo);\r
837\r
838 return NULL;\r
839}\r
840\r
841\r
842/**\r
843 Open an IP_IO instance for use.\r
844\r
845 @param IpIo Pointer to an IP_IO instance that needs to open.\r
846 @param OpenData The configuration data for the IP_IO instance.\r
847\r
848 @retval EFI_SUCCESS The IP_IO instance opened with OpenData\r
849 successfully.\r
850 @retval other Error condition occurred.\r
851\r
852**/\r
853EFI_STATUS\r
854IpIoOpen (\r
855 IN IP_IO *IpIo,\r
856 IN IP_IO_OPEN_DATA *OpenData\r
857 )\r
858{\r
859 EFI_STATUS Status;\r
860 EFI_IP4_PROTOCOL *Ip;\r
cbf316f2 861\r
862 if (IpIo->IsConfigured) {\r
863 return EFI_ACCESS_DENIED;\r
864 }\r
865\r
866 Ip = IpIo->Ip;\r
867\r
868 //\r
869 // configure ip\r
870 //\r
871 Status = Ip->Configure (Ip, &OpenData->IpConfigData);\r
872 if (EFI_ERROR (Status)) {\r
873 return Status;\r
874 }\r
875\r
876 //\r
877 // bugbug: to delete the default route entry in this Ip, if it is:\r
878 // (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified\r
879 // its code\r
880 //\r
b61439a7 881 Status = Ip->Routes (Ip, TRUE, &mZeroIp4Addr, &mZeroIp4Addr, &mZeroIp4Addr);\r
cbf316f2 882\r
883 if (EFI_ERROR (Status) && (EFI_NOT_FOUND != Status)) {\r
884 return Status;\r
885 }\r
886\r
887 IpIo->PktRcvdNotify = OpenData->PktRcvdNotify;\r
888 IpIo->PktSentNotify = OpenData->PktSentNotify;\r
889\r
890 IpIo->RcvdContext = OpenData->RcvdContext;\r
891 IpIo->SndContext = OpenData->SndContext;\r
892\r
893 IpIo->Protocol = OpenData->IpConfigData.DefaultProtocol;\r
894\r
895 //\r
896 // start to listen incoming packet\r
897 //\r
898 Status = Ip->Receive (Ip, &(IpIo->RcvToken));\r
899 if (EFI_ERROR (Status)) {\r
900 Ip->Configure (Ip, NULL);\r
901 goto ErrorExit;\r
902 }\r
903\r
904 IpIo->IsConfigured = TRUE;\r
905 NetListInsertTail (&mActiveIpIoList, &IpIo->Entry);\r
906\r
907ErrorExit:\r
908\r
909 return Status;\r
910}\r
911\r
912\r
913/**\r
914 Stop an IP_IO instance.\r
915\r
916 @param IpIo Pointer to the IP_IO instance that needs to stop.\r
917\r
918 @retval EFI_SUCCESS The IP_IO instance stopped successfully.\r
919 @retval other Error condition occurred.\r
920\r
921**/\r
922EFI_STATUS\r
923IpIoStop (\r
924 IN IP_IO *IpIo\r
925 )\r
926{\r
927 EFI_STATUS Status;\r
928 EFI_IP4_PROTOCOL *Ip;\r
929 IP_IO_IP_INFO *IpInfo;\r
930\r
931 if (!IpIo->IsConfigured) {\r
932 return EFI_SUCCESS;\r
933 }\r
934\r
935 //\r
936 // Remove the IpIo from the active IpIo list.\r
937 //\r
938 NetListRemoveEntry (&IpIo->Entry);\r
939\r
940 Ip = IpIo->Ip;\r
941\r
942 //\r
943 // Configure NULL Ip\r
944 //\r
945 Status = Ip->Configure (Ip, NULL);\r
946 if (EFI_ERROR (Status)) {\r
947 return Status;\r
948 }\r
949\r
950 IpIo->IsConfigured = FALSE;\r
951\r
952 //\r
953 // Detroy the Ip List used by IpIo\r
954 //\r
34edf2ae 955\r
cbf316f2 956 while (!NetListIsEmpty (&(IpIo->IpList))) {\r
957 IpInfo = NET_LIST_HEAD (&(IpIo->IpList), IP_IO_IP_INFO, Entry);\r
958\r
959 IpIoRemoveIp (IpIo, IpInfo);\r
960 }\r
961\r
962 //\r
963 // All pending snd tokens should be flushed by reseting the IP instances.\r
964 //\r
965 ASSERT (NetListIsEmpty (&IpIo->PendingSndList));\r
966\r
967 //\r
968 // Close the receive event.\r
969 //\r
970 gBS->CloseEvent (IpIo->RcvToken.Event);\r
971\r
972 return EFI_SUCCESS;\r
973}\r
974\r
975\r
976/**\r
977 Destroy an IP_IO instance.\r
978\r
979 @param IpIo Pointer to the IP_IO instance that needs to\r
980 destroy.\r
981\r
982 @retval EFI_SUCCESS The IP_IO instance destroyed successfully.\r
983 @retval other Error condition occurred.\r
984\r
985**/\r
986EFI_STATUS\r
987IpIoDestroy (\r
988 IN IP_IO *IpIo\r
989 )\r
990{\r
991 //\r
992 // Stop the IpIo.\r
993 //\r
994 IpIoStop (IpIo);\r
995\r
996 //\r
997 // Close the IP protocol and destroy the child.\r
998 //\r
999 IpIoCloseProtocolDestroyIpChild (IpIo->Controller, IpIo->Image, IpIo->ChildHandle);\r
1000\r
1001 NetFreePool (IpIo);\r
1002\r
1003 return EFI_SUCCESS;\r
1004}\r
1005\r
1006\r
1007/**\r
1008 Send out an IP packet.\r
1009\r
1010 @param IpIo Pointer to an IP_IO instance used for sending IP\r
1011 packet.\r
1012 @param Pkt Pointer to the IP packet to be sent.\r
1013 @param Sender The IP protocol instance used for sending.\r
1014 @param NotifyData\r
1015 @param Dest The destination IP address to send this packet to.\r
1016 @param OverrideData The data to override some configuration of the IP\r
1017 instance used for sending.\r
1018\r
1019 @retval EFI_SUCCESS The operation is completed successfully.\r
1020 @retval EFI_NOT_STARTED The IpIo is not configured.\r
1021 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.\r
1022\r
1023**/\r
1024EFI_STATUS\r
1025IpIoSend (\r
1026 IN IP_IO *IpIo,\r
1027 IN NET_BUF *Pkt,\r
1028 IN IP_IO_IP_INFO *Sender,\r
1029 IN VOID *Context OPTIONAL,\r
1030 IN VOID *NotifyData OPTIONAL,\r
1031 IN IP4_ADDR Dest,\r
1032 IN IP_IO_OVERRIDE *OverrideData\r
1033 )\r
1034{\r
1035 EFI_STATUS Status;\r
1036 EFI_IP4_PROTOCOL *Ip;\r
1037 IP_IO_SEND_ENTRY *SndEntry;\r
1038\r
1039 if (!IpIo->IsConfigured) {\r
1040 return EFI_NOT_STARTED;\r
1041 }\r
1042\r
1043 Ip = (NULL == Sender) ? IpIo->Ip : Sender->Ip;\r
1044\r
1045 //\r
1046 // create a new SndEntry\r
1047 //\r
1048 SndEntry = IpIoCreateSndEntry (IpIo, Pkt, Ip, Context, NotifyData, Dest, OverrideData);\r
1049 if (NULL == SndEntry) {\r
1050 return EFI_OUT_OF_RESOURCES;\r
1051 }\r
1052\r
1053 //\r
1054 // Send this Packet\r
1055 //\r
1056 Status = Ip->Transmit (Ip, SndEntry->SndToken);\r
1057 if (EFI_ERROR (Status)) {\r
1058 IpIoDestroySndEntry (SndEntry);\r
1059 }\r
1060\r
1061 return Status;\r
1062}\r
1063\r
1064\r
1065/**\r
1066 Cancel the IP transmit token which wraps this Packet.\r
1067\r
1068 @param IpIo Pointer to the IP_IO instance.\r
1069 @param Packet Pointer to the packet to cancel.\r
1070\r
1071 @return N/A.\r
1072\r
1073**/\r
1074VOID\r
1075IpIoCancelTxToken (\r
1076 IN IP_IO *IpIo,\r
1077 IN VOID *Packet\r
1078 )\r
1079{\r
1080 NET_LIST_ENTRY *Node;\r
1081 IP_IO_SEND_ENTRY *SndEntry;\r
1082 EFI_IP4_PROTOCOL *Ip;\r
1083\r
1084 ASSERT (IpIo && Packet);\r
1085\r
1086 NET_LIST_FOR_EACH (Node, &IpIo->PendingSndList) {\r
1087\r
1088 SndEntry = NET_LIST_USER_STRUCT (Node, IP_IO_SEND_ENTRY, Entry);\r
1089\r
1090 if (SndEntry->Pkt == Packet) {\r
1091\r
1092 Ip = SndEntry->Ip;\r
1093 Ip->Cancel (Ip, SndEntry->SndToken);\r
1094\r
1095 //\r
1096 // Abort the user token.\r
1097 //\r
1098 SndEntry->SndToken->Status = EFI_ABORTED;\r
1099 IpIoTransmitHandler (NULL, SndEntry);\r
1100\r
1101 break;\r
1102 }\r
1103 }\r
1104\r
1105}\r
1106\r
1107\r
1108/**\r
1109 Add a new IP instance for sending data.\r
1110\r
1111 @param IpIo Pointer to a IP_IO instance to add a new IP\r
1112 instance for sending purpose.\r
1113\r
1114 @return Pointer to the created IP_IO_IP_INFO structure, NULL is failed.\r
1115\r
1116**/\r
1117IP_IO_IP_INFO *\r
1118IpIoAddIp (\r
1119 IN IP_IO *IpIo\r
1120 )\r
1121{\r
1122 EFI_STATUS Status;\r
1123 IP_IO_IP_INFO *IpInfo;\r
1124\r
1125 ASSERT (IpIo);\r
1126\r
1127 IpInfo = NetAllocatePool (sizeof (IP_IO_IP_INFO));\r
1128 if (IpInfo == NULL) {\r
1129 return IpInfo;\r
1130 }\r
1131\r
1132 //\r
1133 // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP\r
1134 // instance.\r
1135 //\r
1136 NetListInit (&IpInfo->Entry);\r
1137 IpInfo->ChildHandle = NULL;\r
1138 IpInfo->Addr = 0;\r
1139 IpInfo->SubnetMask = 0;\r
1140 IpInfo->RefCnt = 1;\r
1141\r
1142 //\r
1143 // Create the IP instance and open the Ip4 protocol.\r
1144 //\r
1145 Status = IpIoCreateIpChildOpenProtocol (\r
1146 IpIo->Controller,\r
1147 IpIo->Image,\r
1148 &IpInfo->ChildHandle,\r
4eb65aff 1149 (VOID **) &IpInfo->Ip\r
cbf316f2 1150 );\r
1151 if (EFI_ERROR (Status)) {\r
1152 goto ReleaseIpInfo;\r
1153 }\r
1154\r
1155 //\r
1156 // Create the event for the DummyRcvToken.\r
1157 //\r
1158 Status = gBS->CreateEvent (\r
1159 EVT_NOTIFY_SIGNAL,\r
1160 NET_TPL_EVENT,\r
1161 IpIoDummyHandler,\r
1162 IpInfo,\r
1163 &IpInfo->DummyRcvToken.Event\r
1164 );\r
1165 if (EFI_ERROR (Status)) {\r
1166 goto ReleaseIpChild;\r
1167 }\r
1168\r
1169 //\r
1170 // Link this IpInfo into the IpIo.\r
1171 //\r
1172 NetListInsertTail (&IpIo->IpList, &IpInfo->Entry);\r
1173\r
1174 return IpInfo;\r
1175\r
1176ReleaseIpChild:\r
1177\r
1178 IpIoCloseProtocolDestroyIpChild (\r
1179 IpIo->Controller,\r
1180 IpIo->Image,\r
1181 IpInfo->ChildHandle\r
1182 );\r
1183\r
1184ReleaseIpInfo:\r
1185\r
1186 NetFreePool (IpInfo);\r
1187\r
1188 return NULL;\r
1189}\r
1190\r
1191\r
1192/**\r
1193 Configure the IP instance of this IpInfo and start the receiving if Ip4ConfigData\r
1194 is not NULL.\r
1195\r
1196 @param IpInfo Pointer to the IP_IO_IP_INFO instance.\r
1197 @param Ip4ConfigData The IP4 configure data used to configure the ip\r
1198 instance, if NULL the ip instance is reseted. If\r
1199 UseDefaultAddress is set to TRUE, and the configure\r
1200 operation succeeds, the default address information\r
1201 is written back in this Ip4ConfigData.\r
1202\r
1203 @retval EFI_STATUS The status returned by IP4->Configure or\r
1204 IP4->Receive.\r
1205\r
1206**/\r
1207EFI_STATUS\r
1208IpIoConfigIp (\r
1209 IN IP_IO_IP_INFO *IpInfo,\r
1210 IN OUT EFI_IP4_CONFIG_DATA *Ip4ConfigData OPTIONAL\r
1211 )\r
1212{\r
1213 EFI_STATUS Status;\r
1214 EFI_IP4_PROTOCOL *Ip;\r
1215 EFI_IP4_MODE_DATA Ip4ModeData;\r
1216\r
1217 ASSERT (IpInfo);\r
1218\r
1219 if (IpInfo->RefCnt > 1) {\r
1220 //\r
1221 // This IP instance is shared, don't reconfigure it until it has only one\r
1222 // consumer. Currently, only the tcp children cloned from their passive parent\r
1223 // will share the same IP. So this cases only happens while Ip4ConfigData is NULL,\r
1224 // let the last consumer clean the IP instance.\r
1225 //\r
1226 return EFI_SUCCESS;\r
1227 }\r
1228\r
1229 Ip = IpInfo->Ip;\r
1230\r
1231 Status = Ip->Configure (Ip, Ip4ConfigData);\r
1232 if (EFI_ERROR (Status)) {\r
1233 goto OnExit;\r
1234 }\r
1235\r
1236 if (Ip4ConfigData != NULL) {\r
1237\r
1238 if (Ip4ConfigData->UseDefaultAddress) {\r
1239 Ip->GetModeData (Ip, &Ip4ModeData, NULL, NULL);\r
1240\r
1241 Ip4ConfigData->StationAddress = Ip4ModeData.ConfigData.StationAddress;\r
1242 Ip4ConfigData->SubnetMask = Ip4ModeData.ConfigData.SubnetMask;\r
1243 }\r
1244\r
b61439a7 1245 NetCopyMem (&IpInfo->Addr, &Ip4ConfigData->StationAddress, sizeof (IP4_ADDR));\r
1246 NetCopyMem (&IpInfo->SubnetMask, &Ip4ConfigData->SubnetMask, sizeof (IP4_ADDR));\r
cbf316f2 1247\r
1248 Status = Ip->Receive (Ip, &IpInfo->DummyRcvToken);\r
1249 if (EFI_ERROR (Status)) {\r
1250 Ip->Configure (Ip, NULL);\r
1251 }\r
1252 } else {\r
1253\r
1254 //\r
1255 // The IP instance is reseted, set the stored Addr and SubnetMask to zero.\r
1256 //\r
1257 IpInfo->Addr = 0;\r
1258 IpInfo->SubnetMask =0;\r
1259 }\r
1260\r
1261OnExit:\r
1262\r
1263 return Status;\r
1264}\r
1265\r
1266\r
1267/**\r
1268 Destroy an IP instance maintained in IpIo->IpList for\r
1269 sending purpose.\r
1270\r
1271 @param IpIo Pointer to the IP_IO instance.\r
1272 @param IpInfo Pointer to the IpInfo to be removed.\r
1273\r
1274 @return None.\r
1275\r
1276**/\r
1277VOID\r
1278IpIoRemoveIp (\r
1279 IN IP_IO *IpIo,\r
1280 IN IP_IO_IP_INFO *IpInfo\r
1281 )\r
1282{\r
1283 ASSERT (IpInfo->RefCnt > 0);\r
1284\r
1285 NET_PUT_REF (IpInfo);\r
1286\r
1287 if (IpInfo->RefCnt > 0) {\r
1288\r
1289 return;\r
1290 }\r
1291\r
1292 NetListRemoveEntry (&IpInfo->Entry);\r
1293\r
1294 IpInfo->Ip->Configure (IpInfo->Ip, NULL);\r
1295\r
1296 IpIoCloseProtocolDestroyIpChild (IpIo->Controller, IpIo->Image, IpInfo->ChildHandle);\r
1297\r
1298 gBS->CloseEvent (IpInfo->DummyRcvToken.Event);\r
1299\r
1300 NetFreePool (IpInfo);\r
1301}\r
1302\r
1303\r
1304/**\r
1305 Find the first IP protocol maintained in IpIo whose local\r
1306 address is the same with Src.\r
1307\r
1308 @param IpIo Pointer to the pointer of the IP_IO instance.\r
1309 @param Src The local IP address.\r
1310\r
1311 @return Pointer to the IP protocol can be used for sending purpose and its local\r
1312 @return address is the same with Src.\r
1313\r
1314**/\r
1315IP_IO_IP_INFO *\r
1316IpIoFindSender (\r
1317 IN OUT IP_IO **IpIo,\r
1318 IN IP4_ADDR Src\r
1319 )\r
1320{\r
1321 NET_LIST_ENTRY *IpIoEntry;\r
1322 IP_IO *IpIoPtr;\r
1323 NET_LIST_ENTRY *IpInfoEntry;\r
1324 IP_IO_IP_INFO *IpInfo;\r
1325\r
1326 NET_LIST_FOR_EACH (IpIoEntry, &mActiveIpIoList) {\r
1327 IpIoPtr = NET_LIST_USER_STRUCT (IpIoEntry, IP_IO, Entry);\r
1328\r
1329 if ((*IpIo != NULL) && (*IpIo != IpIoPtr)) {\r
1330 continue;\r
1331 }\r
1332\r
1333 NET_LIST_FOR_EACH (IpInfoEntry, &IpIoPtr->IpList) {\r
1334 IpInfo = NET_LIST_USER_STRUCT (IpInfoEntry, IP_IO_IP_INFO, Entry);\r
1335\r
1336 if (IpInfo->Addr == Src) {\r
1337 *IpIo = IpIoPtr;\r
1338 return IpInfo;\r
1339 }\r
1340 }\r
1341 }\r
1342\r
1343 //\r
1344 // No match.\r
1345 //\r
1346 return NULL;\r
1347}\r
1348\r
1349\r
1350/**\r
1351 Get the ICMP error map information, the ErrorStatus will be returned.\r
1352 The IsHard and Notify are optional. If they are not NULL, this rouine will\r
1353 fill them.\r
1354 We move IcmpErrMap[] to local variable to enable EBC build.\r
1355\r
1356 @param IcmpError IcmpError Type\r
1357 @param IsHard Whether it is a hard error\r
1358 @param Notify Whether it need to notify SockError\r
1359\r
1360 @return ICMP Error Status\r
1361\r
1362**/\r
1363EFI_STATUS\r
1364IpIoGetIcmpErrStatus (\r
1365 IN ICMP_ERROR IcmpError,\r
1366 OUT BOOLEAN *IsHard, OPTIONAL\r
1367 OUT BOOLEAN *Notify OPTIONAL\r
1368 )\r
1369{\r
01750eb0 1370 ASSERT ((IcmpError >= ICMP_ERR_UNREACH_NET) && (IcmpError <= ICMP_ERR_PARAMPROB));\r
687a2e5f 1371\r
01750eb0 1372 if (IsHard != NULL) {\r
1373 *IsHard = mIcmpErrMap[IcmpError].IsHard;\r
1374 }\r
687a2e5f 1375\r
01750eb0 1376 if (Notify != NULL) {\r
1377 *Notify = mIcmpErrMap[IcmpError].Notify;\r
1378 }\r
687a2e5f 1379\r
01750eb0 1380 switch (IcmpError) {\r
1381 case ICMP_ERR_UNREACH_NET:\r
1382 return EFI_NETWORK_UNREACHABLE;\r
687a2e5f 1383\r
01750eb0 1384 case ICMP_ERR_TIMXCEED_INTRANS:\r
1385 case ICMP_ERR_TIMXCEED_REASS:\r
1386 case ICMP_ERR_UNREACH_HOST:\r
1387 return EFI_HOST_UNREACHABLE;\r
cbf316f2 1388\r
01750eb0 1389 case ICMP_ERR_UNREACH_PROTOCOL:\r
1390 return EFI_PROTOCOL_UNREACHABLE;\r
cbf316f2 1391\r
01750eb0 1392 case ICMP_ERR_UNREACH_PORT:\r
1393 return EFI_PORT_UNREACHABLE;\r
cbf316f2 1394\r
01750eb0 1395 case ICMP_ERR_MSGSIZE:\r
1396 case ICMP_ERR_UNREACH_SRCFAIL:\r
1397 case ICMP_ERR_QUENCH:\r
1398 case ICMP_ERR_PARAMPROB:\r
1399 return EFI_ICMP_ERROR;\r
cbf316f2 1400 }\r
1401\r
01750eb0 1402 //\r
1403 // will never run here!\r
1404 //\r
1405 ASSERT (FALSE);\r
1406 return EFI_UNSUPPORTED;\r
cbf316f2 1407}\r
1408\r