]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.c
1. Add EFI_COMPONENT_NAME2_PROTOCOL.GetControllerName() support.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Driver.c
CommitLineData
8a67d61d 1/** @file\r
dab714aa 2 Tcp driver function.\r
8a67d61d 3\r
216f7970 4Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
8a67d61d 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
dfc1f033 8http://opensource.org/licenses/bsd-license.php<BR>\r
8a67d61d 9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
8a67d61d 13**/\r
14\r
15#include "Tcp4Main.h"\r
16\r
17\r
120db52c 18UINT16 mTcp4RandomPort;\r
83cbd279 19extern EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName;\r
20extern EFI_COMPONENT_NAME2_PROTOCOL gTcp4ComponentName2;\r
216f7970 21extern EFI_UNICODE_STRING_TABLE *gTcpControllerNameTable;\r
8a67d61d 22\r
23TCP4_HEARTBEAT_TIMER mTcp4Timer = {\r
24 NULL,\r
25 0\r
26};\r
27\r
28EFI_TCP4_PROTOCOL mTcp4ProtocolTemplate = {\r
29 Tcp4GetModeData,\r
30 Tcp4Configure,\r
31 Tcp4Routes,\r
32 Tcp4Connect,\r
33 Tcp4Accept,\r
34 Tcp4Transmit,\r
35 Tcp4Receive,\r
36 Tcp4Close,\r
37 Tcp4Cancel,\r
38 Tcp4Poll\r
39};\r
40\r
41SOCK_INIT_DATA mTcp4DefaultSockData = {\r
f6b7393c 42 SockStream,\r
43 0,\r
8a67d61d 44 NULL,\r
45 TCP_BACKLOG,\r
46 TCP_SND_BUF_SIZE,\r
47 TCP_RCV_BUF_SIZE,\r
48 &mTcp4ProtocolTemplate,\r
4f6e31e4 49 Tcp4CreateSocketCallback,\r
50 Tcp4DestroySocketCallback,\r
51 NULL,\r
52 NULL,\r
53 0,\r
8a67d61d 54 Tcp4Dispatcher,\r
55 NULL,\r
56};\r
57\r
58EFI_DRIVER_BINDING_PROTOCOL mTcp4DriverBinding = {\r
59 Tcp4DriverBindingSupported,\r
60 Tcp4DriverBindingStart,\r
61 Tcp4DriverBindingStop,\r
62 0xa,\r
63 NULL,\r
64 NULL\r
65};\r
66\r
67EFI_SERVICE_BINDING_PROTOCOL mTcp4ServiceBinding = {\r
68 Tcp4ServiceBindingCreateChild,\r
69 Tcp4ServiceBindingDestroyChild\r
70};\r
71\r
72\r
73/**\r
74 Create and start the heartbeat timer for TCP driver.\r
75\r
8a67d61d 76 @retval EFI_SUCCESS The timer is successfully created and started.\r
77 @retval other The timer is not created.\r
78\r
79**/\r
8a67d61d 80EFI_STATUS\r
81Tcp4CreateTimer (\r
82 VOID\r
83 )\r
84{\r
85 EFI_STATUS Status;\r
86\r
87 Status = EFI_SUCCESS;\r
88\r
89 if (mTcp4Timer.RefCnt == 0) {\r
90\r
91 Status = gBS->CreateEvent (\r
92 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
e48e37fc 93 TPL_NOTIFY,\r
8a67d61d 94 TcpTicking,\r
95 NULL,\r
96 &mTcp4Timer.TimerEvent\r
97 );\r
98 if (!EFI_ERROR (Status)) {\r
99\r
100 Status = gBS->SetTimer (\r
101 mTcp4Timer.TimerEvent,\r
102 TimerPeriodic,\r
103 (UINT64) (TICKS_PER_SECOND / TCP_TICK_HZ)\r
104 );\r
105 }\r
106 }\r
107\r
108 if (!EFI_ERROR (Status)) {\r
109\r
110 mTcp4Timer.RefCnt++;\r
111 }\r
112\r
113 return Status;\r
114}\r
115\r
116\r
117/**\r
118 Stop and destroy the heartbeat timer for TCP driver.\r
85511ddf 119 \r
8a67d61d 120**/\r
8a67d61d 121VOID\r
120db52c 122Tcp4DestroyTimer (\r
123 VOID\r
124 )\r
8a67d61d 125{\r
126 ASSERT (mTcp4Timer.RefCnt > 0);\r
127\r
128 mTcp4Timer.RefCnt--;\r
129\r
130 if (mTcp4Timer.RefCnt > 0) {\r
131 return;\r
132 }\r
133\r
134 gBS->SetTimer (mTcp4Timer.TimerEvent, TimerCancel, 0);\r
135 gBS->CloseEvent (mTcp4Timer.TimerEvent);\r
136 mTcp4Timer.TimerEvent = NULL;\r
137}\r
138\r
216f7970 139/**\r
140 Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
141 \r
142 @param[in] Entry The entry to be removed.\r
143 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
144\r
145 @retval EFI_SUCCESS The entry has been removed successfully.\r
146 @retval Others Fail to remove the entry.\r
147\r
148**/\r
149EFI_STATUS\r
150Tcp4DestroyChildEntryInHandleBuffer (\r
151 IN LIST_ENTRY *Entry,\r
152 IN VOID *Context\r
153)\r
154{\r
155 SOCKET *Sock;\r
156 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
157 UINTN NumberOfChildren;\r
158 EFI_HANDLE *ChildHandleBuffer;\r
159\r
160 if (Entry == NULL || Context == NULL) {\r
161 return EFI_INVALID_PARAMETER;\r
162 }\r
163\r
164 Sock = NET_LIST_USER_STRUCT_S (Entry, SOCKET, Link, SOCK_SIGNATURE);\r
165 ServiceBinding = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
166 NumberOfChildren = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
167 ChildHandleBuffer = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
168\r
169 if (!NetIsInHandleBuffer (Sock->SockHandle, NumberOfChildren, ChildHandleBuffer)) {\r
170 return EFI_SUCCESS;\r
171 }\r
172\r
173 return ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);\r
174}\r
175\r
85511ddf 176/**\r
120db52c 177 The entry point for Tcp4 driver, used to install Tcp4 driver on the ImageHandle.\r
85511ddf 178\r
179 @param ImageHandle The firmware allocated handle for this\r
180 driver image.\r
181 @param SystemTable Pointer to the EFI system table.\r
182\r
183 @retval EFI_SUCCESS Driver loaded.\r
184 @retval other Driver not loaded.\r
8a67d61d 185\r
85511ddf 186**/\r
8a67d61d 187EFI_STATUS\r
188EFIAPI\r
189Tcp4DriverEntryPoint (\r
190 IN EFI_HANDLE ImageHandle,\r
191 IN EFI_SYSTEM_TABLE *SystemTable\r
192 )\r
8a67d61d 193{\r
194 EFI_STATUS Status;\r
195 UINT32 Seed;\r
196\r
197 //\r
198 // Install the TCP4 Driver Binding Protocol\r
199 //\r
83cbd279 200 Status = EfiLibInstallDriverBindingComponentName2 (\r
8a67d61d 201 ImageHandle,\r
202 SystemTable,\r
203 &mTcp4DriverBinding,\r
204 ImageHandle,\r
205 &gTcp4ComponentName,\r
83cbd279 206 &gTcp4ComponentName2\r
8a67d61d 207 );\r
da1d0201 208 ASSERT_EFI_ERROR (Status);\r
8a67d61d 209 //\r
210 // Initialize ISS and random port.\r
211 //\r
212 Seed = NetRandomInitSeed ();\r
213 mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;\r
120db52c 214 mTcp4RandomPort = (UINT16) (TCP4_PORT_KNOWN +\r
4eb65aff 215 (UINT16) (NET_RANDOM(Seed) % TCP4_PORT_KNOWN));\r
8a67d61d 216\r
217 return Status;\r
218}\r
219\r
220\r
221/**\r
dfc1f033 222 Tests to see if this driver supports a given controller.\r
223 \r
224 If a child device is provided, it further tests to see if this driver supports \r
225 creating a handle for the specified child device.\r
226\r
227 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
228 @param ControllerHandle The handle of the controller to test. This handle \r
229 must support a protocol interface that supplies \r
230 an I/O abstraction to the driver.\r
231 @param RemainingDevicePath A pointer to the remaining portion of a device path. \r
232 This parameter is ignored by device drivers, and is optional for bus drivers.\r
233\r
234\r
235 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
236 RemainingDevicePath is supported by the driver \r
237 specified by This.\r
238 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
239 RemainingDevicePath is already being managed by \r
240 the driver specified by This.\r
241 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
242 RemainingDevicePath is already being managed by a \r
243 different driver or an application that requires \r
244 exclusive access.\r
245 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
246 RemainingDevicePath is not supported by the driver \r
247 specified by This.\r
248 \r
8a67d61d 249**/\r
250EFI_STATUS\r
251EFIAPI\r
252Tcp4DriverBindingSupported (\r
120db52c 253 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
8a67d61d 254 IN EFI_HANDLE ControllerHandle,\r
120db52c 255 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
8a67d61d 256 )\r
257{\r
258 EFI_STATUS Status;\r
259\r
260 //\r
261 // Test for the Tcp4ServiceBinding Protocol\r
262 //\r
263 Status = gBS->OpenProtocol (\r
264 ControllerHandle,\r
265 &gEfiTcp4ServiceBindingProtocolGuid,\r
266 NULL,\r
267 This->DriverBindingHandle,\r
268 ControllerHandle,\r
269 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
270 );\r
271 if (!EFI_ERROR (Status)) {\r
272 return EFI_ALREADY_STARTED;\r
273 }\r
274\r
275 //\r
276 // Test for the Ip4 Protocol\r
277 //\r
278 Status = gBS->OpenProtocol (\r
279 ControllerHandle,\r
280 &gEfiIp4ServiceBindingProtocolGuid,\r
281 NULL,\r
282 This->DriverBindingHandle,\r
283 ControllerHandle,\r
284 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
285 );\r
286\r
287 return Status;\r
288}\r
289\r
290\r
291/**\r
dfc1f033 292 Start this driver on ControllerHandle. \r
293 \r
294 The Start() function is designed to be invoked from the EFI boot service \r
295 ConnectController(). As a result, much of the error checking on the parameters \r
296 to Start() has been moved into this common boot service. It is legal to call \r
297 Start() from other locations, but the following calling restrictions must be \r
298 followed or the system behavior will not be deterministic.\r
299 1. ControllerHandle must be a valid EFI_HANDLE.\r
300 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally \r
301 aligned EFI_DEVICE_PATH_PROTOCOL.\r
302 3. Prior to calling Start(), the Supported() function for the driver specified \r
303 by This must have been called with the same calling parameters, and Supported() \r
304 must have returned EFI_SUCCESS.\r
305\r
306 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
307 @param ControllerHandle The handle of the controller to start. This handle \r
308 must support a protocol interface that supplies \r
309 an I/O abstraction to the driver.\r
310 @param RemainingDevicePath A pointer to the remaining portion of a device path. \r
311 This parameter is ignored by device drivers, and is \r
312 optional for bus drivers.\r
313\r
314 @retval EFI_SUCCESS The device was started.\r
315 @retval EFI_ALREADY_STARTED The device could not be started due to a device error.\r
316 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack \r
317 of resources.\r
8a67d61d 318\r
319**/\r
320EFI_STATUS\r
321EFIAPI\r
322Tcp4DriverBindingStart (\r
120db52c 323 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
8a67d61d 324 IN EFI_HANDLE ControllerHandle,\r
120db52c 325 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
8a67d61d 326 )\r
327{\r
328 EFI_STATUS Status;\r
329 TCP4_SERVICE_DATA *TcpServiceData;\r
330 IP_IO_OPEN_DATA OpenData;\r
331\r
e48e37fc 332 TcpServiceData = AllocateZeroPool (sizeof (TCP4_SERVICE_DATA));\r
8a67d61d 333\r
334 if (NULL == TcpServiceData) {\r
e48e37fc 335 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Have no enough"\r
dfc1f033 336 " resource to create a Tcp Servcie Data\n"));\r
8a67d61d 337\r
338 return EFI_OUT_OF_RESOURCES;\r
339 }\r
340\r
341 //\r
342 // Create a new IP IO to Consume it\r
343 //\r
fb115c61 344 TcpServiceData->IpIo = IpIoCreate (\r
345 This->DriverBindingHandle,\r
346 ControllerHandle,\r
347 IP_VERSION_4\r
348 );\r
8a67d61d 349 if (NULL == TcpServiceData->IpIo) {\r
350\r
e48e37fc 351 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Have no enough"\r
dfc1f033 352 " resource to create an Ip Io\n"));\r
8a67d61d 353\r
354 Status = EFI_OUT_OF_RESOURCES;\r
c4a62a12 355 goto ON_ERROR;\r
8a67d61d 356 }\r
357\r
358 //\r
359 // Configure and start IpIo.\r
360 //\r
e48e37fc 361 ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));\r
8a67d61d 362\r
fb115c61 363 CopyMem (\r
364 &OpenData.IpConfigData.Ip4CfgData,\r
365 &mIp4IoDefaultIpConfigData,\r
366 sizeof (EFI_IP4_CONFIG_DATA)\r
367 );\r
368\r
369 OpenData.IpConfigData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;\r
8a67d61d 370\r
371 OpenData.PktRcvdNotify = Tcp4RxCallback;\r
372 Status = IpIoOpen (TcpServiceData->IpIo, &OpenData);\r
373\r
374 if (EFI_ERROR (Status)) {\r
c4a62a12 375 goto ON_ERROR;\r
8a67d61d 376 }\r
377\r
378 //\r
379 // Create the timer event used by TCP driver\r
380 //\r
381 Status = Tcp4CreateTimer ();\r
382 if (EFI_ERROR (Status)) {\r
383\r
e48e37fc 384 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Create TcpTimer"\r
8a67d61d 385 " Event failed with %r\n", Status));\r
386\r
c4a62a12 387 goto ON_ERROR;\r
8a67d61d 388 }\r
389\r
390 //\r
391 // Install the Tcp4ServiceBinding Protocol on the\r
392 // controller handle\r
393 //\r
394 TcpServiceData->Tcp4ServiceBinding = mTcp4ServiceBinding;\r
395\r
396 Status = gBS->InstallMultipleProtocolInterfaces (\r
397 &ControllerHandle,\r
398 &gEfiTcp4ServiceBindingProtocolGuid,\r
399 &TcpServiceData->Tcp4ServiceBinding,\r
400 NULL\r
401 );\r
402 if (EFI_ERROR (Status)) {\r
403\r
e48e37fc 404 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Install Tcp4 Service Binding"\r
8a67d61d 405 " Protocol failed for %r\n", Status));\r
406\r
c4a62a12 407 Tcp4DestroyTimer ();\r
408 goto ON_ERROR;\r
8a67d61d 409 }\r
410\r
411 //\r
412 // Initialize member in TcpServiceData\r
413 //\r
414 TcpServiceData->ControllerHandle = ControllerHandle;\r
415 TcpServiceData->Signature = TCP4_DRIVER_SIGNATURE;\r
416 TcpServiceData->DriverBindingHandle = This->DriverBindingHandle;\r
417\r
e48e37fc 418 InitializeListHead (&TcpServiceData->SocketList);\r
c4a62a12 419\r
8a67d61d 420 TcpSetVariableData (TcpServiceData);\r
421\r
422 return EFI_SUCCESS;\r
423\r
c4a62a12 424ON_ERROR:\r
8a67d61d 425\r
c4a62a12 426 if (TcpServiceData->IpIo != NULL) {\r
427 IpIoDestroy (TcpServiceData->IpIo);\r
216f7970 428 TcpServiceData->IpIo = NULL;\r
c4a62a12 429 }\r
8a67d61d 430\r
766c7483 431 FreePool (TcpServiceData);\r
8a67d61d 432\r
433 return Status;\r
434}\r
435\r
436\r
437/**\r
438 Stop this driver on ControllerHandle.\r
dfc1f033 439 \r
440 The Stop() function is designed to be invoked from the EFI boot service \r
441 DisconnectController(). As a result, much of the error checking on the parameters \r
442 to Stop() has been moved into this common boot service. It is legal to call Stop() \r
443 from other locations, but the following calling restrictions must be followed \r
444 or the system behavior will not be deterministic.\r
445 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call \r
446 to this same driver's Start() function.\r
447 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
448 EFI_HANDLE. In addition, all of these handles must have been created in this \r
449 driver's Start() function, and the Start() function must have called OpenProtocol() \r
450 on ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
451 \r
452 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
453 @param ControllerHandle A handle to the device being stopped. The handle must \r
454 support a bus specific I/O protocol for the driver \r
455 to use to stop the device.\r
456 @param NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
457 @param ChildHandleBuffer An array of child handles to be freed. May be NULL if \r
458 NumberOfChildren is 0.\r
8a67d61d 459\r
dfc1f033 460 @retval EFI_SUCCESS The device was stopped.\r
461 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
8a67d61d 462\r
463**/\r
464EFI_STATUS\r
465EFIAPI\r
466Tcp4DriverBindingStop (\r
467 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
468 IN EFI_HANDLE ControllerHandle,\r
469 IN UINTN NumberOfChildren,\r
470 IN EFI_HANDLE *ChildHandleBuffer\r
471 )\r
472{\r
216f7970 473 EFI_STATUS Status;\r
474 EFI_HANDLE NicHandle;\r
475 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
476 TCP4_SERVICE_DATA *TcpServiceData;\r
477 LIST_ENTRY *List;\r
478 TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
8a67d61d 479\r
480 // Find the NicHandle where Tcp4 ServiceBinding Protocol is installed.\r
481 //\r
482 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);\r
483 if (NicHandle == NULL) {\r
216f7970 484 return EFI_SUCCESS;\r
8a67d61d 485 }\r
486\r
487 //\r
488 // Retrieve the TCP driver Data Structure\r
489 //\r
490 Status = gBS->OpenProtocol (\r
491 NicHandle,\r
492 &gEfiTcp4ServiceBindingProtocolGuid,\r
c4a62a12 493 (VOID **) &ServiceBinding,\r
8a67d61d 494 This->DriverBindingHandle,\r
495 ControllerHandle,\r
496 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
497 );\r
498 if (EFI_ERROR (Status)) {\r
499\r
e48e37fc 500 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStop: Locate Tcp4 Service "\r
8a67d61d 501 " Binding Protocol failed with %r\n", Status));\r
502\r
c4a62a12 503 return EFI_DEVICE_ERROR;\r
8a67d61d 504 }\r
505\r
c4a62a12 506 TcpServiceData = TCP4_FROM_THIS (ServiceBinding);\r
8a67d61d 507\r
216f7970 508 if (NumberOfChildren != 0) {\r
509 List = &TcpServiceData->SocketList; \r
510 Context.ServiceBinding = ServiceBinding;\r
511 Context.NumberOfChildren = NumberOfChildren;\r
512 Context.ChildHandleBuffer = ChildHandleBuffer;\r
513 Status = NetDestroyLinkList (\r
514 List,\r
515 Tcp4DestroyChildEntryInHandleBuffer,\r
516 &Context,\r
517 NULL\r
518 );\r
519 } else if (IsListEmpty (&TcpServiceData->SocketList)) {\r
8a67d61d 520 //\r
c4a62a12 521 // Uninstall TCP servicebinding protocol\r
8a67d61d 522 //\r
c4a62a12 523 gBS->UninstallMultipleProtocolInterfaces (\r
524 NicHandle,\r
525 &gEfiTcp4ServiceBindingProtocolGuid,\r
526 ServiceBinding,\r
527 NULL\r
528 );\r
8a67d61d 529\r
c4a62a12 530 //\r
531 // Destroy the IpIO consumed by TCP driver\r
532 //\r
533 IpIoDestroy (TcpServiceData->IpIo);\r
216f7970 534 TcpServiceData->IpIo = NULL;\r
8a67d61d 535\r
c4a62a12 536 //\r
537 // Destroy the heartbeat timer.\r
538 //\r
539 Tcp4DestroyTimer ();\r
8a67d61d 540\r
c4a62a12 541 //\r
542 // Clear the variable.\r
543 //\r
544 TcpClearVariableData (TcpServiceData);\r
8a67d61d 545\r
216f7970 546 if (gTcpControllerNameTable != NULL) {\r
547 FreeUnicodeStringTable (gTcpControllerNameTable);\r
548 gTcpControllerNameTable = NULL;\r
549 }\r
550 \r
8a67d61d 551 //\r
c4a62a12 552 // Release the TCP service data\r
8a67d61d 553 //\r
766c7483 554 FreePool (TcpServiceData);\r
8a67d61d 555\r
216f7970 556 Status = EFI_SUCCESS;\r
8a67d61d 557 }\r
558\r
8a67d61d 559 return Status;\r
560}\r
561\r
120db52c 562/**\r
563 Open Ip4 and device path protocols for a created socket, and insert it in \r
564 socket list.\r
565 \r
566 @param This Pointer to the socket just created\r
567 @param Context Context of the socket\r
568 \r
569 @retval EFI_SUCCESS This protocol is installed successfully.\r
570 @retval other Some error occured.\r
571 \r
572**/\r
4f6e31e4 573EFI_STATUS\r
574Tcp4CreateSocketCallback (\r
575 IN SOCKET *This,\r
576 IN VOID *Context\r
577 )\r
578{\r
579 EFI_STATUS Status;\r
580 TCP4_SERVICE_DATA *TcpServiceData;\r
581 EFI_IP4_PROTOCOL *Ip4;\r
582\r
583 TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService;\r
584\r
585 //\r
586 // Open the default Ip4 protocol of IP_IO BY_DRIVER.\r
587 //\r
588 Status = gBS->OpenProtocol (\r
589 TcpServiceData->IpIo->ChildHandle,\r
590 &gEfiIp4ProtocolGuid,\r
591 (VOID **) &Ip4,\r
592 TcpServiceData->DriverBindingHandle,\r
593 This->SockHandle,\r
594 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
595 );\r
596 if (EFI_ERROR (Status)) {\r
597 return Status;\r
598 }\r
599\r
600 //\r
601 // Open the device path on the handle where service binding resides on.\r
602 //\r
603 Status = gBS->OpenProtocol (\r
604 TcpServiceData->ControllerHandle,\r
605 &gEfiDevicePathProtocolGuid,\r
606 (VOID **) &This->ParentDevicePath,\r
607 TcpServiceData->DriverBindingHandle,\r
608 This->SockHandle,\r
609 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
610 );\r
611 if (EFI_ERROR (Status)) {\r
612 gBS->CloseProtocol (\r
613 TcpServiceData->IpIo->ChildHandle,\r
614 &gEfiIp4ProtocolGuid,\r
615 TcpServiceData->DriverBindingHandle,\r
616 This->SockHandle\r
617 );\r
618 } else {\r
619 //\r
620 // Insert this socket into the SocketList.\r
621 //\r
e48e37fc 622 InsertTailList (&TcpServiceData->SocketList, &This->Link);\r
4f6e31e4 623 }\r
624\r
625 return Status;\r
626}\r
627\r
120db52c 628/**\r
629 Close Ip4 and device path protocols for a socket, and remove it from socket list. \r
630 \r
631 @param This Pointer to the socket to be removed\r
632 @param Context Context of the socket\r
633 \r
634**/\r
4f6e31e4 635VOID\r
636Tcp4DestroySocketCallback (\r
637 IN SOCKET *This,\r
638 IN VOID *Context\r
639 )\r
640{\r
641 TCP4_SERVICE_DATA *TcpServiceData;\r
642\r
643 TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService;\r
644\r
645 //\r
646 // Remove this node from the list.\r
647 //\r
e48e37fc 648 RemoveEntryList (&This->Link);\r
4f6e31e4 649\r
650 //\r
651 // Close the device path protocol\r
652 //\r
653 gBS->CloseProtocol (\r
654 TcpServiceData->ControllerHandle,\r
655 &gEfiDevicePathProtocolGuid,\r
656 TcpServiceData->DriverBindingHandle,\r
657 This->SockHandle\r
658 );\r
659\r
660 //\r
661 // Close the Ip4 protocol.\r
662 //\r
663 gBS->CloseProtocol (\r
664 TcpServiceData->IpIo->ChildHandle,\r
665 &gEfiIp4ProtocolGuid,\r
666 TcpServiceData->DriverBindingHandle,\r
667 This->SockHandle\r
668 );\r
669}\r
670\r
8a67d61d 671/**\r
dfc1f033 672 Creates a child handle and installs a protocol.\r
673 \r
674 The CreateChild() function installs a protocol on ChildHandle. If ChildHandle \r
675 is a pointer to NULL, then a new handle is created and returned in ChildHandle. \r
676 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing \r
677 ChildHandle.\r
678\r
679 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
680 @param ChildHandle Pointer to the handle of the child to create. If it is NULL, then \r
681 a new handle is created. If it is a pointer to an existing UEFI \r
682 handle, then the protocol is added to the existing UEFI handle.\r
683\r
684 @retval EFI_SUCCES The protocol was added to ChildHandle.\r
685 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
686 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
687 the child.\r
688 @retval other The child handle was not created.\r
8a67d61d 689\r
690**/\r
691EFI_STATUS\r
692EFIAPI\r
693Tcp4ServiceBindingCreateChild (\r
276dcc1b 694 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
695 IN OUT EFI_HANDLE *ChildHandle\r
8a67d61d 696 )\r
697{\r
698 SOCKET *Sock;\r
699 TCP4_SERVICE_DATA *TcpServiceData;\r
700 TCP4_PROTO_DATA TcpProto;\r
701 EFI_STATUS Status;\r
8a67d61d 702 EFI_TPL OldTpl;\r
703\r
704 if (NULL == This || NULL == ChildHandle) {\r
705 return EFI_INVALID_PARAMETER;\r
706 }\r
707\r
e48e37fc 708 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
4f6e31e4 709 Status = EFI_SUCCESS;\r
8a67d61d 710 TcpServiceData = TCP4_FROM_THIS (This);\r
711 TcpProto.TcpService = TcpServiceData;\r
712 TcpProto.TcpPcb = NULL;\r
713\r
714 //\r
715 // Create a tcp instance with defualt Tcp default\r
716 // sock init data and TcpProto\r
717 //\r
4f6e31e4 718 mTcp4DefaultSockData.ProtoData = &TcpProto;\r
719 mTcp4DefaultSockData.DataSize = sizeof (TCP4_PROTO_DATA);\r
8a67d61d 720 mTcp4DefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;\r
e48e37fc 721\r
4f6e31e4 722 Sock = SockCreateChild (&mTcp4DefaultSockData);\r
8a67d61d 723 if (NULL == Sock) {\r
e48e37fc 724 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingCreateChild: "\r
8a67d61d 725 "No resource to create a Tcp Child\n"));\r
726\r
727 Status = EFI_OUT_OF_RESOURCES;\r
c4a62a12 728 } else {\r
4f6e31e4 729 *ChildHandle = Sock->SockHandle;\r
8a67d61d 730 }\r
731\r
c9325700
ED
732 mTcp4DefaultSockData.ProtoData = NULL;\r
733\r
e48e37fc 734 gBS->RestoreTPL (OldTpl);\r
8a67d61d 735 return Status;\r
736}\r
737\r
738\r
739/**\r
dfc1f033 740 Destroys a child handle with a protocol installed on it.\r
741 \r
742 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol \r
743 that was installed by CreateChild() from ChildHandle. If the removed protocol is the \r
744 last protocol on ChildHandle, then ChildHandle is destroyed.\r
745\r
746 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
747 @param ChildHandle Handle of the child to destroy\r
748\r
749 @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
750 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is \r
751 being removed.\r
284ee2e8 752 @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
dfc1f033 753 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
754 because its services are being used.\r
755 @retval other The child handle was not destroyed.\r
756 \r
8a67d61d 757**/\r
758EFI_STATUS\r
759EFIAPI\r
760Tcp4ServiceBindingDestroyChild (\r
761 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
762 IN EFI_HANDLE ChildHandle\r
763 )\r
764{\r
765 EFI_STATUS Status;\r
766 EFI_TCP4_PROTOCOL *Tcp4;\r
767 SOCKET *Sock;\r
8a67d61d 768\r
769 if (NULL == This || NULL == ChildHandle) {\r
770 return EFI_INVALID_PARAMETER;\r
771 }\r
772\r
8a67d61d 773 //\r
774 // retrieve the Tcp4 protocol from ChildHandle\r
775 //\r
776 Status = gBS->OpenProtocol (\r
777 ChildHandle,\r
778 &gEfiTcp4ProtocolGuid,\r
779 (VOID **) &Tcp4,\r
780 mTcp4DriverBinding.DriverBindingHandle,\r
781 ChildHandle,\r
782 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
783 );\r
784 if (EFI_ERROR (Status)) {\r
785 Status = EFI_UNSUPPORTED;\r
4f6e31e4 786 } else {\r
787 //\r
788 // destroy this sock and related Tcp protocol control\r
789 // block\r
790 //\r
791 Sock = SOCK_FROM_THIS (Tcp4);\r
e5e12de7 792\r
4f6e31e4 793 SockDestroyChild (Sock);\r
794 }\r
8a67d61d 795\r
8a67d61d 796 return Status;\r
797}\r
4f6e31e4 798\r