]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/TcpDxe/TcpDriver.c
Comment's added and fixed.
[mirror_edk2.git] / NetworkPkg / TcpDxe / TcpDriver.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 The driver binding and service binding protocol for the TCP driver.\r
3\r
76389e18 4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
a3bcde70
HT
5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php.\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "TcpMain.h"\r
17\r
18UINT16 mTcp4RandomPort;\r
19UINT16 mTcp6RandomPort;\r
20\r
21TCP_HEARTBEAT_TIMER mTcpTimer = {\r
22 NULL,\r
23 0\r
24};\r
25\r
26EFI_TCP4_PROTOCOL gTcp4ProtocolTemplate = {\r
27 Tcp4GetModeData,\r
28 Tcp4Configure,\r
29 Tcp4Routes,\r
30 Tcp4Connect,\r
31 Tcp4Accept,\r
32 Tcp4Transmit,\r
33 Tcp4Receive,\r
34 Tcp4Close,\r
35 Tcp4Cancel,\r
36 Tcp4Poll\r
37};\r
38\r
39EFI_TCP6_PROTOCOL gTcp6ProtocolTemplate = {\r
40 Tcp6GetModeData,\r
41 Tcp6Configure,\r
42 Tcp6Connect,\r
43 Tcp6Accept,\r
44 Tcp6Transmit,\r
45 Tcp6Receive,\r
46 Tcp6Close,\r
47 Tcp6Cancel,\r
48 Tcp6Poll\r
49};\r
50\r
51SOCK_INIT_DATA mTcpDefaultSockData = {\r
52 SockStream,\r
53 SO_CLOSED,\r
54 NULL,\r
55 TCP_BACKLOG,\r
56 TCP_SND_BUF_SIZE,\r
57 TCP_RCV_BUF_SIZE,\r
58 IP_VERSION_4,\r
59 NULL,\r
60 TcpCreateSocketCallback,\r
61 TcpDestroySocketCallback,\r
62 NULL,\r
63 NULL,\r
64 0,\r
65 TcpDispatcher,\r
66 NULL,\r
67};\r
68\r
69EFI_DRIVER_BINDING_PROTOCOL gTcpDriverBinding = {\r
70 TcpDriverBindingSupported,\r
71 TcpDriverBindingStart,\r
72 TcpDriverBindingStop,\r
73 0xa,\r
74 NULL,\r
75 NULL\r
76};\r
77\r
78EFI_SERVICE_BINDING_PROTOCOL gTcpServiceBinding = {\r
79 TcpServiceBindingCreateChild,\r
80 TcpServiceBindingDestroyChild\r
81};\r
82\r
83\r
84/**\r
85 Create and start the heartbeat timer for the TCP driver.\r
86\r
87 @retval EFI_SUCCESS The timer was successfully created and started.\r
88 @retval other The timer was not created.\r
89\r
90**/\r
91EFI_STATUS\r
92TcpCreateTimer (\r
93 VOID\r
94 )\r
95{\r
96 EFI_STATUS Status;\r
97\r
98 Status = EFI_SUCCESS;\r
99\r
100 if (mTcpTimer.RefCnt == 0) {\r
101\r
102 Status = gBS->CreateEvent (\r
103 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
104 TPL_NOTIFY,\r
105 TcpTicking,\r
106 NULL,\r
107 &mTcpTimer.TimerEvent\r
108 );\r
109 if (!EFI_ERROR (Status)) {\r
110\r
111 Status = gBS->SetTimer (\r
112 mTcpTimer.TimerEvent,\r
113 TimerPeriodic,\r
114 (UINT64) (TICKS_PER_SECOND / TCP_TICK_HZ)\r
115 );\r
116 }\r
117 }\r
118\r
119 if (!EFI_ERROR (Status)) {\r
120\r
121 mTcpTimer.RefCnt++;\r
122 }\r
123\r
124 return Status;\r
125}\r
126\r
127/**\r
128 Stop and destroy the heartbeat timer for TCP driver.\r
129\r
130**/\r
131VOID\r
132TcpDestroyTimer (\r
133 VOID\r
134 )\r
135{\r
136 ASSERT (mTcpTimer.RefCnt > 0);\r
137\r
138 mTcpTimer.RefCnt--;\r
139\r
140 if (mTcpTimer.RefCnt > 0) {\r
141 return;\r
142 }\r
143\r
144 gBS->SetTimer (mTcpTimer.TimerEvent, TimerCancel, 0);\r
145 gBS->CloseEvent (mTcpTimer.TimerEvent);\r
146 mTcpTimer.TimerEvent = NULL;\r
147}\r
148\r
149/**\r
150 The entry point for Tcp driver, which is used to install Tcp driver on the ImageHandle.\r
151\r
152 @param[in] ImageHandle The firmware allocated handle for this driver image.\r
153 @param[in] SystemTable Pointer to the EFI system table.\r
154\r
155 @retval EFI_SUCCESS The driver loaded.\r
156 @retval other The driver did not load.\r
157\r
158**/\r
159EFI_STATUS\r
160EFIAPI\r
161TcpDriverEntryPoint (\r
162 IN EFI_HANDLE ImageHandle,\r
163 IN EFI_SYSTEM_TABLE *SystemTable\r
164 )\r
165{\r
166 EFI_STATUS Status;\r
167 UINT32 Seed;\r
168\r
169 //\r
170 // Install the TCP Driver Binding Protocol\r
171 //\r
172 Status = EfiLibInstallDriverBindingComponentName2 (\r
173 ImageHandle,\r
174 SystemTable,\r
175 &gTcpDriverBinding,\r
176 ImageHandle,\r
177 &gTcpComponentName,\r
178 &gTcpComponentName2\r
179 );\r
180 if (EFI_ERROR (Status)) {\r
181 return Status;\r
182 }\r
183\r
184 //\r
185 // Initialize ISS and random port.\r
186 //\r
187 Seed = NetRandomInitSeed ();\r
188 mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;\r
189 mTcp4RandomPort = (UINT16) (TCP_PORT_KNOWN + (NET_RANDOM (Seed) % TCP_PORT_KNOWN));\r
190 mTcp6RandomPort = mTcp4RandomPort;\r
191\r
192 return EFI_SUCCESS;\r
193}\r
194\r
195/**\r
196 Create a new TCP4 or TCP6 driver service binding protocol\r
197\r
198 @param[in] Controller Controller handle of device to bind driver to.\r
76389e18 199 @param[in] Image The TCP driver's image handle.\r
a3bcde70
HT
200 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
201\r
202 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.\r
203 @retval EFI_SUCCESS A new IP6 service binding private was created.\r
204\r
205**/\r
206EFI_STATUS\r
207TcpCreateService (\r
208 IN EFI_HANDLE Controller,\r
209 IN EFI_HANDLE Image,\r
210 IN UINT8 IpVersion\r
211 )\r
212{\r
213 EFI_STATUS Status;\r
214 EFI_GUID *IpServiceBindingGuid;\r
215 EFI_GUID *TcpServiceBindingGuid;\r
216 TCP_SERVICE_DATA *TcpServiceData;\r
217 IP_IO_OPEN_DATA OpenData;\r
218\r
219 if (IpVersion == IP_VERSION_4) {\r
220 IpServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;\r
221 TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
222 } else {\r
223 IpServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid;\r
224 TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
225 }\r
226\r
227 Status = gBS->OpenProtocol (\r
228 Controller,\r
229 TcpServiceBindingGuid,\r
230 NULL,\r
231 Image,\r
232 Controller,\r
233 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
234 );\r
235 if (!EFI_ERROR (Status)) {\r
236 return EFI_ALREADY_STARTED;\r
237 }\r
238\r
239 Status = gBS->OpenProtocol (\r
240 Controller,\r
241 IpServiceBindingGuid,\r
242 NULL,\r
243 Image,\r
244 Controller,\r
245 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
246 );\r
247 if (EFI_ERROR (Status)) {\r
248 return EFI_UNSUPPORTED;\r
249 }\r
250\r
251 //\r
252 // Create the TCP service data.\r
253 //\r
254 TcpServiceData = AllocateZeroPool (sizeof (TCP_SERVICE_DATA));\r
255 if (TcpServiceData == NULL) {\r
256 return EFI_OUT_OF_RESOURCES;\r
257 }\r
258\r
259 TcpServiceData->Signature = TCP_DRIVER_SIGNATURE;\r
260 TcpServiceData->ControllerHandle = Controller;\r
261 TcpServiceData->DriverBindingHandle = Image;\r
262 TcpServiceData->IpVersion = IpVersion;\r
263 CopyMem (\r
264 &TcpServiceData->ServiceBinding,\r
265 &gTcpServiceBinding,\r
266 sizeof (EFI_SERVICE_BINDING_PROTOCOL)\r
267 );\r
268\r
269 TcpServiceData->IpIo = IpIoCreate (Image, Controller, IpVersion);\r
270 if (TcpServiceData->IpIo == NULL) {\r
271 Status = EFI_OUT_OF_RESOURCES;\r
272 goto ON_ERROR;\r
273 }\r
274\r
275\r
276 InitializeListHead (&TcpServiceData->SocketList);\r
277 ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));\r
278\r
279 if (IpVersion == IP_VERSION_4) {\r
280 CopyMem (\r
281 &OpenData.IpConfigData.Ip4CfgData,\r
282 &mIp4IoDefaultIpConfigData,\r
283 sizeof (EFI_IP4_CONFIG_DATA)\r
284 );\r
285 OpenData.IpConfigData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;\r
286 } else {\r
287 CopyMem (\r
288 &OpenData.IpConfigData.Ip6CfgData,\r
289 &mIp6IoDefaultIpConfigData,\r
290 sizeof (EFI_IP6_CONFIG_DATA)\r
291 );\r
292 OpenData.IpConfigData.Ip6CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;\r
293 }\r
294\r
295 OpenData.PktRcvdNotify = TcpRxCallback;\r
296 Status = IpIoOpen (TcpServiceData->IpIo, &OpenData);\r
297 if (EFI_ERROR (Status)) {\r
298 goto ON_ERROR;\r
299 }\r
300\r
301 Status = TcpCreateTimer ();\r
302 if (EFI_ERROR (Status)) {\r
303 goto ON_ERROR;\r
304 }\r
305\r
306 Status = gBS->InstallMultipleProtocolInterfaces (\r
307 &Controller,\r
308 TcpServiceBindingGuid,\r
309 &TcpServiceData->ServiceBinding,\r
310 NULL\r
311 );\r
312 if (EFI_ERROR (Status)) {\r
313 TcpDestroyTimer ();\r
314\r
315 goto ON_ERROR;\r
316 }\r
317\r
318 TcpSetVariableData (TcpServiceData);\r
319\r
320 return EFI_SUCCESS;\r
321\r
322ON_ERROR:\r
323\r
324 if (TcpServiceData->IpIo != NULL) {\r
325 IpIoDestroy (TcpServiceData->IpIo);\r
326 }\r
327\r
328 FreePool (TcpServiceData);\r
329\r
330 return Status;\r
331}\r
332\r
333/**\r
334 Destroy a TCP6 or TCP4 service binding instance. It will release all\r
335 the resources allocated by the instance.\r
336\r
337 @param[in] Controller Controller handle of device to bind driver to.\r
338 @param[in] ImageHandle The TCP driver's image handle.\r
339 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
340 of children is zero stop the entire bus driver.\r
341 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6\r
342\r
343 @retval EFI_SUCCESS The resources used by the instance were cleaned up.\r
344 @retval Others Failed to clean up some of the resources.\r
345\r
346**/\r
347EFI_STATUS\r
348TcpDestroyService (\r
349 IN EFI_HANDLE Controller,\r
350 IN EFI_HANDLE ImageHandle,\r
351 IN UINTN NumberOfChildren,\r
352 IN UINT8 IpVersion\r
353 )\r
354{\r
355 EFI_HANDLE NicHandle;\r
356 EFI_GUID *IpProtocolGuid;\r
357 EFI_GUID *ServiceBindingGuid;\r
358 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
359 TCP_SERVICE_DATA *TcpServiceData;\r
360 EFI_STATUS Status;\r
361 SOCKET *Sock;\r
362\r
363 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
364\r
365 if (IpVersion == IP_VERSION_4) {\r
366 IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
367 ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
368 } else {\r
369 IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
370 ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
371 }\r
372\r
373 NicHandle = NetLibGetNicHandle (Controller, IpProtocolGuid);\r
374 if (NicHandle == NULL) {\r
375 return EFI_NOT_FOUND;\r
376 }\r
377\r
378 Status = gBS->OpenProtocol (\r
379 NicHandle,\r
380 ServiceBindingGuid,\r
381 (VOID **) &ServiceBinding,\r
382 ImageHandle,\r
383 Controller,\r
384 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
385 );\r
386 if (EFI_ERROR (Status)) {\r
387 return EFI_DEVICE_ERROR;\r
388 }\r
389\r
390 TcpServiceData = TCP_SERVICE_FROM_THIS (ServiceBinding);\r
391\r
392 if (NumberOfChildren == 0) {\r
393 //\r
394 // Uninstall TCP servicebinding protocol\r
395 //\r
396 gBS->UninstallMultipleProtocolInterfaces (\r
397 NicHandle,\r
398 ServiceBindingGuid,\r
399 ServiceBinding,\r
400 NULL\r
401 );\r
402\r
403 //\r
404 // Destroy the IpIO consumed by TCP driver\r
405 //\r
406 IpIoDestroy (TcpServiceData->IpIo);\r
407\r
408 //\r
409 // Destroy the heartbeat timer.\r
410 //\r
411 TcpDestroyTimer ();\r
412\r
413 //\r
414 // Clear the variable.\r
415 //\r
416 TcpClearVariableData (TcpServiceData);\r
417\r
418 //\r
419 // Release the TCP service data\r
420 //\r
421 FreePool (TcpServiceData);\r
422 } else {\r
423\r
424 while (!IsListEmpty (&TcpServiceData->SocketList)) {\r
425 Sock = NET_LIST_HEAD (&TcpServiceData->SocketList, SOCKET, Link);\r
426\r
427 ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);\r
428 }\r
429 }\r
430\r
431 return EFI_SUCCESS;\r
432}\r
433\r
434/**\r
435 Test to see if this driver supports ControllerHandle.\r
436\r
437 @param[in] This Protocol instance pointer.\r
438 @param[in] ControllerHandle Handle of device to test.\r
439 @param[in] RemainingDevicePath Optional parameter use to pick a specific\r
440 child device to start.\r
441\r
442 @retval EFI_SUCCESS This driver supports this device.\r
443 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
444 @retval other This driver does not support this device.\r
445\r
446**/\r
447EFI_STATUS\r
448EFIAPI\r
449TcpDriverBindingSupported (\r
450 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
451 IN EFI_HANDLE ControllerHandle,\r
452 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
453 )\r
454{\r
455 EFI_STATUS Status;\r
456 BOOLEAN IsTcp4Started;\r
457\r
458 //\r
459 // Test for the Tcp4ServiceBinding Protocol\r
460 //\r
461 Status = gBS->OpenProtocol (\r
462 ControllerHandle,\r
463 &gEfiTcp4ServiceBindingProtocolGuid,\r
464 NULL,\r
465 This->DriverBindingHandle,\r
466 ControllerHandle,\r
467 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
468 );\r
469 if (EFI_ERROR (Status)) {\r
470 //\r
471 // Test for the Ip4ServiceBinding Protocol\r
472 //\r
473 Status = gBS->OpenProtocol (\r
474 ControllerHandle,\r
475 &gEfiIp4ServiceBindingProtocolGuid,\r
476 NULL,\r
477 This->DriverBindingHandle,\r
478 ControllerHandle,\r
479 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
480 );\r
481 if (!EFI_ERROR (Status)) {\r
482 return EFI_SUCCESS;\r
483 }\r
484\r
485 IsTcp4Started = FALSE;\r
486 } else {\r
487 IsTcp4Started = TRUE;\r
488 }\r
489\r
490 //\r
491 // Check the Tcp6ServiceBinding Protocol\r
492 //\r
493 Status = gBS->OpenProtocol (\r
494 ControllerHandle,\r
495 &gEfiTcp6ServiceBindingProtocolGuid,\r
496 NULL,\r
497 This->DriverBindingHandle,\r
498 ControllerHandle,\r
499 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
500 );\r
501 if (EFI_ERROR (Status)) {\r
502 //\r
503 // Test for the Ip6ServiceBinding Protocol\r
504 //\r
505 Status = gBS->OpenProtocol (\r
506 ControllerHandle,\r
507 &gEfiIp6ServiceBindingProtocolGuid,\r
508 NULL,\r
509 This->DriverBindingHandle,\r
510 ControllerHandle,\r
511 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
512 );\r
513 if (!EFI_ERROR (Status)) {\r
514 return EFI_SUCCESS;\r
515 }\r
516 } else if (IsTcp4Started) {\r
517 return EFI_ALREADY_STARTED;\r
518 }\r
519\r
520 return EFI_UNSUPPORTED;\r
521}\r
522\r
523/**\r
524 Start this driver on ControllerHandle.\r
525\r
526 @param[in] This Protocol instance pointer.\r
527 @param[in] ControllerHandle Handle of device to bind driver to.\r
528 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
529 device to start.\r
530\r
531 @retval EFI_SUCCESS The driver is added to ControllerHandle.\r
532 @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the\r
533 driver.\r
534 @retval other The driver cannot be added to ControllerHandle.\r
535\r
536**/\r
537EFI_STATUS\r
538EFIAPI\r
539TcpDriverBindingStart (\r
540 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
541 IN EFI_HANDLE ControllerHandle,\r
542 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
543 )\r
544{\r
545 EFI_STATUS Tcp4Status;\r
546 EFI_STATUS Tcp6Status;\r
547\r
548 Tcp4Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4);\r
549 if ((Tcp4Status == EFI_ALREADY_STARTED) || (Tcp4Status == EFI_UNSUPPORTED)) {\r
550 Tcp4Status = EFI_SUCCESS;\r
551 }\r
552\r
553 Tcp6Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6);\r
554 if ((Tcp6Status == EFI_ALREADY_STARTED) || (Tcp6Status == EFI_UNSUPPORTED)) {\r
555 Tcp6Status = EFI_SUCCESS;\r
556 }\r
557\r
558 if (!EFI_ERROR (Tcp4Status) || !EFI_ERROR (Tcp6Status)) {\r
559 return EFI_SUCCESS;\r
560 } else if (EFI_ERROR (Tcp4Status)) {\r
561 return Tcp4Status;\r
562 } else {\r
563 return Tcp6Status;\r
564 }\r
565}\r
566\r
567/**\r
568 Stop this driver on ControllerHandle.\r
569\r
570 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
571 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
572 support a bus specific I/O protocol for the driver\r
573 to use to stop the device.\r
574 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
575 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
576 if NumberOfChildren is 0.\r
577\r
578 @retval EFI_SUCCESS The device was stopped.\r
579 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
580\r
581**/\r
582EFI_STATUS\r
583EFIAPI\r
584TcpDriverBindingStop (\r
585 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
586 IN EFI_HANDLE ControllerHandle,\r
587 IN UINTN NumberOfChildren,\r
588 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
589 )\r
590{\r
591 EFI_STATUS Tcp4Status;\r
592 EFI_STATUS Tcp6Status;\r
593\r
594 Tcp4Status = TcpDestroyService (\r
595 ControllerHandle,\r
596 This->DriverBindingHandle,\r
597 NumberOfChildren,\r
598 IP_VERSION_4\r
599 );\r
600\r
601 Tcp6Status = TcpDestroyService (\r
602 ControllerHandle,\r
603 This->DriverBindingHandle,\r
604 NumberOfChildren,\r
605 IP_VERSION_6\r
606 );\r
607\r
608 if (EFI_ERROR (Tcp4Status) && EFI_ERROR (Tcp6Status)) {\r
609 return EFI_DEVICE_ERROR;\r
610 } else {\r
611 return EFI_SUCCESS;\r
612 }\r
613}\r
614\r
615/**\r
616 The Callback funtion called after the TCP socket was created.\r
617\r
618 @param[in] This Pointer to the socket just created\r
619 @param[in] Context Context of the socket\r
620\r
621 @retval EFI_SUCCESS This protocol installed successfully.\r
622 @retval other An error occured.\r
623\r
624**/\r
625EFI_STATUS\r
626TcpCreateSocketCallback (\r
627 IN SOCKET *This,\r
628 IN VOID *Context\r
629 )\r
630{\r
631 EFI_STATUS Status;\r
632 TCP_SERVICE_DATA *TcpServiceData;\r
633 EFI_GUID *IpProtocolGuid;\r
634 VOID *Ip;\r
635\r
636 if (This->IpVersion == IP_VERSION_4) {\r
637 IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
638 } else {\r
639 IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
640 }\r
641\r
642 TcpServiceData = ((TCP_PROTO_DATA *) This->ProtoReserved)->TcpService;\r
643\r
644 //\r
645 // Open the default IP protocol of IP_IO BY_DRIVER.\r
646 //\r
647 Status = gBS->OpenProtocol (\r
648 TcpServiceData->IpIo->ChildHandle,\r
649 IpProtocolGuid,\r
650 &Ip,\r
651 TcpServiceData->DriverBindingHandle,\r
652 This->SockHandle,\r
653 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
654 );\r
655 if (EFI_ERROR (Status)) {\r
656 return Status;\r
657 }\r
658\r
659 //\r
660 // Open the device path on the handle where service binding resides on.\r
661 //\r
662 Status = gBS->OpenProtocol (\r
663 TcpServiceData->ControllerHandle,\r
664 &gEfiDevicePathProtocolGuid,\r
665 (VOID **) &This->ParentDevicePath,\r
666 TcpServiceData->DriverBindingHandle,\r
667 This->SockHandle,\r
668 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
669 );\r
670 if (EFI_ERROR (Status)) {\r
671 gBS->CloseProtocol (\r
672 TcpServiceData->IpIo->ChildHandle,\r
673 IpProtocolGuid,\r
674 TcpServiceData->DriverBindingHandle,\r
675 This->SockHandle\r
676 );\r
677 } else {\r
678 //\r
679 // Insert this socket into the SocketList.\r
680 //\r
681 InsertTailList (&TcpServiceData->SocketList, &This->Link);\r
682 }\r
683\r
684 return Status;\r
685}\r
686\r
687/**\r
688 The callback function called before the TCP socket was to be destroyed.\r
689\r
690 @param[in] This The TCP socket to be destroyed.\r
691 @param[in] Context The context of the socket.\r
692\r
693**/\r
694VOID\r
695TcpDestroySocketCallback (\r
696 IN SOCKET *This,\r
697 IN VOID *Context\r
698 )\r
699{\r
700 TCP_SERVICE_DATA *TcpServiceData;\r
701 EFI_GUID *IpProtocolGuid;\r
702\r
703 if (This->IpVersion == IP_VERSION_4) {\r
704 IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
705 } else {\r
706 IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
707 }\r
708\r
709 TcpServiceData = ((TCP_PROTO_DATA *) This->ProtoReserved)->TcpService;\r
710\r
711 //\r
712 // Remove this node from the list.\r
713 //\r
714 RemoveEntryList (&This->Link);\r
715\r
716 //\r
717 // Close the device path protocol\r
718 //\r
719 gBS->CloseProtocol (\r
720 TcpServiceData->ControllerHandle,\r
721 &gEfiDevicePathProtocolGuid,\r
722 TcpServiceData->DriverBindingHandle,\r
723 This->SockHandle\r
724 );\r
725\r
726 //\r
727 // Close the IP protocol.\r
728 //\r
729 gBS->CloseProtocol (\r
730 TcpServiceData->IpIo->ChildHandle,\r
731 IpProtocolGuid,\r
732 TcpServiceData->DriverBindingHandle,\r
733 This->SockHandle\r
734 );\r
735}\r
736\r
737/**\r
738 Creates a child handle with a set of TCP services.\r
739\r
740 The CreateChild() function installs a protocol on ChildHandle.\r
741 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.\r
742 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
743\r
744 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
745 @param[in, out] ChildHandle Pointer to the handle of the child to create.\r
746 If it is NULL, then a new handle is created.\r
747 If it is a pointer to an existing UEFI handle,\r
748 then the protocol is added to the existing UEFI handle.\r
749\r
750 @retval EFI_SUCCES The protocol was added to ChildHandle.\r
751 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
752 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
753 the child.\r
754 @retval other The child handle was not created.\r
755\r
756**/\r
757EFI_STATUS\r
758EFIAPI\r
759TcpServiceBindingCreateChild (\r
760 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
761 IN OUT EFI_HANDLE *ChildHandle\r
762 )\r
763{\r
764 SOCKET *Sock;\r
765 TCP_SERVICE_DATA *TcpServiceData;\r
766 TCP_PROTO_DATA TcpProto;\r
767 EFI_STATUS Status;\r
768 EFI_TPL OldTpl;\r
769\r
770 if (NULL == This || NULL == ChildHandle) {\r
771 return EFI_INVALID_PARAMETER;\r
772 }\r
773\r
774 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
775\r
776 Status = EFI_SUCCESS;\r
777 TcpServiceData = TCP_SERVICE_FROM_THIS (This);\r
778 TcpProto.TcpService = TcpServiceData;\r
779 TcpProto.TcpPcb = NULL;\r
780\r
781 //\r
782 // Create a tcp instance with defualt Tcp default\r
783 // sock init data and TcpProto\r
784 //\r
785 mTcpDefaultSockData.ProtoData = &TcpProto;\r
786 mTcpDefaultSockData.DataSize = sizeof (TCP_PROTO_DATA);\r
787 mTcpDefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;\r
788 mTcpDefaultSockData.IpVersion = TcpServiceData->IpVersion;\r
789\r
790 if (TcpServiceData->IpVersion == IP_VERSION_4) {\r
791 mTcpDefaultSockData.Protocol = &gTcp4ProtocolTemplate;\r
792 } else {\r
793 mTcpDefaultSockData.Protocol = &gTcp6ProtocolTemplate;\r
794 }\r
795\r
796 Sock = SockCreateChild (&mTcpDefaultSockData);\r
797 if (NULL == Sock) {\r
798 DEBUG (\r
799 (EFI_D_ERROR,\r
800 "TcpDriverBindingCreateChild: No resource to create a Tcp Child\n")\r
801 );\r
802\r
803 Status = EFI_OUT_OF_RESOURCES;\r
804 } else {\r
805 *ChildHandle = Sock->SockHandle;\r
806 }\r
807\r
808 mTcpDefaultSockData.ProtoData = NULL;\r
809\r
810 gBS->RestoreTPL (OldTpl);\r
811 return Status;\r
812}\r
813\r
814/**\r
815 Destroys a child handle with a set of TCP services.\r
816\r
817 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol\r
818 that was installed by CreateChild() from ChildHandle. If the removed protocol is the\r
819 last protocol on ChildHandle, then ChildHandle is destroyed.\r
820\r
821 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
822 @param ChildHandle Handle of the child to be destroyed.\r
823\r
824 @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
825 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.\r
826 @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.\r
827 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
828 because its services are being used.\r
829 @retval other The child handle was not destroyed.\r
830\r
831**/\r
832EFI_STATUS\r
833EFIAPI\r
834TcpServiceBindingDestroyChild (\r
835 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
836 IN EFI_HANDLE ChildHandle\r
837 )\r
838{\r
839 EFI_STATUS Status;\r
840 VOID *Tcp;\r
841 SOCKET *Sock;\r
842 EFI_TPL OldTpl;\r
843\r
844 if (NULL == This || NULL == ChildHandle) {\r
845 return EFI_INVALID_PARAMETER;\r
846 }\r
847\r
848 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
849\r
850 //\r
851 // retrieve the Tcp4 protocol from ChildHandle\r
852 //\r
853 Status = gBS->OpenProtocol (\r
854 ChildHandle,\r
855 &gEfiTcp4ProtocolGuid,\r
856 &Tcp,\r
857 gTcpDriverBinding.DriverBindingHandle,\r
858 ChildHandle,\r
859 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
860 );\r
861 if (EFI_ERROR (Status)) {\r
862 //\r
863 // No Tcp4, try the Tcp6 protocol\r
864 //\r
865 Status = gBS->OpenProtocol (\r
866 ChildHandle,\r
867 &gEfiTcp6ProtocolGuid,\r
868 &Tcp,\r
869 gTcpDriverBinding.DriverBindingHandle,\r
870 ChildHandle,\r
871 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
872 );\r
873 if (EFI_ERROR (Status)) {\r
874 Status = EFI_UNSUPPORTED;\r
875 }\r
876 }\r
877\r
878 if (!EFI_ERROR (Status)) {\r
879 //\r
880 // destroy this sock and related Tcp protocol control\r
881 // block\r
882 //\r
883 Sock = SOCK_FROM_THIS (Tcp);\r
884\r
885 SockDestroyChild (Sock);\r
886 }\r
887\r
888 gBS->RestoreTPL (OldTpl);\r
889\r
890 return Status;\r
891}\r