]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/TcpDxe/TcpDriver.c
NetworkPkg: Protocol Uninstallation Cleanup
[mirror_edk2.git] / NetworkPkg / TcpDxe / TcpDriver.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 The driver binding and service binding protocol for the TCP driver.\r
3\r
f75a7f56 4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
a3bcde70
HT
5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php.\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "TcpMain.h"\r
17\r
18UINT16 mTcp4RandomPort;\r
19UINT16 mTcp6RandomPort;\r
20\r
21TCP_HEARTBEAT_TIMER mTcpTimer = {\r
22 NULL,\r
23 0\r
24};\r
25\r
26EFI_TCP4_PROTOCOL gTcp4ProtocolTemplate = {\r
27 Tcp4GetModeData,\r
28 Tcp4Configure,\r
29 Tcp4Routes,\r
30 Tcp4Connect,\r
31 Tcp4Accept,\r
32 Tcp4Transmit,\r
33 Tcp4Receive,\r
34 Tcp4Close,\r
35 Tcp4Cancel,\r
36 Tcp4Poll\r
37};\r
38\r
39EFI_TCP6_PROTOCOL gTcp6ProtocolTemplate = {\r
40 Tcp6GetModeData,\r
41 Tcp6Configure,\r
42 Tcp6Connect,\r
43 Tcp6Accept,\r
44 Tcp6Transmit,\r
45 Tcp6Receive,\r
46 Tcp6Close,\r
47 Tcp6Cancel,\r
48 Tcp6Poll\r
49};\r
50\r
51SOCK_INIT_DATA mTcpDefaultSockData = {\r
52 SockStream,\r
53 SO_CLOSED,\r
54 NULL,\r
55 TCP_BACKLOG,\r
56 TCP_SND_BUF_SIZE,\r
57 TCP_RCV_BUF_SIZE,\r
58 IP_VERSION_4,\r
59 NULL,\r
60 TcpCreateSocketCallback,\r
61 TcpDestroySocketCallback,\r
62 NULL,\r
63 NULL,\r
64 0,\r
65 TcpDispatcher,\r
66 NULL,\r
67};\r
68\r
6879581d 69EFI_DRIVER_BINDING_PROTOCOL gTcp4DriverBinding = {\r
70 Tcp4DriverBindingSupported,\r
71 Tcp4DriverBindingStart,\r
72 Tcp4DriverBindingStop,\r
73 0xa,\r
74 NULL,\r
75 NULL\r
76};\r
77\r
78EFI_DRIVER_BINDING_PROTOCOL gTcp6DriverBinding = {\r
79 Tcp6DriverBindingSupported,\r
80 Tcp6DriverBindingStart,\r
81 Tcp6DriverBindingStop,\r
a3bcde70
HT
82 0xa,\r
83 NULL,\r
84 NULL\r
85};\r
86\r
87EFI_SERVICE_BINDING_PROTOCOL gTcpServiceBinding = {\r
88 TcpServiceBindingCreateChild,\r
89 TcpServiceBindingDestroyChild\r
90};\r
91\r
92\r
93/**\r
94 Create and start the heartbeat timer for the TCP driver.\r
95\r
96 @retval EFI_SUCCESS The timer was successfully created and started.\r
97 @retval other The timer was not created.\r
98\r
99**/\r
100EFI_STATUS\r
101TcpCreateTimer (\r
102 VOID\r
103 )\r
104{\r
105 EFI_STATUS Status;\r
106\r
107 Status = EFI_SUCCESS;\r
108\r
109 if (mTcpTimer.RefCnt == 0) {\r
110\r
111 Status = gBS->CreateEvent (\r
112 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
113 TPL_NOTIFY,\r
114 TcpTicking,\r
115 NULL,\r
116 &mTcpTimer.TimerEvent\r
117 );\r
118 if (!EFI_ERROR (Status)) {\r
119\r
120 Status = gBS->SetTimer (\r
121 mTcpTimer.TimerEvent,\r
122 TimerPeriodic,\r
123 (UINT64) (TICKS_PER_SECOND / TCP_TICK_HZ)\r
124 );\r
125 }\r
126 }\r
127\r
128 if (!EFI_ERROR (Status)) {\r
129\r
130 mTcpTimer.RefCnt++;\r
131 }\r
132\r
133 return Status;\r
134}\r
135\r
136/**\r
137 Stop and destroy the heartbeat timer for TCP driver.\r
138\r
139**/\r
140VOID\r
141TcpDestroyTimer (\r
142 VOID\r
143 )\r
144{\r
145 ASSERT (mTcpTimer.RefCnt > 0);\r
146\r
147 mTcpTimer.RefCnt--;\r
148\r
149 if (mTcpTimer.RefCnt > 0) {\r
150 return;\r
151 }\r
152\r
153 gBS->SetTimer (mTcpTimer.TimerEvent, TimerCancel, 0);\r
154 gBS->CloseEvent (mTcpTimer.TimerEvent);\r
155 mTcpTimer.TimerEvent = NULL;\r
156}\r
157\r
158/**\r
159 The entry point for Tcp driver, which is used to install Tcp driver on the ImageHandle.\r
160\r
161 @param[in] ImageHandle The firmware allocated handle for this driver image.\r
162 @param[in] SystemTable Pointer to the EFI system table.\r
163\r
164 @retval EFI_SUCCESS The driver loaded.\r
165 @retval other The driver did not load.\r
166\r
167**/\r
168EFI_STATUS\r
169EFIAPI\r
170TcpDriverEntryPoint (\r
171 IN EFI_HANDLE ImageHandle,\r
172 IN EFI_SYSTEM_TABLE *SystemTable\r
173 )\r
174{\r
175 EFI_STATUS Status;\r
176 UINT32 Seed;\r
177\r
178 //\r
179 // Install the TCP Driver Binding Protocol\r
180 //\r
181 Status = EfiLibInstallDriverBindingComponentName2 (\r
182 ImageHandle,\r
183 SystemTable,\r
6879581d 184 &gTcp4DriverBinding,\r
a3bcde70
HT
185 ImageHandle,\r
186 &gTcpComponentName,\r
187 &gTcpComponentName2\r
188 );\r
189 if (EFI_ERROR (Status)) {\r
190 return Status;\r
191 }\r
192\r
6879581d 193 //\r
194 // Install the TCP Driver Binding Protocol\r
195 //\r
196 Status = EfiLibInstallDriverBindingComponentName2 (\r
197 ImageHandle,\r
198 SystemTable,\r
199 &gTcp6DriverBinding,\r
200 NULL,\r
201 &gTcpComponentName,\r
202 &gTcpComponentName2\r
203 );\r
204 if (EFI_ERROR (Status)) {\r
22b35e8b
AS
205 EfiLibUninstallDriverBindingComponentName2 (\r
206 &gTcp4DriverBinding,\r
207 &gTcpComponentName,\r
208 &gTcpComponentName2\r
209 );\r
6879581d 210 return Status;\r
211 }\r
212\r
a3bcde70
HT
213 //\r
214 // Initialize ISS and random port.\r
215 //\r
216 Seed = NetRandomInitSeed ();\r
217 mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;\r
218 mTcp4RandomPort = (UINT16) (TCP_PORT_KNOWN + (NET_RANDOM (Seed) % TCP_PORT_KNOWN));\r
219 mTcp6RandomPort = mTcp4RandomPort;\r
220\r
221 return EFI_SUCCESS;\r
222}\r
223\r
224/**\r
225 Create a new TCP4 or TCP6 driver service binding protocol\r
226\r
227 @param[in] Controller Controller handle of device to bind driver to.\r
76389e18 228 @param[in] Image The TCP driver's image handle.\r
a3bcde70
HT
229 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
230\r
231 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.\r
232 @retval EFI_SUCCESS A new IP6 service binding private was created.\r
233\r
234**/\r
235EFI_STATUS\r
236TcpCreateService (\r
237 IN EFI_HANDLE Controller,\r
238 IN EFI_HANDLE Image,\r
239 IN UINT8 IpVersion\r
240 )\r
241{\r
242 EFI_STATUS Status;\r
243 EFI_GUID *IpServiceBindingGuid;\r
244 EFI_GUID *TcpServiceBindingGuid;\r
245 TCP_SERVICE_DATA *TcpServiceData;\r
246 IP_IO_OPEN_DATA OpenData;\r
247\r
248 if (IpVersion == IP_VERSION_4) {\r
249 IpServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;\r
250 TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
251 } else {\r
252 IpServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid;\r
253 TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
254 }\r
255\r
256 Status = gBS->OpenProtocol (\r
257 Controller,\r
258 TcpServiceBindingGuid,\r
259 NULL,\r
260 Image,\r
261 Controller,\r
262 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
263 );\r
264 if (!EFI_ERROR (Status)) {\r
265 return EFI_ALREADY_STARTED;\r
266 }\r
267\r
268 Status = gBS->OpenProtocol (\r
269 Controller,\r
270 IpServiceBindingGuid,\r
271 NULL,\r
272 Image,\r
273 Controller,\r
274 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
275 );\r
276 if (EFI_ERROR (Status)) {\r
277 return EFI_UNSUPPORTED;\r
278 }\r
279\r
280 //\r
281 // Create the TCP service data.\r
282 //\r
283 TcpServiceData = AllocateZeroPool (sizeof (TCP_SERVICE_DATA));\r
284 if (TcpServiceData == NULL) {\r
285 return EFI_OUT_OF_RESOURCES;\r
286 }\r
287\r
288 TcpServiceData->Signature = TCP_DRIVER_SIGNATURE;\r
289 TcpServiceData->ControllerHandle = Controller;\r
290 TcpServiceData->DriverBindingHandle = Image;\r
291 TcpServiceData->IpVersion = IpVersion;\r
292 CopyMem (\r
293 &TcpServiceData->ServiceBinding,\r
294 &gTcpServiceBinding,\r
295 sizeof (EFI_SERVICE_BINDING_PROTOCOL)\r
296 );\r
297\r
298 TcpServiceData->IpIo = IpIoCreate (Image, Controller, IpVersion);\r
299 if (TcpServiceData->IpIo == NULL) {\r
300 Status = EFI_OUT_OF_RESOURCES;\r
301 goto ON_ERROR;\r
302 }\r
303\r
304\r
305 InitializeListHead (&TcpServiceData->SocketList);\r
306 ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));\r
307\r
308 if (IpVersion == IP_VERSION_4) {\r
309 CopyMem (\r
310 &OpenData.IpConfigData.Ip4CfgData,\r
311 &mIp4IoDefaultIpConfigData,\r
312 sizeof (EFI_IP4_CONFIG_DATA)\r
313 );\r
314 OpenData.IpConfigData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;\r
315 } else {\r
316 CopyMem (\r
317 &OpenData.IpConfigData.Ip6CfgData,\r
318 &mIp6IoDefaultIpConfigData,\r
319 sizeof (EFI_IP6_CONFIG_DATA)\r
320 );\r
321 OpenData.IpConfigData.Ip6CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;\r
322 }\r
323\r
324 OpenData.PktRcvdNotify = TcpRxCallback;\r
325 Status = IpIoOpen (TcpServiceData->IpIo, &OpenData);\r
326 if (EFI_ERROR (Status)) {\r
327 goto ON_ERROR;\r
328 }\r
329\r
330 Status = TcpCreateTimer ();\r
331 if (EFI_ERROR (Status)) {\r
332 goto ON_ERROR;\r
333 }\r
334\r
335 Status = gBS->InstallMultipleProtocolInterfaces (\r
336 &Controller,\r
337 TcpServiceBindingGuid,\r
338 &TcpServiceData->ServiceBinding,\r
339 NULL\r
340 );\r
341 if (EFI_ERROR (Status)) {\r
342 TcpDestroyTimer ();\r
343\r
344 goto ON_ERROR;\r
345 }\r
346\r
a3bcde70
HT
347 return EFI_SUCCESS;\r
348\r
349ON_ERROR:\r
350\r
351 if (TcpServiceData->IpIo != NULL) {\r
352 IpIoDestroy (TcpServiceData->IpIo);\r
216f7970 353 TcpServiceData->IpIo = NULL;\r
a3bcde70
HT
354 }\r
355\r
356 FreePool (TcpServiceData);\r
357\r
358 return Status;\r
359}\r
360\r
216f7970 361/**\r
362 Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
f75a7f56 363\r
216f7970 364 @param[in] Entry The entry to be removed.\r
365 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
366\r
367 @retval EFI_SUCCESS The entry has been removed successfully.\r
368 @retval Others Fail to remove the entry.\r
369\r
370**/\r
371EFI_STATUS\r
1f7eb561 372EFIAPI\r
216f7970 373TcpDestroyChildEntryInHandleBuffer (\r
374 IN LIST_ENTRY *Entry,\r
375 IN VOID *Context\r
1f7eb561 376 )\r
216f7970 377{\r
378 SOCKET *Sock;\r
379 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
380 UINTN NumberOfChildren;\r
381 EFI_HANDLE *ChildHandleBuffer;\r
382\r
383 if (Entry == NULL || Context == NULL) {\r
384 return EFI_INVALID_PARAMETER;\r
385 }\r
386\r
387 Sock = NET_LIST_USER_STRUCT_S (Entry, SOCKET, Link, SOCK_SIGNATURE);\r
388 ServiceBinding = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
389 NumberOfChildren = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
390 ChildHandleBuffer = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
391\r
392 if (!NetIsInHandleBuffer (Sock->SockHandle, NumberOfChildren, ChildHandleBuffer)) {\r
393 return EFI_SUCCESS;\r
394 }\r
395\r
396 return ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);\r
397}\r
398\r
a3bcde70
HT
399/**\r
400 Destroy a TCP6 or TCP4 service binding instance. It will release all\r
401 the resources allocated by the instance.\r
402\r
403 @param[in] Controller Controller handle of device to bind driver to.\r
404 @param[in] ImageHandle The TCP driver's image handle.\r
216f7970 405 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
a3bcde70 406 of children is zero stop the entire bus driver.\r
216f7970 407 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
f75a7f56 408 if NumberOfChildren is 0.\r
a3bcde70
HT
409 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6\r
410\r
411 @retval EFI_SUCCESS The resources used by the instance were cleaned up.\r
412 @retval Others Failed to clean up some of the resources.\r
413\r
414**/\r
415EFI_STATUS\r
416TcpDestroyService (\r
417 IN EFI_HANDLE Controller,\r
418 IN EFI_HANDLE ImageHandle,\r
419 IN UINTN NumberOfChildren,\r
216f7970 420 IN EFI_HANDLE *ChildHandleBuffer, OPTIONAL\r
a3bcde70
HT
421 IN UINT8 IpVersion\r
422 )\r
423{\r
424 EFI_HANDLE NicHandle;\r
425 EFI_GUID *IpProtocolGuid;\r
426 EFI_GUID *ServiceBindingGuid;\r
427 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
428 TCP_SERVICE_DATA *TcpServiceData;\r
429 EFI_STATUS Status;\r
216f7970 430 LIST_ENTRY *List;\r
431 TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
a3bcde70
HT
432\r
433 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
434\r
435 if (IpVersion == IP_VERSION_4) {\r
436 IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
437 ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
438 } else {\r
439 IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
440 ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
441 }\r
442\r
443 NicHandle = NetLibGetNicHandle (Controller, IpProtocolGuid);\r
444 if (NicHandle == NULL) {\r
216f7970 445 return EFI_SUCCESS;\r
a3bcde70
HT
446 }\r
447\r
448 Status = gBS->OpenProtocol (\r
449 NicHandle,\r
450 ServiceBindingGuid,\r
451 (VOID **) &ServiceBinding,\r
452 ImageHandle,\r
453 Controller,\r
454 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
455 );\r
456 if (EFI_ERROR (Status)) {\r
457 return EFI_DEVICE_ERROR;\r
458 }\r
459\r
460 TcpServiceData = TCP_SERVICE_FROM_THIS (ServiceBinding);\r
461\r
216f7970 462 if (NumberOfChildren != 0) {\r
463 List = &TcpServiceData->SocketList;\r
464 Context.ServiceBinding = ServiceBinding;\r
465 Context.NumberOfChildren = NumberOfChildren;\r
466 Context.ChildHandleBuffer = ChildHandleBuffer;\r
467 Status = NetDestroyLinkList (\r
468 List,\r
469 TcpDestroyChildEntryInHandleBuffer,\r
470 &Context,\r
471 NULL\r
472 );\r
473 } else if (IsListEmpty (&TcpServiceData->SocketList)) {\r
a3bcde70
HT
474 //\r
475 // Uninstall TCP servicebinding protocol\r
476 //\r
477 gBS->UninstallMultipleProtocolInterfaces (\r
478 NicHandle,\r
479 ServiceBindingGuid,\r
480 ServiceBinding,\r
481 NULL\r
482 );\r
483\r
484 //\r
485 // Destroy the IpIO consumed by TCP driver\r
486 //\r
487 IpIoDestroy (TcpServiceData->IpIo);\r
216f7970 488 TcpServiceData->IpIo = NULL;\r
a3bcde70
HT
489\r
490 //\r
491 // Destroy the heartbeat timer.\r
492 //\r
493 TcpDestroyTimer ();\r
494\r
a3bcde70
HT
495 //\r
496 // Release the TCP service data\r
497 //\r
498 FreePool (TcpServiceData);\r
a3bcde70 499\r
216f7970 500 Status = EFI_SUCCESS;\r
a3bcde70
HT
501 }\r
502\r
216f7970 503 return Status;\r
a3bcde70
HT
504}\r
505\r
506/**\r
507 Test to see if this driver supports ControllerHandle.\r
508\r
509 @param[in] This Protocol instance pointer.\r
510 @param[in] ControllerHandle Handle of device to test.\r
511 @param[in] RemainingDevicePath Optional parameter use to pick a specific\r
512 child device to start.\r
513\r
514 @retval EFI_SUCCESS This driver supports this device.\r
515 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
516 @retval other This driver does not support this device.\r
517\r
518**/\r
519EFI_STATUS\r
520EFIAPI\r
6879581d 521Tcp4DriverBindingSupported (\r
a3bcde70
HT
522 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
523 IN EFI_HANDLE ControllerHandle,\r
524 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
525 )\r
526{\r
527 EFI_STATUS Status;\r
a3bcde70
HT
528\r
529 //\r
530 // Test for the Tcp4ServiceBinding Protocol\r
531 //\r
532 Status = gBS->OpenProtocol (\r
533 ControllerHandle,\r
534 &gEfiTcp4ServiceBindingProtocolGuid,\r
535 NULL,\r
536 This->DriverBindingHandle,\r
537 ControllerHandle,\r
538 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
539 );\r
6879581d 540 if (!EFI_ERROR (Status)) {\r
541 return EFI_ALREADY_STARTED;\r
542 }\r
f75a7f56 543\r
6879581d 544 //\r
545 // Test for the Ip4ServiceBinding Protocol\r
546 //\r
547 Status = gBS->OpenProtocol (\r
548 ControllerHandle,\r
549 &gEfiIp4ServiceBindingProtocolGuid,\r
550 NULL,\r
551 This->DriverBindingHandle,\r
552 ControllerHandle,\r
553 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
554 );\r
555 return Status;\r
556}\r
a3bcde70 557\r
6879581d 558/**\r
559 Start this driver on ControllerHandle.\r
560\r
561 @param[in] This Protocol instance pointer.\r
562 @param[in] ControllerHandle Handle of device to bind driver to.\r
563 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
564 device to start.\r
565\r
566 @retval EFI_SUCCESS The driver is added to ControllerHandle.\r
567 @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the\r
568 driver.\r
569 @retval other The driver cannot be added to ControllerHandle.\r
570\r
571**/\r
572EFI_STATUS\r
573EFIAPI\r
574Tcp4DriverBindingStart (\r
575 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
576 IN EFI_HANDLE ControllerHandle,\r
577 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
578 )\r
579{\r
580 EFI_STATUS Status;\r
581\r
582 Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4);\r
583 if ((Status == EFI_ALREADY_STARTED) || (Status == EFI_UNSUPPORTED)) {\r
584 Status = EFI_SUCCESS;\r
a3bcde70
HT
585 }\r
586\r
6879581d 587 return Status;\r
588}\r
589\r
590/**\r
591 Stop this driver on ControllerHandle.\r
592\r
593 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
594 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
595 support a bus specific I/O protocol for the driver\r
596 to use to stop the device.\r
597 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
598 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
599 if NumberOfChildren is 0.\r
600\r
601 @retval EFI_SUCCESS The device was stopped.\r
602 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
603\r
604**/\r
605EFI_STATUS\r
606EFIAPI\r
607Tcp4DriverBindingStop (\r
608 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
609 IN EFI_HANDLE ControllerHandle,\r
610 IN UINTN NumberOfChildren,\r
611 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
612 )\r
613{\r
614 return TcpDestroyService (\r
615 ControllerHandle,\r
616 This->DriverBindingHandle,\r
617 NumberOfChildren,\r
618 ChildHandleBuffer,\r
619 IP_VERSION_4\r
620 );\r
621}\r
622\r
623/**\r
624 Test to see if this driver supports ControllerHandle.\r
625\r
626 @param[in] This Protocol instance pointer.\r
627 @param[in] ControllerHandle Handle of device to test.\r
628 @param[in] RemainingDevicePath Optional parameter use to pick a specific\r
629 child device to start.\r
630\r
631 @retval EFI_SUCCESS This driver supports this device.\r
632 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
633 @retval other This driver does not support this device.\r
634\r
635**/\r
636EFI_STATUS\r
637EFIAPI\r
638Tcp6DriverBindingSupported (\r
639 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
640 IN EFI_HANDLE ControllerHandle,\r
641 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
642 )\r
643{\r
644 EFI_STATUS Status;\r
645\r
a3bcde70 646 //\r
6879581d 647 // Test for the Tcp6ServiceBinding Protocol\r
a3bcde70
HT
648 //\r
649 Status = gBS->OpenProtocol (\r
650 ControllerHandle,\r
651 &gEfiTcp6ServiceBindingProtocolGuid,\r
652 NULL,\r
653 This->DriverBindingHandle,\r
654 ControllerHandle,\r
655 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
656 );\r
6879581d 657 if (!EFI_ERROR (Status)) {\r
a3bcde70
HT
658 return EFI_ALREADY_STARTED;\r
659 }\r
f75a7f56 660\r
6879581d 661 //\r
662 // Test for the Ip6ServiceBinding Protocol\r
663 //\r
664 Status = gBS->OpenProtocol (\r
665 ControllerHandle,\r
666 &gEfiIp6ServiceBindingProtocolGuid,\r
667 NULL,\r
668 This->DriverBindingHandle,\r
669 ControllerHandle,\r
670 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
671 );\r
672 return Status;\r
a3bcde70
HT
673}\r
674\r
675/**\r
676 Start this driver on ControllerHandle.\r
677\r
678 @param[in] This Protocol instance pointer.\r
679 @param[in] ControllerHandle Handle of device to bind driver to.\r
680 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
681 device to start.\r
682\r
683 @retval EFI_SUCCESS The driver is added to ControllerHandle.\r
684 @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the\r
685 driver.\r
686 @retval other The driver cannot be added to ControllerHandle.\r
687\r
688**/\r
689EFI_STATUS\r
690EFIAPI\r
6879581d 691Tcp6DriverBindingStart (\r
a3bcde70
HT
692 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
693 IN EFI_HANDLE ControllerHandle,\r
694 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
695 )\r
696{\r
6879581d 697 EFI_STATUS Status;\r
a3bcde70 698\r
6879581d 699 Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6);\r
700 if ((Status == EFI_ALREADY_STARTED) || (Status == EFI_UNSUPPORTED)) {\r
701 Status = EFI_SUCCESS;\r
a3bcde70
HT
702 }\r
703\r
6879581d 704 return Status;\r
a3bcde70
HT
705}\r
706\r
707/**\r
708 Stop this driver on ControllerHandle.\r
709\r
710 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
711 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
712 support a bus specific I/O protocol for the driver\r
713 to use to stop the device.\r
714 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
715 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
716 if NumberOfChildren is 0.\r
717\r
718 @retval EFI_SUCCESS The device was stopped.\r
719 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
720\r
721**/\r
722EFI_STATUS\r
723EFIAPI\r
6879581d 724Tcp6DriverBindingStop (\r
a3bcde70
HT
725 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
726 IN EFI_HANDLE ControllerHandle,\r
727 IN UINTN NumberOfChildren,\r
728 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
729 )\r
730{\r
6879581d 731 return TcpDestroyService (\r
732 ControllerHandle,\r
733 This->DriverBindingHandle,\r
734 NumberOfChildren,\r
735 ChildHandleBuffer,\r
736 IP_VERSION_6\r
737 );\r
a3bcde70
HT
738}\r
739\r
740/**\r
741 The Callback funtion called after the TCP socket was created.\r
742\r
743 @param[in] This Pointer to the socket just created\r
744 @param[in] Context Context of the socket\r
745\r
746 @retval EFI_SUCCESS This protocol installed successfully.\r
747 @retval other An error occured.\r
748\r
749**/\r
750EFI_STATUS\r
751TcpCreateSocketCallback (\r
752 IN SOCKET *This,\r
753 IN VOID *Context\r
754 )\r
755{\r
756 EFI_STATUS Status;\r
757 TCP_SERVICE_DATA *TcpServiceData;\r
758 EFI_GUID *IpProtocolGuid;\r
759 VOID *Ip;\r
760\r
761 if (This->IpVersion == IP_VERSION_4) {\r
762 IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
763 } else {\r
764 IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
765 }\r
766\r
767 TcpServiceData = ((TCP_PROTO_DATA *) This->ProtoReserved)->TcpService;\r
768\r
769 //\r
770 // Open the default IP protocol of IP_IO BY_DRIVER.\r
771 //\r
772 Status = gBS->OpenProtocol (\r
773 TcpServiceData->IpIo->ChildHandle,\r
774 IpProtocolGuid,\r
775 &Ip,\r
776 TcpServiceData->DriverBindingHandle,\r
777 This->SockHandle,\r
778 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
779 );\r
780 if (EFI_ERROR (Status)) {\r
781 return Status;\r
782 }\r
783\r
784 //\r
785 // Open the device path on the handle where service binding resides on.\r
786 //\r
787 Status = gBS->OpenProtocol (\r
788 TcpServiceData->ControllerHandle,\r
789 &gEfiDevicePathProtocolGuid,\r
790 (VOID **) &This->ParentDevicePath,\r
791 TcpServiceData->DriverBindingHandle,\r
792 This->SockHandle,\r
bf1400b9 793 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
a3bcde70
HT
794 );\r
795 if (EFI_ERROR (Status)) {\r
796 gBS->CloseProtocol (\r
797 TcpServiceData->IpIo->ChildHandle,\r
798 IpProtocolGuid,\r
799 TcpServiceData->DriverBindingHandle,\r
800 This->SockHandle\r
801 );\r
802 } else {\r
803 //\r
804 // Insert this socket into the SocketList.\r
805 //\r
806 InsertTailList (&TcpServiceData->SocketList, &This->Link);\r
807 }\r
808\r
809 return Status;\r
810}\r
811\r
812/**\r
813 The callback function called before the TCP socket was to be destroyed.\r
814\r
815 @param[in] This The TCP socket to be destroyed.\r
816 @param[in] Context The context of the socket.\r
817\r
818**/\r
819VOID\r
820TcpDestroySocketCallback (\r
821 IN SOCKET *This,\r
822 IN VOID *Context\r
823 )\r
824{\r
825 TCP_SERVICE_DATA *TcpServiceData;\r
826 EFI_GUID *IpProtocolGuid;\r
827\r
828 if (This->IpVersion == IP_VERSION_4) {\r
829 IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
830 } else {\r
831 IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
832 }\r
833\r
834 TcpServiceData = ((TCP_PROTO_DATA *) This->ProtoReserved)->TcpService;\r
835\r
836 //\r
837 // Remove this node from the list.\r
838 //\r
839 RemoveEntryList (&This->Link);\r
840\r
a3bcde70
HT
841 //\r
842 // Close the IP protocol.\r
843 //\r
844 gBS->CloseProtocol (\r
845 TcpServiceData->IpIo->ChildHandle,\r
846 IpProtocolGuid,\r
847 TcpServiceData->DriverBindingHandle,\r
848 This->SockHandle\r
849 );\r
850}\r
851\r
852/**\r
853 Creates a child handle with a set of TCP services.\r
854\r
855 The CreateChild() function installs a protocol on ChildHandle.\r
856 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.\r
857 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
858\r
859 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
860 @param[in, out] ChildHandle Pointer to the handle of the child to create.\r
861 If it is NULL, then a new handle is created.\r
862 If it is a pointer to an existing UEFI handle,\r
863 then the protocol is added to the existing UEFI handle.\r
864\r
865 @retval EFI_SUCCES The protocol was added to ChildHandle.\r
866 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
c2adf51f 867 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create\r
a3bcde70
HT
868 the child.\r
869 @retval other The child handle was not created.\r
870\r
871**/\r
872EFI_STATUS\r
873EFIAPI\r
874TcpServiceBindingCreateChild (\r
875 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
876 IN OUT EFI_HANDLE *ChildHandle\r
877 )\r
878{\r
879 SOCKET *Sock;\r
880 TCP_SERVICE_DATA *TcpServiceData;\r
881 TCP_PROTO_DATA TcpProto;\r
882 EFI_STATUS Status;\r
883 EFI_TPL OldTpl;\r
884\r
885 if (NULL == This || NULL == ChildHandle) {\r
886 return EFI_INVALID_PARAMETER;\r
887 }\r
888\r
889 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
890\r
891 Status = EFI_SUCCESS;\r
892 TcpServiceData = TCP_SERVICE_FROM_THIS (This);\r
893 TcpProto.TcpService = TcpServiceData;\r
894 TcpProto.TcpPcb = NULL;\r
895\r
896 //\r
897 // Create a tcp instance with defualt Tcp default\r
898 // sock init data and TcpProto\r
899 //\r
900 mTcpDefaultSockData.ProtoData = &TcpProto;\r
901 mTcpDefaultSockData.DataSize = sizeof (TCP_PROTO_DATA);\r
902 mTcpDefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;\r
903 mTcpDefaultSockData.IpVersion = TcpServiceData->IpVersion;\r
904\r
905 if (TcpServiceData->IpVersion == IP_VERSION_4) {\r
906 mTcpDefaultSockData.Protocol = &gTcp4ProtocolTemplate;\r
907 } else {\r
908 mTcpDefaultSockData.Protocol = &gTcp6ProtocolTemplate;\r
909 }\r
910\r
911 Sock = SockCreateChild (&mTcpDefaultSockData);\r
912 if (NULL == Sock) {\r
913 DEBUG (\r
914 (EFI_D_ERROR,\r
915 "TcpDriverBindingCreateChild: No resource to create a Tcp Child\n")\r
916 );\r
917\r
918 Status = EFI_OUT_OF_RESOURCES;\r
919 } else {\r
920 *ChildHandle = Sock->SockHandle;\r
921 }\r
922\r
923 mTcpDefaultSockData.ProtoData = NULL;\r
924\r
925 gBS->RestoreTPL (OldTpl);\r
926 return Status;\r
927}\r
928\r
929/**\r
930 Destroys a child handle with a set of TCP services.\r
931\r
932 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol\r
933 that was installed by CreateChild() from ChildHandle. If the removed protocol is the\r
934 last protocol on ChildHandle, then ChildHandle is destroyed.\r
935\r
936 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
937 @param ChildHandle Handle of the child to be destroyed.\r
938\r
939 @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
940 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.\r
15ee13fc 941 @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
a3bcde70
HT
942 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
943 because its services are being used.\r
944 @retval other The child handle was not destroyed.\r
945\r
946**/\r
947EFI_STATUS\r
948EFIAPI\r
949TcpServiceBindingDestroyChild (\r
950 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
951 IN EFI_HANDLE ChildHandle\r
952 )\r
953{\r
954 EFI_STATUS Status;\r
955 VOID *Tcp;\r
956 SOCKET *Sock;\r
a3bcde70
HT
957\r
958 if (NULL == This || NULL == ChildHandle) {\r
959 return EFI_INVALID_PARAMETER;\r
960 }\r
961\r
a3bcde70
HT
962 //\r
963 // retrieve the Tcp4 protocol from ChildHandle\r
964 //\r
965 Status = gBS->OpenProtocol (\r
966 ChildHandle,\r
967 &gEfiTcp4ProtocolGuid,\r
968 &Tcp,\r
6879581d 969 gTcp4DriverBinding.DriverBindingHandle,\r
a3bcde70
HT
970 ChildHandle,\r
971 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
972 );\r
973 if (EFI_ERROR (Status)) {\r
974 //\r
975 // No Tcp4, try the Tcp6 protocol\r
976 //\r
977 Status = gBS->OpenProtocol (\r
978 ChildHandle,\r
979 &gEfiTcp6ProtocolGuid,\r
980 &Tcp,\r
6879581d 981 gTcp6DriverBinding.DriverBindingHandle,\r
a3bcde70
HT
982 ChildHandle,\r
983 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
984 );\r
985 if (EFI_ERROR (Status)) {\r
986 Status = EFI_UNSUPPORTED;\r
987 }\r
988 }\r
989\r
990 if (!EFI_ERROR (Status)) {\r
991 //\r
992 // destroy this sock and related Tcp protocol control\r
993 // block\r
994 //\r
995 Sock = SOCK_FROM_THIS (Tcp);\r
996\r
997 SockDestroyChild (Sock);\r
998 }\r
999\r
a3bcde70
HT
1000 return Status;\r
1001}\r