]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.c
Import ArpDxe, Dhcp4Dxe, Ip4Dxe, Mtftp4Dxe, PxeBcDxe and PxeDhcp4Dxe.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Driver.c
CommitLineData
8a67d61d 1/** @file\r
2\r
3Copyright (c) 2005 - 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 Tcp4Driver.c\r
15\r
16Abstract:\r
17\r
18\r
19**/\r
20\r
21#include "Tcp4Main.h"\r
22\r
23\r
24UINT16 mTcp4RandomPort;\r
25extern EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName;\r
26\r
27TCP4_HEARTBEAT_TIMER mTcp4Timer = {\r
28 NULL,\r
29 0\r
30};\r
31\r
32EFI_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
45SOCK_INIT_DATA mTcp4DefaultSockData = {\r
46 SOCK_STREAM,\r
4eb65aff 47 (SOCK_STATE) 0,\r
8a67d61d 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
57EFI_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
66EFI_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
81STATIC\r
82EFI_STATUS\r
83Tcp4CreateTimer (\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
127STATIC\r
128VOID\r
129Tcp4DestroyTimer (\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
8a67d61d 146\r
147EFI_STATUS\r
148EFIAPI\r
149Tcp4DriverEntryPoint (\r
150 IN EFI_HANDLE ImageHandle,\r
151 IN EFI_SYSTEM_TABLE *SystemTable\r
152 )\r
153/*++\r
154\r
155Routine Description:\r
156\r
157 The entry point for Tcp4 driver. used to install\r
158 Tcp4 driver on the ImageHandle.\r
159\r
160Arguments:\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
166Returns:\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
4eb65aff 194 mTcp4RandomPort = (UINT16) ( TCP4_PORT_KNOWN +\r
195 (UINT16) (NET_RANDOM(Seed) % TCP4_PORT_KNOWN));\r
8a67d61d 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
214EFI_STATUS\r
215EFIAPI\r
216Tcp4DriverBindingSupported (\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
269EFI_STATUS\r
270EFIAPI\r
271Tcp4DriverBindingStart (\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
4eb65aff 308 CopyMem (&OpenData.IpConfigData, &mIpIoDefaultIpConfigData, sizeof (EFI_IP4_CONFIG_DATA));\r
8a67d61d 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
361ReleaseTimer:\r
362\r
363 Tcp4DestroyTimer ();\r
364\r
365ReleaseIpIo:\r
366\r
367 IpIoDestroy (TcpServiceData->IpIo);\r
368\r
369ReleaseServiceData:\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
390EFI_STATUS\r
391EFIAPI\r
392Tcp4DriverBindingStop (\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
536EFI_STATUS\r
537EFIAPI\r
538Tcp4ServiceBindingCreateChild (\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
591ON_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
609EFI_STATUS\r
610EFIAPI\r
611Tcp4ServiceBindingDestroyChild (\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
665ON_EXIT:\r
666 NET_RESTORE_TPL (OldTpl);\r
667 return Status;\r
668}\r