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