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