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