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