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