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