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