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