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