]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.c
1. Add EFI_COMPONENT_NAME2_PROTOCOL.GetControllerName() support.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Driver.c
1 /** @file
2 Tcp driver function.
3
4 Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php<BR>
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Tcp4Main.h"
16
17
18 UINT16 mTcp4RandomPort;
19 extern EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName;
20 extern EFI_COMPONENT_NAME2_PROTOCOL gTcp4ComponentName2;
21 extern EFI_UNICODE_STRING_TABLE *gTcpControllerNameTable;
22
23 TCP4_HEARTBEAT_TIMER mTcp4Timer = {
24 NULL,
25 0
26 };
27
28 EFI_TCP4_PROTOCOL mTcp4ProtocolTemplate = {
29 Tcp4GetModeData,
30 Tcp4Configure,
31 Tcp4Routes,
32 Tcp4Connect,
33 Tcp4Accept,
34 Tcp4Transmit,
35 Tcp4Receive,
36 Tcp4Close,
37 Tcp4Cancel,
38 Tcp4Poll
39 };
40
41 SOCK_INIT_DATA mTcp4DefaultSockData = {
42 SockStream,
43 0,
44 NULL,
45 TCP_BACKLOG,
46 TCP_SND_BUF_SIZE,
47 TCP_RCV_BUF_SIZE,
48 &mTcp4ProtocolTemplate,
49 Tcp4CreateSocketCallback,
50 Tcp4DestroySocketCallback,
51 NULL,
52 NULL,
53 0,
54 Tcp4Dispatcher,
55 NULL,
56 };
57
58 EFI_DRIVER_BINDING_PROTOCOL mTcp4DriverBinding = {
59 Tcp4DriverBindingSupported,
60 Tcp4DriverBindingStart,
61 Tcp4DriverBindingStop,
62 0xa,
63 NULL,
64 NULL
65 };
66
67 EFI_SERVICE_BINDING_PROTOCOL mTcp4ServiceBinding = {
68 Tcp4ServiceBindingCreateChild,
69 Tcp4ServiceBindingDestroyChild
70 };
71
72
73 /**
74 Create and start the heartbeat timer for TCP driver.
75
76 @retval EFI_SUCCESS The timer is successfully created and started.
77 @retval other The timer is not created.
78
79 **/
80 EFI_STATUS
81 Tcp4CreateTimer (
82 VOID
83 )
84 {
85 EFI_STATUS Status;
86
87 Status = EFI_SUCCESS;
88
89 if (mTcp4Timer.RefCnt == 0) {
90
91 Status = gBS->CreateEvent (
92 EVT_TIMER | EVT_NOTIFY_SIGNAL,
93 TPL_NOTIFY,
94 TcpTicking,
95 NULL,
96 &mTcp4Timer.TimerEvent
97 );
98 if (!EFI_ERROR (Status)) {
99
100 Status = gBS->SetTimer (
101 mTcp4Timer.TimerEvent,
102 TimerPeriodic,
103 (UINT64) (TICKS_PER_SECOND / TCP_TICK_HZ)
104 );
105 }
106 }
107
108 if (!EFI_ERROR (Status)) {
109
110 mTcp4Timer.RefCnt++;
111 }
112
113 return Status;
114 }
115
116
117 /**
118 Stop and destroy the heartbeat timer for TCP driver.
119
120 **/
121 VOID
122 Tcp4DestroyTimer (
123 VOID
124 )
125 {
126 ASSERT (mTcp4Timer.RefCnt > 0);
127
128 mTcp4Timer.RefCnt--;
129
130 if (mTcp4Timer.RefCnt > 0) {
131 return;
132 }
133
134 gBS->SetTimer (mTcp4Timer.TimerEvent, TimerCancel, 0);
135 gBS->CloseEvent (mTcp4Timer.TimerEvent);
136 mTcp4Timer.TimerEvent = NULL;
137 }
138
139 /**
140 Callback function which provided by user to remove one node in NetDestroyLinkList process.
141
142 @param[in] Entry The entry to be removed.
143 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
144
145 @retval EFI_SUCCESS The entry has been removed successfully.
146 @retval Others Fail to remove the entry.
147
148 **/
149 EFI_STATUS
150 Tcp4DestroyChildEntryInHandleBuffer (
151 IN LIST_ENTRY *Entry,
152 IN VOID *Context
153 )
154 {
155 SOCKET *Sock;
156 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
157 UINTN NumberOfChildren;
158 EFI_HANDLE *ChildHandleBuffer;
159
160 if (Entry == NULL || Context == NULL) {
161 return EFI_INVALID_PARAMETER;
162 }
163
164 Sock = NET_LIST_USER_STRUCT_S (Entry, SOCKET, Link, SOCK_SIGNATURE);
165 ServiceBinding = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;
166 NumberOfChildren = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;
167 ChildHandleBuffer = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;
168
169 if (!NetIsInHandleBuffer (Sock->SockHandle, NumberOfChildren, ChildHandleBuffer)) {
170 return EFI_SUCCESS;
171 }
172
173 return ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);
174 }
175
176 /**
177 The entry point for Tcp4 driver, used to install Tcp4 driver on the ImageHandle.
178
179 @param ImageHandle The firmware allocated handle for this
180 driver image.
181 @param SystemTable Pointer to the EFI system table.
182
183 @retval EFI_SUCCESS Driver loaded.
184 @retval other Driver not loaded.
185
186 **/
187 EFI_STATUS
188 EFIAPI
189 Tcp4DriverEntryPoint (
190 IN EFI_HANDLE ImageHandle,
191 IN EFI_SYSTEM_TABLE *SystemTable
192 )
193 {
194 EFI_STATUS Status;
195 UINT32 Seed;
196
197 //
198 // Install the TCP4 Driver Binding Protocol
199 //
200 Status = EfiLibInstallDriverBindingComponentName2 (
201 ImageHandle,
202 SystemTable,
203 &mTcp4DriverBinding,
204 ImageHandle,
205 &gTcp4ComponentName,
206 &gTcp4ComponentName2
207 );
208 ASSERT_EFI_ERROR (Status);
209 //
210 // Initialize ISS and random port.
211 //
212 Seed = NetRandomInitSeed ();
213 mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;
214 mTcp4RandomPort = (UINT16) (TCP4_PORT_KNOWN +
215 (UINT16) (NET_RANDOM(Seed) % TCP4_PORT_KNOWN));
216
217 return Status;
218 }
219
220
221 /**
222 Tests to see if this driver supports a given controller.
223
224 If a child device is provided, it further tests to see if this driver supports
225 creating a handle for the specified child device.
226
227 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
228 @param ControllerHandle The handle of the controller to test. This handle
229 must support a protocol interface that supplies
230 an I/O abstraction to the driver.
231 @param RemainingDevicePath A pointer to the remaining portion of a device path.
232 This parameter is ignored by device drivers, and is optional for bus drivers.
233
234
235 @retval EFI_SUCCESS The device specified by ControllerHandle and
236 RemainingDevicePath is supported by the driver
237 specified by This.
238 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
239 RemainingDevicePath is already being managed by
240 the driver specified by This.
241 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
242 RemainingDevicePath is already being managed by a
243 different driver or an application that requires
244 exclusive access.
245 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
246 RemainingDevicePath is not supported by the driver
247 specified by This.
248
249 **/
250 EFI_STATUS
251 EFIAPI
252 Tcp4DriverBindingSupported (
253 IN EFI_DRIVER_BINDING_PROTOCOL *This,
254 IN EFI_HANDLE ControllerHandle,
255 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
256 )
257 {
258 EFI_STATUS Status;
259
260 //
261 // Test for the Tcp4ServiceBinding Protocol
262 //
263 Status = gBS->OpenProtocol (
264 ControllerHandle,
265 &gEfiTcp4ServiceBindingProtocolGuid,
266 NULL,
267 This->DriverBindingHandle,
268 ControllerHandle,
269 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
270 );
271 if (!EFI_ERROR (Status)) {
272 return EFI_ALREADY_STARTED;
273 }
274
275 //
276 // Test for the Ip4 Protocol
277 //
278 Status = gBS->OpenProtocol (
279 ControllerHandle,
280 &gEfiIp4ServiceBindingProtocolGuid,
281 NULL,
282 This->DriverBindingHandle,
283 ControllerHandle,
284 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
285 );
286
287 return Status;
288 }
289
290
291 /**
292 Start this driver on ControllerHandle.
293
294 The Start() function is designed to be invoked from the EFI boot service
295 ConnectController(). As a result, much of the error checking on the parameters
296 to Start() has been moved into this common boot service. It is legal to call
297 Start() from other locations, but the following calling restrictions must be
298 followed or the system behavior will not be deterministic.
299 1. ControllerHandle must be a valid EFI_HANDLE.
300 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally
301 aligned EFI_DEVICE_PATH_PROTOCOL.
302 3. Prior to calling Start(), the Supported() function for the driver specified
303 by This must have been called with the same calling parameters, and Supported()
304 must have returned EFI_SUCCESS.
305
306 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
307 @param ControllerHandle The handle of the controller to start. This handle
308 must support a protocol interface that supplies
309 an I/O abstraction to the driver.
310 @param RemainingDevicePath A pointer to the remaining portion of a device path.
311 This parameter is ignored by device drivers, and is
312 optional for bus drivers.
313
314 @retval EFI_SUCCESS The device was started.
315 @retval EFI_ALREADY_STARTED The device could not be started due to a device error.
316 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
317 of resources.
318
319 **/
320 EFI_STATUS
321 EFIAPI
322 Tcp4DriverBindingStart (
323 IN EFI_DRIVER_BINDING_PROTOCOL *This,
324 IN EFI_HANDLE ControllerHandle,
325 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
326 )
327 {
328 EFI_STATUS Status;
329 TCP4_SERVICE_DATA *TcpServiceData;
330 IP_IO_OPEN_DATA OpenData;
331
332 TcpServiceData = AllocateZeroPool (sizeof (TCP4_SERVICE_DATA));
333
334 if (NULL == TcpServiceData) {
335 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Have no enough"
336 " resource to create a Tcp Servcie Data\n"));
337
338 return EFI_OUT_OF_RESOURCES;
339 }
340
341 //
342 // Create a new IP IO to Consume it
343 //
344 TcpServiceData->IpIo = IpIoCreate (
345 This->DriverBindingHandle,
346 ControllerHandle,
347 IP_VERSION_4
348 );
349 if (NULL == TcpServiceData->IpIo) {
350
351 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Have no enough"
352 " resource to create an Ip Io\n"));
353
354 Status = EFI_OUT_OF_RESOURCES;
355 goto ON_ERROR;
356 }
357
358 //
359 // Configure and start IpIo.
360 //
361 ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));
362
363 CopyMem (
364 &OpenData.IpConfigData.Ip4CfgData,
365 &mIp4IoDefaultIpConfigData,
366 sizeof (EFI_IP4_CONFIG_DATA)
367 );
368
369 OpenData.IpConfigData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
370
371 OpenData.PktRcvdNotify = Tcp4RxCallback;
372 Status = IpIoOpen (TcpServiceData->IpIo, &OpenData);
373
374 if (EFI_ERROR (Status)) {
375 goto ON_ERROR;
376 }
377
378 //
379 // Create the timer event used by TCP driver
380 //
381 Status = Tcp4CreateTimer ();
382 if (EFI_ERROR (Status)) {
383
384 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Create TcpTimer"
385 " Event failed with %r\n", Status));
386
387 goto ON_ERROR;
388 }
389
390 //
391 // Install the Tcp4ServiceBinding Protocol on the
392 // controller handle
393 //
394 TcpServiceData->Tcp4ServiceBinding = mTcp4ServiceBinding;
395
396 Status = gBS->InstallMultipleProtocolInterfaces (
397 &ControllerHandle,
398 &gEfiTcp4ServiceBindingProtocolGuid,
399 &TcpServiceData->Tcp4ServiceBinding,
400 NULL
401 );
402 if (EFI_ERROR (Status)) {
403
404 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Install Tcp4 Service Binding"
405 " Protocol failed for %r\n", Status));
406
407 Tcp4DestroyTimer ();
408 goto ON_ERROR;
409 }
410
411 //
412 // Initialize member in TcpServiceData
413 //
414 TcpServiceData->ControllerHandle = ControllerHandle;
415 TcpServiceData->Signature = TCP4_DRIVER_SIGNATURE;
416 TcpServiceData->DriverBindingHandle = This->DriverBindingHandle;
417
418 InitializeListHead (&TcpServiceData->SocketList);
419
420 TcpSetVariableData (TcpServiceData);
421
422 return EFI_SUCCESS;
423
424 ON_ERROR:
425
426 if (TcpServiceData->IpIo != NULL) {
427 IpIoDestroy (TcpServiceData->IpIo);
428 TcpServiceData->IpIo = NULL;
429 }
430
431 FreePool (TcpServiceData);
432
433 return Status;
434 }
435
436
437 /**
438 Stop this driver on ControllerHandle.
439
440 The Stop() function is designed to be invoked from the EFI boot service
441 DisconnectController(). As a result, much of the error checking on the parameters
442 to Stop() has been moved into this common boot service. It is legal to call Stop()
443 from other locations, but the following calling restrictions must be followed
444 or the system behavior will not be deterministic.
445 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call
446 to this same driver's Start() function.
447 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
448 EFI_HANDLE. In addition, all of these handles must have been created in this
449 driver's Start() function, and the Start() function must have called OpenProtocol()
450 on ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
451
452 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
453 @param ControllerHandle A handle to the device being stopped. The handle must
454 support a bus specific I/O protocol for the driver
455 to use to stop the device.
456 @param NumberOfChildren The number of child device handles in ChildHandleBuffer.
457 @param ChildHandleBuffer An array of child handles to be freed. May be NULL if
458 NumberOfChildren is 0.
459
460 @retval EFI_SUCCESS The device was stopped.
461 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
462
463 **/
464 EFI_STATUS
465 EFIAPI
466 Tcp4DriverBindingStop (
467 IN EFI_DRIVER_BINDING_PROTOCOL *This,
468 IN EFI_HANDLE ControllerHandle,
469 IN UINTN NumberOfChildren,
470 IN EFI_HANDLE *ChildHandleBuffer
471 )
472 {
473 EFI_STATUS Status;
474 EFI_HANDLE NicHandle;
475 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
476 TCP4_SERVICE_DATA *TcpServiceData;
477 LIST_ENTRY *List;
478 TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
479
480 // Find the NicHandle where Tcp4 ServiceBinding Protocol is installed.
481 //
482 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
483 if (NicHandle == NULL) {
484 return EFI_SUCCESS;
485 }
486
487 //
488 // Retrieve the TCP driver Data Structure
489 //
490 Status = gBS->OpenProtocol (
491 NicHandle,
492 &gEfiTcp4ServiceBindingProtocolGuid,
493 (VOID **) &ServiceBinding,
494 This->DriverBindingHandle,
495 ControllerHandle,
496 EFI_OPEN_PROTOCOL_GET_PROTOCOL
497 );
498 if (EFI_ERROR (Status)) {
499
500 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStop: Locate Tcp4 Service "
501 " Binding Protocol failed with %r\n", Status));
502
503 return EFI_DEVICE_ERROR;
504 }
505
506 TcpServiceData = TCP4_FROM_THIS (ServiceBinding);
507
508 if (NumberOfChildren != 0) {
509 List = &TcpServiceData->SocketList;
510 Context.ServiceBinding = ServiceBinding;
511 Context.NumberOfChildren = NumberOfChildren;
512 Context.ChildHandleBuffer = ChildHandleBuffer;
513 Status = NetDestroyLinkList (
514 List,
515 Tcp4DestroyChildEntryInHandleBuffer,
516 &Context,
517 NULL
518 );
519 } else if (IsListEmpty (&TcpServiceData->SocketList)) {
520 //
521 // Uninstall TCP servicebinding protocol
522 //
523 gBS->UninstallMultipleProtocolInterfaces (
524 NicHandle,
525 &gEfiTcp4ServiceBindingProtocolGuid,
526 ServiceBinding,
527 NULL
528 );
529
530 //
531 // Destroy the IpIO consumed by TCP driver
532 //
533 IpIoDestroy (TcpServiceData->IpIo);
534 TcpServiceData->IpIo = NULL;
535
536 //
537 // Destroy the heartbeat timer.
538 //
539 Tcp4DestroyTimer ();
540
541 //
542 // Clear the variable.
543 //
544 TcpClearVariableData (TcpServiceData);
545
546 if (gTcpControllerNameTable != NULL) {
547 FreeUnicodeStringTable (gTcpControllerNameTable);
548 gTcpControllerNameTable = NULL;
549 }
550
551 //
552 // Release the TCP service data
553 //
554 FreePool (TcpServiceData);
555
556 Status = EFI_SUCCESS;
557 }
558
559 return Status;
560 }
561
562 /**
563 Open Ip4 and device path protocols for a created socket, and insert it in
564 socket list.
565
566 @param This Pointer to the socket just created
567 @param Context Context of the socket
568
569 @retval EFI_SUCCESS This protocol is installed successfully.
570 @retval other Some error occured.
571
572 **/
573 EFI_STATUS
574 Tcp4CreateSocketCallback (
575 IN SOCKET *This,
576 IN VOID *Context
577 )
578 {
579 EFI_STATUS Status;
580 TCP4_SERVICE_DATA *TcpServiceData;
581 EFI_IP4_PROTOCOL *Ip4;
582
583 TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService;
584
585 //
586 // Open the default Ip4 protocol of IP_IO BY_DRIVER.
587 //
588 Status = gBS->OpenProtocol (
589 TcpServiceData->IpIo->ChildHandle,
590 &gEfiIp4ProtocolGuid,
591 (VOID **) &Ip4,
592 TcpServiceData->DriverBindingHandle,
593 This->SockHandle,
594 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
595 );
596 if (EFI_ERROR (Status)) {
597 return Status;
598 }
599
600 //
601 // Open the device path on the handle where service binding resides on.
602 //
603 Status = gBS->OpenProtocol (
604 TcpServiceData->ControllerHandle,
605 &gEfiDevicePathProtocolGuid,
606 (VOID **) &This->ParentDevicePath,
607 TcpServiceData->DriverBindingHandle,
608 This->SockHandle,
609 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
610 );
611 if (EFI_ERROR (Status)) {
612 gBS->CloseProtocol (
613 TcpServiceData->IpIo->ChildHandle,
614 &gEfiIp4ProtocolGuid,
615 TcpServiceData->DriverBindingHandle,
616 This->SockHandle
617 );
618 } else {
619 //
620 // Insert this socket into the SocketList.
621 //
622 InsertTailList (&TcpServiceData->SocketList, &This->Link);
623 }
624
625 return Status;
626 }
627
628 /**
629 Close Ip4 and device path protocols for a socket, and remove it from socket list.
630
631 @param This Pointer to the socket to be removed
632 @param Context Context of the socket
633
634 **/
635 VOID
636 Tcp4DestroySocketCallback (
637 IN SOCKET *This,
638 IN VOID *Context
639 )
640 {
641 TCP4_SERVICE_DATA *TcpServiceData;
642
643 TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService;
644
645 //
646 // Remove this node from the list.
647 //
648 RemoveEntryList (&This->Link);
649
650 //
651 // Close the device path protocol
652 //
653 gBS->CloseProtocol (
654 TcpServiceData->ControllerHandle,
655 &gEfiDevicePathProtocolGuid,
656 TcpServiceData->DriverBindingHandle,
657 This->SockHandle
658 );
659
660 //
661 // Close the Ip4 protocol.
662 //
663 gBS->CloseProtocol (
664 TcpServiceData->IpIo->ChildHandle,
665 &gEfiIp4ProtocolGuid,
666 TcpServiceData->DriverBindingHandle,
667 This->SockHandle
668 );
669 }
670
671 /**
672 Creates a child handle and installs a protocol.
673
674 The CreateChild() function installs a protocol on ChildHandle. If ChildHandle
675 is a pointer to NULL, then a new handle is created and returned in ChildHandle.
676 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing
677 ChildHandle.
678
679 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
680 @param ChildHandle Pointer to the handle of the child to create. If it is NULL, then
681 a new handle is created. If it is a pointer to an existing UEFI
682 handle, then the protocol is added to the existing UEFI handle.
683
684 @retval EFI_SUCCES The protocol was added to ChildHandle.
685 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
686 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
687 the child.
688 @retval other The child handle was not created.
689
690 **/
691 EFI_STATUS
692 EFIAPI
693 Tcp4ServiceBindingCreateChild (
694 IN EFI_SERVICE_BINDING_PROTOCOL *This,
695 IN OUT EFI_HANDLE *ChildHandle
696 )
697 {
698 SOCKET *Sock;
699 TCP4_SERVICE_DATA *TcpServiceData;
700 TCP4_PROTO_DATA TcpProto;
701 EFI_STATUS Status;
702 EFI_TPL OldTpl;
703
704 if (NULL == This || NULL == ChildHandle) {
705 return EFI_INVALID_PARAMETER;
706 }
707
708 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
709 Status = EFI_SUCCESS;
710 TcpServiceData = TCP4_FROM_THIS (This);
711 TcpProto.TcpService = TcpServiceData;
712 TcpProto.TcpPcb = NULL;
713
714 //
715 // Create a tcp instance with defualt Tcp default
716 // sock init data and TcpProto
717 //
718 mTcp4DefaultSockData.ProtoData = &TcpProto;
719 mTcp4DefaultSockData.DataSize = sizeof (TCP4_PROTO_DATA);
720 mTcp4DefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;
721
722 Sock = SockCreateChild (&mTcp4DefaultSockData);
723 if (NULL == Sock) {
724 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingCreateChild: "
725 "No resource to create a Tcp Child\n"));
726
727 Status = EFI_OUT_OF_RESOURCES;
728 } else {
729 *ChildHandle = Sock->SockHandle;
730 }
731
732 mTcp4DefaultSockData.ProtoData = NULL;
733
734 gBS->RestoreTPL (OldTpl);
735 return Status;
736 }
737
738
739 /**
740 Destroys a child handle with a protocol installed on it.
741
742 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
743 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
744 last protocol on ChildHandle, then ChildHandle is destroyed.
745
746 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
747 @param ChildHandle Handle of the child to destroy
748
749 @retval EFI_SUCCES The protocol was removed from ChildHandle.
750 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is
751 being removed.
752 @retval EFI_INVALID_PARAMETER Child handle is NULL.
753 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
754 because its services are being used.
755 @retval other The child handle was not destroyed.
756
757 **/
758 EFI_STATUS
759 EFIAPI
760 Tcp4ServiceBindingDestroyChild (
761 IN EFI_SERVICE_BINDING_PROTOCOL *This,
762 IN EFI_HANDLE ChildHandle
763 )
764 {
765 EFI_STATUS Status;
766 EFI_TCP4_PROTOCOL *Tcp4;
767 SOCKET *Sock;
768
769 if (NULL == This || NULL == ChildHandle) {
770 return EFI_INVALID_PARAMETER;
771 }
772
773 //
774 // retrieve the Tcp4 protocol from ChildHandle
775 //
776 Status = gBS->OpenProtocol (
777 ChildHandle,
778 &gEfiTcp4ProtocolGuid,
779 (VOID **) &Tcp4,
780 mTcp4DriverBinding.DriverBindingHandle,
781 ChildHandle,
782 EFI_OPEN_PROTOCOL_GET_PROTOCOL
783 );
784 if (EFI_ERROR (Status)) {
785 Status = EFI_UNSUPPORTED;
786 } else {
787 //
788 // destroy this sock and related Tcp protocol control
789 // block
790 //
791 Sock = SOCK_FROM_THIS (Tcp4);
792
793 SockDestroyChild (Sock);
794 }
795
796 return Status;
797 }
798