]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[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
e48e37fc 39LIST_ENTRY mActiveIpIoList = {\r
cbf316f2 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
e48e37fc 391 SndEntry = AllocatePool (sizeof (IP_IO_SEND_ENTRY));\r
cbf316f2 392 if (NULL == SndEntry) {\r
393 return NULL;\r
394 }\r
395\r
396 //\r
397 // Allocate resource for SndToken\r
398 //\r
e48e37fc 399 SndToken = AllocatePool (sizeof (EFI_IP4_COMPLETION_TOKEN));\r
cbf316f2 400 if (NULL == SndToken) {\r
401 goto ReleaseSndEntry;\r
402 }\r
403\r
404 Status = gBS->CreateEvent (\r
405 EVT_NOTIFY_SIGNAL,\r
e48e37fc 406 TPL_NOTIFY,\r
cbf316f2 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
e48e37fc 418 TxData = AllocatePool (\r
cbf316f2 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
e48e37fc 433 OverrideData = AllocatePool (sizeof (EFI_IP4_OVERRIDE_DATA));\r
cbf316f2 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
e48e37fc 446 CopyMem (&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
e48e37fc 477 InsertTailList (&IpIo->PendingSndList, &SndEntry->Entry);\r
cbf316f2 478\r
479 return SndEntry;\r
480\r
481ReleaseResource:\r
e48e37fc 482 gBS->FreePool (TxData);\r
cbf316f2 483\r
484ReleaseEvent:\r
485 gBS->CloseEvent (SndToken->Event);\r
486\r
487ReleaseSndToken:\r
e48e37fc 488 gBS->FreePool (SndToken);\r
cbf316f2 489\r
490ReleaseSndEntry:\r
e48e37fc 491 gBS->FreePool (SndEntry);\r
cbf316f2 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
e48e37fc 516 gBS->FreePool (TxData->OverrideData);\r
cbf316f2 517 }\r
518\r
e48e37fc 519 gBS->FreePool (TxData);\r
cbf316f2 520 NetbufFree (SndEntry->Pkt);\r
521 gBS->CloseEvent (SndEntry->SndToken->Event);\r
522\r
e48e37fc 523 gBS->FreePool (SndEntry->SndToken);\r
524 RemoveEntryList (&SndEntry->Entry);\r
cbf316f2 525\r
e48e37fc 526 gBS->FreePool (SndEntry);\r
cbf316f2 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
7b414b4e 786EFIAPI\r
cbf316f2 787IpIoCreate (\r
788 IN EFI_HANDLE Image,\r
789 IN EFI_HANDLE Controller\r
790 )\r
791{\r
792 EFI_STATUS Status;\r
793 IP_IO *IpIo;\r
794\r
e48e37fc 795 IpIo = AllocateZeroPool (sizeof (IP_IO));\r
cbf316f2 796 if (NULL == IpIo) {\r
797 return NULL;\r
798 }\r
799\r
e48e37fc 800 InitializeListHead (&(IpIo->PendingSndList));\r
801 InitializeListHead (&(IpIo->IpList));\r
cbf316f2 802 IpIo->Controller = Controller;\r
803 IpIo->Image = Image;\r
804\r
805 Status = gBS->CreateEvent (\r
806 EVT_NOTIFY_SIGNAL,\r
e48e37fc 807 TPL_NOTIFY,\r
cbf316f2 808 IpIoListenHandler,\r
809 IpIo,\r
810 &(IpIo->RcvToken.Event)\r
811 );\r
812 if (EFI_ERROR (Status)) {\r
813 goto ReleaseIpIo;\r
814 }\r
815\r
816 //\r
817 // Create an IP child and open IP protocol\r
818 //\r
819 Status = IpIoCreateIpChildOpenProtocol (\r
820 Controller,\r
821 Image,\r
822 &IpIo->ChildHandle,\r
823 (VOID **)&(IpIo->Ip)\r
824 );\r
825 if (EFI_ERROR (Status)) {\r
826 goto ReleaseIpIo;\r
827 }\r
828\r
829 return IpIo;\r
830\r
831ReleaseIpIo:\r
832\r
833 if (NULL != IpIo->RcvToken.Event) {\r
834 gBS->CloseEvent (IpIo->RcvToken.Event);\r
835 }\r
836\r
e48e37fc 837 gBS->FreePool (IpIo);\r
cbf316f2 838\r
839 return NULL;\r
840}\r
841\r
842\r
843/**\r
844 Open an IP_IO instance for use.\r
845\r
846 @param IpIo Pointer to an IP_IO instance that needs to open.\r
847 @param OpenData The configuration data for the IP_IO instance.\r
848\r
849 @retval EFI_SUCCESS The IP_IO instance opened with OpenData\r
850 successfully.\r
851 @retval other Error condition occurred.\r
852\r
853**/\r
854EFI_STATUS\r
7b414b4e 855EFIAPI\r
cbf316f2 856IpIoOpen (\r
857 IN IP_IO *IpIo,\r
858 IN IP_IO_OPEN_DATA *OpenData\r
859 )\r
860{\r
861 EFI_STATUS Status;\r
862 EFI_IP4_PROTOCOL *Ip;\r
cbf316f2 863\r
864 if (IpIo->IsConfigured) {\r
865 return EFI_ACCESS_DENIED;\r
866 }\r
867\r
868 Ip = IpIo->Ip;\r
869\r
870 //\r
871 // configure ip\r
872 //\r
873 Status = Ip->Configure (Ip, &OpenData->IpConfigData);\r
874 if (EFI_ERROR (Status)) {\r
875 return Status;\r
876 }\r
877\r
878 //\r
879 // bugbug: to delete the default route entry in this Ip, if it is:\r
880 // (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified\r
881 // its code\r
882 //\r
b61439a7 883 Status = Ip->Routes (Ip, TRUE, &mZeroIp4Addr, &mZeroIp4Addr, &mZeroIp4Addr);\r
cbf316f2 884\r
885 if (EFI_ERROR (Status) && (EFI_NOT_FOUND != Status)) {\r
886 return Status;\r
887 }\r
888\r
889 IpIo->PktRcvdNotify = OpenData->PktRcvdNotify;\r
890 IpIo->PktSentNotify = OpenData->PktSentNotify;\r
891\r
892 IpIo->RcvdContext = OpenData->RcvdContext;\r
893 IpIo->SndContext = OpenData->SndContext;\r
894\r
895 IpIo->Protocol = OpenData->IpConfigData.DefaultProtocol;\r
896\r
897 //\r
898 // start to listen incoming packet\r
899 //\r
900 Status = Ip->Receive (Ip, &(IpIo->RcvToken));\r
901 if (EFI_ERROR (Status)) {\r
902 Ip->Configure (Ip, NULL);\r
903 goto ErrorExit;\r
904 }\r
905\r
906 IpIo->IsConfigured = TRUE;\r
e48e37fc 907 InsertTailList (&mActiveIpIoList, &IpIo->Entry);\r
cbf316f2 908\r
909ErrorExit:\r
910\r
911 return Status;\r
912}\r
913\r
914\r
915/**\r
916 Stop an IP_IO instance.\r
917\r
918 @param IpIo Pointer to the IP_IO instance that needs to stop.\r
919\r
920 @retval EFI_SUCCESS The IP_IO instance stopped successfully.\r
921 @retval other Error condition occurred.\r
922\r
923**/\r
924EFI_STATUS\r
925IpIoStop (\r
926 IN IP_IO *IpIo\r
927 )\r
928{\r
929 EFI_STATUS Status;\r
930 EFI_IP4_PROTOCOL *Ip;\r
931 IP_IO_IP_INFO *IpInfo;\r
932\r
933 if (!IpIo->IsConfigured) {\r
934 return EFI_SUCCESS;\r
935 }\r
936\r
937 //\r
938 // Remove the IpIo from the active IpIo list.\r
939 //\r
e48e37fc 940 RemoveEntryList (&IpIo->Entry);\r
cbf316f2 941\r
942 Ip = IpIo->Ip;\r
943\r
944 //\r
945 // Configure NULL Ip\r
946 //\r
947 Status = Ip->Configure (Ip, NULL);\r
948 if (EFI_ERROR (Status)) {\r
949 return Status;\r
950 }\r
951\r
952 IpIo->IsConfigured = FALSE;\r
953\r
954 //\r
955 // Detroy the Ip List used by IpIo\r
956 //\r
34edf2ae 957\r
e48e37fc 958 while (!IsListEmpty (&(IpIo->IpList))) {\r
cbf316f2 959 IpInfo = NET_LIST_HEAD (&(IpIo->IpList), IP_IO_IP_INFO, Entry);\r
960\r
961 IpIoRemoveIp (IpIo, IpInfo);\r
962 }\r
963\r
964 //\r
965 // All pending snd tokens should be flushed by reseting the IP instances.\r
966 //\r
e48e37fc 967 ASSERT (IsListEmpty (&IpIo->PendingSndList));\r
cbf316f2 968\r
969 //\r
970 // Close the receive event.\r
971 //\r
972 gBS->CloseEvent (IpIo->RcvToken.Event);\r
973\r
974 return EFI_SUCCESS;\r
975}\r
976\r
977\r
978/**\r
979 Destroy an IP_IO instance.\r
980\r
981 @param IpIo Pointer to the IP_IO instance that needs to\r
982 destroy.\r
983\r
984 @retval EFI_SUCCESS The IP_IO instance destroyed successfully.\r
985 @retval other Error condition occurred.\r
986\r
987**/\r
988EFI_STATUS\r
7b414b4e 989EFIAPI\r
cbf316f2 990IpIoDestroy (\r
991 IN IP_IO *IpIo\r
992 )\r
993{\r
994 //\r
995 // Stop the IpIo.\r
996 //\r
997 IpIoStop (IpIo);\r
998\r
999 //\r
1000 // Close the IP protocol and destroy the child.\r
1001 //\r
1002 IpIoCloseProtocolDestroyIpChild (IpIo->Controller, IpIo->Image, IpIo->ChildHandle);\r
1003\r
e48e37fc 1004 gBS->FreePool (IpIo);\r
cbf316f2 1005\r
1006 return EFI_SUCCESS;\r
1007}\r
1008\r
1009\r
1010/**\r
1011 Send out an IP packet.\r
1012\r
1013 @param IpIo Pointer to an IP_IO instance used for sending IP\r
1014 packet.\r
1015 @param Pkt Pointer to the IP packet to be sent.\r
1016 @param Sender The IP protocol instance used for sending.\r
1017 @param NotifyData\r
1018 @param Dest The destination IP address to send this packet to.\r
1019 @param OverrideData The data to override some configuration of the IP\r
1020 instance used for sending.\r
1021\r
1022 @retval EFI_SUCCESS The operation is completed successfully.\r
1023 @retval EFI_NOT_STARTED The IpIo is not configured.\r
1024 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.\r
1025\r
1026**/\r
1027EFI_STATUS\r
7b414b4e 1028EFIAPI\r
cbf316f2 1029IpIoSend (\r
1030 IN IP_IO *IpIo,\r
1031 IN NET_BUF *Pkt,\r
1032 IN IP_IO_IP_INFO *Sender,\r
1033 IN VOID *Context OPTIONAL,\r
1034 IN VOID *NotifyData OPTIONAL,\r
1035 IN IP4_ADDR Dest,\r
1036 IN IP_IO_OVERRIDE *OverrideData\r
1037 )\r
1038{\r
1039 EFI_STATUS Status;\r
1040 EFI_IP4_PROTOCOL *Ip;\r
1041 IP_IO_SEND_ENTRY *SndEntry;\r
1042\r
1043 if (!IpIo->IsConfigured) {\r
1044 return EFI_NOT_STARTED;\r
1045 }\r
1046\r
1047 Ip = (NULL == Sender) ? IpIo->Ip : Sender->Ip;\r
1048\r
1049 //\r
1050 // create a new SndEntry\r
1051 //\r
1052 SndEntry = IpIoCreateSndEntry (IpIo, Pkt, Ip, Context, NotifyData, Dest, OverrideData);\r
1053 if (NULL == SndEntry) {\r
1054 return EFI_OUT_OF_RESOURCES;\r
1055 }\r
1056\r
1057 //\r
1058 // Send this Packet\r
1059 //\r
1060 Status = Ip->Transmit (Ip, SndEntry->SndToken);\r
1061 if (EFI_ERROR (Status)) {\r
1062 IpIoDestroySndEntry (SndEntry);\r
1063 }\r
1064\r
1065 return Status;\r
1066}\r
1067\r
1068\r
1069/**\r
1070 Cancel the IP transmit token which wraps this Packet.\r
1071\r
1072 @param IpIo Pointer to the IP_IO instance.\r
1073 @param Packet Pointer to the packet to cancel.\r
1074\r
1075 @return N/A.\r
1076\r
1077**/\r
1078VOID\r
7b414b4e 1079EFIAPI\r
cbf316f2 1080IpIoCancelTxToken (\r
1081 IN IP_IO *IpIo,\r
1082 IN VOID *Packet\r
1083 )\r
1084{\r
e48e37fc 1085 LIST_ENTRY *Node;\r
cbf316f2 1086 IP_IO_SEND_ENTRY *SndEntry;\r
1087 EFI_IP4_PROTOCOL *Ip;\r
1088\r
1089 ASSERT (IpIo && Packet);\r
1090\r
1091 NET_LIST_FOR_EACH (Node, &IpIo->PendingSndList) {\r
1092\r
1093 SndEntry = NET_LIST_USER_STRUCT (Node, IP_IO_SEND_ENTRY, Entry);\r
1094\r
1095 if (SndEntry->Pkt == Packet) {\r
1096\r
1097 Ip = SndEntry->Ip;\r
1098 Ip->Cancel (Ip, SndEntry->SndToken);\r
1099\r
cbf316f2 1100 break;\r
1101 }\r
1102 }\r
1103\r
1104}\r
1105\r
1106\r
1107/**\r
1108 Add a new IP instance for sending data.\r
1109\r
1110 @param IpIo Pointer to a IP_IO instance to add a new IP\r
1111 instance for sending purpose.\r
1112\r
1113 @return Pointer to the created IP_IO_IP_INFO structure, NULL is failed.\r
1114\r
1115**/\r
1116IP_IO_IP_INFO *\r
7b414b4e 1117EFIAPI\r
cbf316f2 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
e48e37fc 1127 IpInfo = AllocatePool (sizeof (IP_IO_IP_INFO));\r
cbf316f2 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
e48e37fc 1136 InitializeListHead (&IpInfo->Entry);\r
cbf316f2 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
e48e37fc 1160 TPL_NOTIFY,\r
cbf316f2 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
e48e37fc 1172 InsertTailList (&IpIo->IpList, &IpInfo->Entry);\r
cbf316f2 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
e48e37fc 1186 gBS->FreePool (IpInfo);\r
cbf316f2 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
7b414b4e 1208EFIAPI\r
cbf316f2 1209IpIoConfigIp (\r
1210 IN IP_IO_IP_INFO *IpInfo,\r
1211 IN OUT EFI_IP4_CONFIG_DATA *Ip4ConfigData OPTIONAL\r
1212 )\r
1213{\r
1214 EFI_STATUS Status;\r
1215 EFI_IP4_PROTOCOL *Ip;\r
1216 EFI_IP4_MODE_DATA Ip4ModeData;\r
1217\r
1218 ASSERT (IpInfo);\r
1219\r
1220 if (IpInfo->RefCnt > 1) {\r
1221 //\r
1222 // This IP instance is shared, don't reconfigure it until it has only one\r
1223 // consumer. Currently, only the tcp children cloned from their passive parent\r
1224 // will share the same IP. So this cases only happens while Ip4ConfigData is NULL,\r
1225 // let the last consumer clean the IP instance.\r
1226 //\r
1227 return EFI_SUCCESS;\r
1228 }\r
1229\r
1230 Ip = IpInfo->Ip;\r
1231\r
1232 Status = Ip->Configure (Ip, Ip4ConfigData);\r
1233 if (EFI_ERROR (Status)) {\r
1234 goto OnExit;\r
1235 }\r
1236\r
1237 if (Ip4ConfigData != NULL) {\r
1238\r
1239 if (Ip4ConfigData->UseDefaultAddress) {\r
1240 Ip->GetModeData (Ip, &Ip4ModeData, NULL, NULL);\r
1241\r
1242 Ip4ConfigData->StationAddress = Ip4ModeData.ConfigData.StationAddress;\r
1243 Ip4ConfigData->SubnetMask = Ip4ModeData.ConfigData.SubnetMask;\r
1244 }\r
1245\r
e48e37fc 1246 CopyMem (&IpInfo->Addr, &Ip4ConfigData->StationAddress, sizeof (IP4_ADDR));\r
1247 CopyMem (&IpInfo->SubnetMask, &Ip4ConfigData->SubnetMask, sizeof (IP4_ADDR));\r
cbf316f2 1248\r
1249 Status = Ip->Receive (Ip, &IpInfo->DummyRcvToken);\r
1250 if (EFI_ERROR (Status)) {\r
1251 Ip->Configure (Ip, NULL);\r
1252 }\r
1253 } else {\r
1254\r
1255 //\r
1256 // The IP instance is reseted, set the stored Addr and SubnetMask to zero.\r
1257 //\r
1258 IpInfo->Addr = 0;\r
1259 IpInfo->SubnetMask =0;\r
1260 }\r
1261\r
1262OnExit:\r
1263\r
1264 return Status;\r
1265}\r
1266\r
1267\r
1268/**\r
1269 Destroy an IP instance maintained in IpIo->IpList for\r
1270 sending purpose.\r
1271\r
1272 @param IpIo Pointer to the IP_IO instance.\r
1273 @param IpInfo Pointer to the IpInfo to be removed.\r
1274\r
1275 @return None.\r
1276\r
1277**/\r
1278VOID\r
7b414b4e 1279EFIAPI\r
cbf316f2 1280IpIoRemoveIp (\r
1281 IN IP_IO *IpIo,\r
1282 IN IP_IO_IP_INFO *IpInfo\r
1283 )\r
1284{\r
1285 ASSERT (IpInfo->RefCnt > 0);\r
1286\r
1287 NET_PUT_REF (IpInfo);\r
1288\r
1289 if (IpInfo->RefCnt > 0) {\r
1290\r
1291 return;\r
1292 }\r
1293\r
e48e37fc 1294 RemoveEntryList (&IpInfo->Entry);\r
cbf316f2 1295\r
1296 IpInfo->Ip->Configure (IpInfo->Ip, NULL);\r
1297\r
1298 IpIoCloseProtocolDestroyIpChild (IpIo->Controller, IpIo->Image, IpInfo->ChildHandle);\r
1299\r
1300 gBS->CloseEvent (IpInfo->DummyRcvToken.Event);\r
1301\r
e48e37fc 1302 gBS->FreePool (IpInfo);\r
cbf316f2 1303}\r
1304\r
1305\r
1306/**\r
1307 Find the first IP protocol maintained in IpIo whose local\r
1308 address is the same with Src.\r
1309\r
1310 @param IpIo Pointer to the pointer of the IP_IO instance.\r
1311 @param Src The local IP address.\r
1312\r
1313 @return Pointer to the IP protocol can be used for sending purpose and its local\r
1314 @return address is the same with Src.\r
1315\r
1316**/\r
1317IP_IO_IP_INFO *\r
7b414b4e 1318EFIAPI\r
cbf316f2 1319IpIoFindSender (\r
1320 IN OUT IP_IO **IpIo,\r
1321 IN IP4_ADDR Src\r
1322 )\r
1323{\r
e48e37fc 1324 LIST_ENTRY *IpIoEntry;\r
cbf316f2 1325 IP_IO *IpIoPtr;\r
e48e37fc 1326 LIST_ENTRY *IpInfoEntry;\r
cbf316f2 1327 IP_IO_IP_INFO *IpInfo;\r
1328\r
1329 NET_LIST_FOR_EACH (IpIoEntry, &mActiveIpIoList) {\r
1330 IpIoPtr = NET_LIST_USER_STRUCT (IpIoEntry, IP_IO, Entry);\r
1331\r
1332 if ((*IpIo != NULL) && (*IpIo != IpIoPtr)) {\r
1333 continue;\r
1334 }\r
1335\r
1336 NET_LIST_FOR_EACH (IpInfoEntry, &IpIoPtr->IpList) {\r
1337 IpInfo = NET_LIST_USER_STRUCT (IpInfoEntry, IP_IO_IP_INFO, Entry);\r
1338\r
1339 if (IpInfo->Addr == Src) {\r
1340 *IpIo = IpIoPtr;\r
1341 return IpInfo;\r
1342 }\r
1343 }\r
1344 }\r
1345\r
1346 //\r
1347 // No match.\r
1348 //\r
1349 return NULL;\r
1350}\r
1351\r
1352\r
1353/**\r
1354 Get the ICMP error map information, the ErrorStatus will be returned.\r
1355 The IsHard and Notify are optional. If they are not NULL, this rouine will\r
1356 fill them.\r
1357 We move IcmpErrMap[] to local variable to enable EBC build.\r
1358\r
1359 @param IcmpError IcmpError Type\r
1360 @param IsHard Whether it is a hard error\r
1361 @param Notify Whether it need to notify SockError\r
1362\r
1363 @return ICMP Error Status\r
1364\r
1365**/\r
1366EFI_STATUS\r
7b414b4e 1367EFIAPI\r
cbf316f2 1368IpIoGetIcmpErrStatus (\r
1369 IN ICMP_ERROR IcmpError,\r
1370 OUT BOOLEAN *IsHard, OPTIONAL\r
1371 OUT BOOLEAN *Notify OPTIONAL\r
1372 )\r
1373{\r
01750eb0 1374 ASSERT ((IcmpError >= ICMP_ERR_UNREACH_NET) && (IcmpError <= ICMP_ERR_PARAMPROB));\r
687a2e5f 1375\r
01750eb0 1376 if (IsHard != NULL) {\r
1377 *IsHard = mIcmpErrMap[IcmpError].IsHard;\r
1378 }\r
687a2e5f 1379\r
01750eb0 1380 if (Notify != NULL) {\r
1381 *Notify = mIcmpErrMap[IcmpError].Notify;\r
1382 }\r
687a2e5f 1383\r
01750eb0 1384 switch (IcmpError) {\r
1385 case ICMP_ERR_UNREACH_NET:\r
1386 return EFI_NETWORK_UNREACHABLE;\r
687a2e5f 1387\r
01750eb0 1388 case ICMP_ERR_TIMXCEED_INTRANS:\r
1389 case ICMP_ERR_TIMXCEED_REASS:\r
1390 case ICMP_ERR_UNREACH_HOST:\r
1391 return EFI_HOST_UNREACHABLE;\r
cbf316f2 1392\r
01750eb0 1393 case ICMP_ERR_UNREACH_PROTOCOL:\r
1394 return EFI_PROTOCOL_UNREACHABLE;\r
cbf316f2 1395\r
01750eb0 1396 case ICMP_ERR_UNREACH_PORT:\r
1397 return EFI_PORT_UNREACHABLE;\r
cbf316f2 1398\r
01750eb0 1399 case ICMP_ERR_MSGSIZE:\r
1400 case ICMP_ERR_UNREACH_SRCFAIL:\r
1401 case ICMP_ERR_QUENCH:\r
1402 case ICMP_ERR_PARAMPROB:\r
1403 return EFI_ICMP_ERROR;\r
cbf316f2 1404 }\r
1405\r
01750eb0 1406 //\r
1407 // will never run here!\r
1408 //\r
1409 ASSERT (FALSE);\r
1410 return EFI_UNSUPPORTED;\r
cbf316f2 1411}\r
1412\r