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