]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/TcpDxe/TcpDriver.c
Get ParentDevicePath by using attribute EFI_OPEN_PROTOCOL_GET_PROTOCOL instead of...
[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
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
1f7eb561 345EFIAPI\r
216f7970 346TcpDestroyChildEntryInHandleBuffer (\r
347 IN LIST_ENTRY *Entry,\r
348 IN VOID *Context\r
1f7eb561 349 )\r
216f7970 350{\r
351 SOCKET *Sock;\r
352 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
353 UINTN NumberOfChildren;\r
354 EFI_HANDLE *ChildHandleBuffer;\r
355\r
356 if (Entry == NULL || Context == NULL) {\r
357 return EFI_INVALID_PARAMETER;\r
358 }\r
359\r
360 Sock = NET_LIST_USER_STRUCT_S (Entry, SOCKET, Link, SOCK_SIGNATURE);\r
361 ServiceBinding = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
362 NumberOfChildren = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
363 ChildHandleBuffer = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
364\r
365 if (!NetIsInHandleBuffer (Sock->SockHandle, NumberOfChildren, ChildHandleBuffer)) {\r
366 return EFI_SUCCESS;\r
367 }\r
368\r
369 return ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);\r
370}\r
371\r
a3bcde70
HT
372/**\r
373 Destroy a TCP6 or TCP4 service binding instance. It will release all\r
374 the resources allocated by the instance.\r
375\r
376 @param[in] Controller Controller handle of device to bind driver to.\r
377 @param[in] ImageHandle The TCP driver's image handle.\r
216f7970 378 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
a3bcde70 379 of children is zero stop the entire bus driver.\r
216f7970 380 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
381 if NumberOfChildren is 0. \r
a3bcde70
HT
382 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6\r
383\r
384 @retval EFI_SUCCESS The resources used by the instance were cleaned up.\r
385 @retval Others Failed to clean up some of the resources.\r
386\r
387**/\r
388EFI_STATUS\r
389TcpDestroyService (\r
390 IN EFI_HANDLE Controller,\r
391 IN EFI_HANDLE ImageHandle,\r
392 IN UINTN NumberOfChildren,\r
216f7970 393 IN EFI_HANDLE *ChildHandleBuffer, OPTIONAL\r
a3bcde70
HT
394 IN UINT8 IpVersion\r
395 )\r
396{\r
397 EFI_HANDLE NicHandle;\r
398 EFI_GUID *IpProtocolGuid;\r
399 EFI_GUID *ServiceBindingGuid;\r
400 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
401 TCP_SERVICE_DATA *TcpServiceData;\r
402 EFI_STATUS Status;\r
216f7970 403 LIST_ENTRY *List;\r
404 TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
a3bcde70
HT
405\r
406 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
407\r
408 if (IpVersion == IP_VERSION_4) {\r
409 IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
410 ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
411 } else {\r
412 IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
413 ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
414 }\r
415\r
416 NicHandle = NetLibGetNicHandle (Controller, IpProtocolGuid);\r
417 if (NicHandle == NULL) {\r
216f7970 418 return EFI_SUCCESS;\r
a3bcde70
HT
419 }\r
420\r
421 Status = gBS->OpenProtocol (\r
422 NicHandle,\r
423 ServiceBindingGuid,\r
424 (VOID **) &ServiceBinding,\r
425 ImageHandle,\r
426 Controller,\r
427 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
428 );\r
429 if (EFI_ERROR (Status)) {\r
430 return EFI_DEVICE_ERROR;\r
431 }\r
432\r
433 TcpServiceData = TCP_SERVICE_FROM_THIS (ServiceBinding);\r
434\r
216f7970 435 if (NumberOfChildren != 0) {\r
436 List = &TcpServiceData->SocketList;\r
437 Context.ServiceBinding = ServiceBinding;\r
438 Context.NumberOfChildren = NumberOfChildren;\r
439 Context.ChildHandleBuffer = ChildHandleBuffer;\r
440 Status = NetDestroyLinkList (\r
441 List,\r
442 TcpDestroyChildEntryInHandleBuffer,\r
443 &Context,\r
444 NULL\r
445 );\r
446 } else if (IsListEmpty (&TcpServiceData->SocketList)) {\r
a3bcde70
HT
447 //\r
448 // Uninstall TCP servicebinding protocol\r
449 //\r
450 gBS->UninstallMultipleProtocolInterfaces (\r
451 NicHandle,\r
452 ServiceBindingGuid,\r
453 ServiceBinding,\r
454 NULL\r
455 );\r
456\r
457 //\r
458 // Destroy the IpIO consumed by TCP driver\r
459 //\r
460 IpIoDestroy (TcpServiceData->IpIo);\r
216f7970 461 TcpServiceData->IpIo = NULL;\r
a3bcde70
HT
462\r
463 //\r
464 // Destroy the heartbeat timer.\r
465 //\r
466 TcpDestroyTimer ();\r
467\r
468 //\r
469 // Clear the variable.\r
470 //\r
471 TcpClearVariableData (TcpServiceData);\r
472\r
473 //\r
474 // Release the TCP service data\r
475 //\r
476 FreePool (TcpServiceData);\r
a3bcde70 477\r
216f7970 478 Status = EFI_SUCCESS;\r
a3bcde70
HT
479 }\r
480\r
216f7970 481 return Status;\r
a3bcde70
HT
482}\r
483\r
484/**\r
485 Test to see if this driver supports ControllerHandle.\r
486\r
487 @param[in] This Protocol instance pointer.\r
488 @param[in] ControllerHandle Handle of device to test.\r
489 @param[in] RemainingDevicePath Optional parameter use to pick a specific\r
490 child device to start.\r
491\r
492 @retval EFI_SUCCESS This driver supports this device.\r
493 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
494 @retval other This driver does not support this device.\r
495\r
496**/\r
497EFI_STATUS\r
498EFIAPI\r
499TcpDriverBindingSupported (\r
500 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
501 IN EFI_HANDLE ControllerHandle,\r
502 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
503 )\r
504{\r
505 EFI_STATUS Status;\r
506 BOOLEAN IsTcp4Started;\r
507\r
508 //\r
509 // Test for the Tcp4ServiceBinding Protocol\r
510 //\r
511 Status = gBS->OpenProtocol (\r
512 ControllerHandle,\r
513 &gEfiTcp4ServiceBindingProtocolGuid,\r
514 NULL,\r
515 This->DriverBindingHandle,\r
516 ControllerHandle,\r
517 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
518 );\r
519 if (EFI_ERROR (Status)) {\r
520 //\r
521 // Test for the Ip4ServiceBinding Protocol\r
522 //\r
523 Status = gBS->OpenProtocol (\r
524 ControllerHandle,\r
525 &gEfiIp4ServiceBindingProtocolGuid,\r
526 NULL,\r
527 This->DriverBindingHandle,\r
528 ControllerHandle,\r
529 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
530 );\r
531 if (!EFI_ERROR (Status)) {\r
532 return EFI_SUCCESS;\r
533 }\r
534\r
535 IsTcp4Started = FALSE;\r
536 } else {\r
537 IsTcp4Started = TRUE;\r
538 }\r
539\r
540 //\r
541 // Check the Tcp6ServiceBinding Protocol\r
542 //\r
543 Status = gBS->OpenProtocol (\r
544 ControllerHandle,\r
545 &gEfiTcp6ServiceBindingProtocolGuid,\r
546 NULL,\r
547 This->DriverBindingHandle,\r
548 ControllerHandle,\r
549 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
550 );\r
551 if (EFI_ERROR (Status)) {\r
552 //\r
553 // Test for the Ip6ServiceBinding Protocol\r
554 //\r
555 Status = gBS->OpenProtocol (\r
556 ControllerHandle,\r
557 &gEfiIp6ServiceBindingProtocolGuid,\r
558 NULL,\r
559 This->DriverBindingHandle,\r
560 ControllerHandle,\r
561 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
562 );\r
563 if (!EFI_ERROR (Status)) {\r
564 return EFI_SUCCESS;\r
565 }\r
566 } else if (IsTcp4Started) {\r
567 return EFI_ALREADY_STARTED;\r
568 }\r
569\r
570 return EFI_UNSUPPORTED;\r
571}\r
572\r
573/**\r
574 Start this driver on ControllerHandle.\r
575\r
576 @param[in] This Protocol instance pointer.\r
577 @param[in] ControllerHandle Handle of device to bind driver to.\r
578 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
579 device to start.\r
580\r
581 @retval EFI_SUCCESS The driver is added to ControllerHandle.\r
582 @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the\r
583 driver.\r
584 @retval other The driver cannot be added to ControllerHandle.\r
585\r
586**/\r
587EFI_STATUS\r
588EFIAPI\r
589TcpDriverBindingStart (\r
590 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
591 IN EFI_HANDLE ControllerHandle,\r
592 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
593 )\r
594{\r
595 EFI_STATUS Tcp4Status;\r
596 EFI_STATUS Tcp6Status;\r
597\r
598 Tcp4Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4);\r
599 if ((Tcp4Status == EFI_ALREADY_STARTED) || (Tcp4Status == EFI_UNSUPPORTED)) {\r
600 Tcp4Status = EFI_SUCCESS;\r
601 }\r
602\r
603 Tcp6Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6);\r
604 if ((Tcp6Status == EFI_ALREADY_STARTED) || (Tcp6Status == EFI_UNSUPPORTED)) {\r
605 Tcp6Status = EFI_SUCCESS;\r
606 }\r
607\r
608 if (!EFI_ERROR (Tcp4Status) || !EFI_ERROR (Tcp6Status)) {\r
609 return EFI_SUCCESS;\r
610 } else if (EFI_ERROR (Tcp4Status)) {\r
611 return Tcp4Status;\r
612 } else {\r
613 return Tcp6Status;\r
614 }\r
615}\r
616\r
617/**\r
618 Stop this driver on ControllerHandle.\r
619\r
620 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
621 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
622 support a bus specific I/O protocol for the driver\r
623 to use to stop the device.\r
624 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
625 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
626 if NumberOfChildren is 0.\r
627\r
628 @retval EFI_SUCCESS The device was stopped.\r
629 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
630\r
631**/\r
632EFI_STATUS\r
633EFIAPI\r
634TcpDriverBindingStop (\r
635 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
636 IN EFI_HANDLE ControllerHandle,\r
637 IN UINTN NumberOfChildren,\r
638 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
639 )\r
640{\r
641 EFI_STATUS Tcp4Status;\r
642 EFI_STATUS Tcp6Status;\r
643\r
644 Tcp4Status = TcpDestroyService (\r
645 ControllerHandle,\r
646 This->DriverBindingHandle,\r
647 NumberOfChildren,\r
216f7970 648 ChildHandleBuffer,\r
a3bcde70
HT
649 IP_VERSION_4\r
650 );\r
651\r
652 Tcp6Status = TcpDestroyService (\r
653 ControllerHandle,\r
654 This->DriverBindingHandle,\r
655 NumberOfChildren,\r
216f7970 656 ChildHandleBuffer,\r
a3bcde70
HT
657 IP_VERSION_6\r
658 );\r
659\r
660 if (EFI_ERROR (Tcp4Status) && EFI_ERROR (Tcp6Status)) {\r
661 return EFI_DEVICE_ERROR;\r
662 } else {\r
663 return EFI_SUCCESS;\r
664 }\r
665}\r
666\r
667/**\r
668 The Callback funtion called after the TCP socket was created.\r
669\r
670 @param[in] This Pointer to the socket just created\r
671 @param[in] Context Context of the socket\r
672\r
673 @retval EFI_SUCCESS This protocol installed successfully.\r
674 @retval other An error occured.\r
675\r
676**/\r
677EFI_STATUS\r
678TcpCreateSocketCallback (\r
679 IN SOCKET *This,\r
680 IN VOID *Context\r
681 )\r
682{\r
683 EFI_STATUS Status;\r
684 TCP_SERVICE_DATA *TcpServiceData;\r
685 EFI_GUID *IpProtocolGuid;\r
686 VOID *Ip;\r
687\r
688 if (This->IpVersion == IP_VERSION_4) {\r
689 IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
690 } else {\r
691 IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
692 }\r
693\r
694 TcpServiceData = ((TCP_PROTO_DATA *) This->ProtoReserved)->TcpService;\r
695\r
696 //\r
697 // Open the default IP protocol of IP_IO BY_DRIVER.\r
698 //\r
699 Status = gBS->OpenProtocol (\r
700 TcpServiceData->IpIo->ChildHandle,\r
701 IpProtocolGuid,\r
702 &Ip,\r
703 TcpServiceData->DriverBindingHandle,\r
704 This->SockHandle,\r
705 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
706 );\r
707 if (EFI_ERROR (Status)) {\r
708 return Status;\r
709 }\r
710\r
711 //\r
712 // Open the device path on the handle where service binding resides on.\r
713 //\r
714 Status = gBS->OpenProtocol (\r
715 TcpServiceData->ControllerHandle,\r
716 &gEfiDevicePathProtocolGuid,\r
717 (VOID **) &This->ParentDevicePath,\r
718 TcpServiceData->DriverBindingHandle,\r
719 This->SockHandle,\r
bf1400b9 720 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
a3bcde70
HT
721 );\r
722 if (EFI_ERROR (Status)) {\r
723 gBS->CloseProtocol (\r
724 TcpServiceData->IpIo->ChildHandle,\r
725 IpProtocolGuid,\r
726 TcpServiceData->DriverBindingHandle,\r
727 This->SockHandle\r
728 );\r
729 } else {\r
730 //\r
731 // Insert this socket into the SocketList.\r
732 //\r
733 InsertTailList (&TcpServiceData->SocketList, &This->Link);\r
734 }\r
735\r
736 return Status;\r
737}\r
738\r
739/**\r
740 The callback function called before the TCP socket was to be destroyed.\r
741\r
742 @param[in] This The TCP socket to be destroyed.\r
743 @param[in] Context The context of the socket.\r
744\r
745**/\r
746VOID\r
747TcpDestroySocketCallback (\r
748 IN SOCKET *This,\r
749 IN VOID *Context\r
750 )\r
751{\r
752 TCP_SERVICE_DATA *TcpServiceData;\r
753 EFI_GUID *IpProtocolGuid;\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 // Remove this node from the list.\r
765 //\r
766 RemoveEntryList (&This->Link);\r
767\r
a3bcde70
HT
768 //\r
769 // Close the IP protocol.\r
770 //\r
771 gBS->CloseProtocol (\r
772 TcpServiceData->IpIo->ChildHandle,\r
773 IpProtocolGuid,\r
774 TcpServiceData->DriverBindingHandle,\r
775 This->SockHandle\r
776 );\r
777}\r
778\r
779/**\r
780 Creates a child handle with a set of TCP services.\r
781\r
782 The CreateChild() function installs a protocol on ChildHandle.\r
783 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.\r
784 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
785\r
786 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
787 @param[in, out] ChildHandle Pointer to the handle of the child to create.\r
788 If it is NULL, then a new handle is created.\r
789 If it is a pointer to an existing UEFI handle,\r
790 then the protocol is added to the existing UEFI handle.\r
791\r
792 @retval EFI_SUCCES The protocol was added to ChildHandle.\r
793 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
794 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
795 the child.\r
796 @retval other The child handle was not created.\r
797\r
798**/\r
799EFI_STATUS\r
800EFIAPI\r
801TcpServiceBindingCreateChild (\r
802 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
803 IN OUT EFI_HANDLE *ChildHandle\r
804 )\r
805{\r
806 SOCKET *Sock;\r
807 TCP_SERVICE_DATA *TcpServiceData;\r
808 TCP_PROTO_DATA TcpProto;\r
809 EFI_STATUS Status;\r
810 EFI_TPL OldTpl;\r
811\r
812 if (NULL == This || NULL == ChildHandle) {\r
813 return EFI_INVALID_PARAMETER;\r
814 }\r
815\r
816 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
817\r
818 Status = EFI_SUCCESS;\r
819 TcpServiceData = TCP_SERVICE_FROM_THIS (This);\r
820 TcpProto.TcpService = TcpServiceData;\r
821 TcpProto.TcpPcb = NULL;\r
822\r
823 //\r
824 // Create a tcp instance with defualt Tcp default\r
825 // sock init data and TcpProto\r
826 //\r
827 mTcpDefaultSockData.ProtoData = &TcpProto;\r
828 mTcpDefaultSockData.DataSize = sizeof (TCP_PROTO_DATA);\r
829 mTcpDefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;\r
830 mTcpDefaultSockData.IpVersion = TcpServiceData->IpVersion;\r
831\r
832 if (TcpServiceData->IpVersion == IP_VERSION_4) {\r
833 mTcpDefaultSockData.Protocol = &gTcp4ProtocolTemplate;\r
834 } else {\r
835 mTcpDefaultSockData.Protocol = &gTcp6ProtocolTemplate;\r
836 }\r
837\r
838 Sock = SockCreateChild (&mTcpDefaultSockData);\r
839 if (NULL == Sock) {\r
840 DEBUG (\r
841 (EFI_D_ERROR,\r
842 "TcpDriverBindingCreateChild: No resource to create a Tcp Child\n")\r
843 );\r
844\r
845 Status = EFI_OUT_OF_RESOURCES;\r
846 } else {\r
847 *ChildHandle = Sock->SockHandle;\r
848 }\r
849\r
850 mTcpDefaultSockData.ProtoData = NULL;\r
851\r
852 gBS->RestoreTPL (OldTpl);\r
853 return Status;\r
854}\r
855\r
856/**\r
857 Destroys a child handle with a set of TCP services.\r
858\r
859 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol\r
860 that was installed by CreateChild() from ChildHandle. If the removed protocol is the\r
861 last protocol on ChildHandle, then ChildHandle is destroyed.\r
862\r
863 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
864 @param ChildHandle Handle of the child to be destroyed.\r
865\r
866 @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
867 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.\r
15ee13fc 868 @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
a3bcde70
HT
869 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
870 because its services are being used.\r
871 @retval other The child handle was not destroyed.\r
872\r
873**/\r
874EFI_STATUS\r
875EFIAPI\r
876TcpServiceBindingDestroyChild (\r
877 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
878 IN EFI_HANDLE ChildHandle\r
879 )\r
880{\r
881 EFI_STATUS Status;\r
882 VOID *Tcp;\r
883 SOCKET *Sock;\r
a3bcde70
HT
884\r
885 if (NULL == This || NULL == ChildHandle) {\r
886 return EFI_INVALID_PARAMETER;\r
887 }\r
888\r
a3bcde70
HT
889 //\r
890 // retrieve the Tcp4 protocol from ChildHandle\r
891 //\r
892 Status = gBS->OpenProtocol (\r
893 ChildHandle,\r
894 &gEfiTcp4ProtocolGuid,\r
895 &Tcp,\r
896 gTcpDriverBinding.DriverBindingHandle,\r
897 ChildHandle,\r
898 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
899 );\r
900 if (EFI_ERROR (Status)) {\r
901 //\r
902 // No Tcp4, try the Tcp6 protocol\r
903 //\r
904 Status = gBS->OpenProtocol (\r
905 ChildHandle,\r
906 &gEfiTcp6ProtocolGuid,\r
907 &Tcp,\r
908 gTcpDriverBinding.DriverBindingHandle,\r
909 ChildHandle,\r
910 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
911 );\r
912 if (EFI_ERROR (Status)) {\r
913 Status = EFI_UNSUPPORTED;\r
914 }\r
915 }\r
916\r
917 if (!EFI_ERROR (Status)) {\r
918 //\r
919 // destroy this sock and related Tcp protocol control\r
920 // block\r
921 //\r
922 Sock = SOCK_FROM_THIS (Tcp);\r
923\r
924 SockDestroyChild (Sock);\r
925 }\r
926\r
a3bcde70
HT
927 return Status;\r
928}\r