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