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