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