]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Driver.c
1 /** @file
2
3 Copyright (c) 2005 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 Tcp4Driver.c
15
16 Abstract:
17
18
19 **/
20
21 #include "Tcp4Main.h"
22
23
24 UINT16 mTcp4RandomPort;
25 extern EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName;
26 extern EFI_COMPONENT_NAME2_PROTOCOL gTcp4ComponentName2;
27
28 TCP4_HEARTBEAT_TIMER mTcp4Timer = {
29 NULL,
30 0
31 };
32
33 EFI_TCP4_PROTOCOL mTcp4ProtocolTemplate = {
34 Tcp4GetModeData,
35 Tcp4Configure,
36 Tcp4Routes,
37 Tcp4Connect,
38 Tcp4Accept,
39 Tcp4Transmit,
40 Tcp4Receive,
41 Tcp4Close,
42 Tcp4Cancel,
43 Tcp4Poll
44 };
45
46 SOCK_INIT_DATA mTcp4DefaultSockData = {
47 SOCK_STREAM,
48 (SOCK_STATE) 0,
49 NULL,
50 TCP_BACKLOG,
51 TCP_SND_BUF_SIZE,
52 TCP_RCV_BUF_SIZE,
53 &mTcp4ProtocolTemplate,
54 Tcp4CreateSocketCallback,
55 Tcp4DestroySocketCallback,
56 NULL,
57 NULL,
58 0,
59 Tcp4Dispatcher,
60 NULL,
61 };
62
63 EFI_DRIVER_BINDING_PROTOCOL mTcp4DriverBinding = {
64 Tcp4DriverBindingSupported,
65 Tcp4DriverBindingStart,
66 Tcp4DriverBindingStop,
67 0xa,
68 NULL,
69 NULL
70 };
71
72 EFI_SERVICE_BINDING_PROTOCOL mTcp4ServiceBinding = {
73 Tcp4ServiceBindingCreateChild,
74 Tcp4ServiceBindingDestroyChild
75 };
76
77
78 /**
79 Create and start the heartbeat timer for TCP driver.
80
81 None.
82
83 @retval EFI_SUCCESS The timer is successfully created and started.
84 @retval other The timer is not created.
85
86 **/
87 EFI_STATUS
88 Tcp4CreateTimer (
89 VOID
90 )
91 {
92 EFI_STATUS Status;
93
94 Status = EFI_SUCCESS;
95
96 if (mTcp4Timer.RefCnt == 0) {
97
98 Status = gBS->CreateEvent (
99 EVT_TIMER | EVT_NOTIFY_SIGNAL,
100 TPL_NOTIFY,
101 TcpTicking,
102 NULL,
103 &mTcp4Timer.TimerEvent
104 );
105 if (!EFI_ERROR (Status)) {
106
107 Status = gBS->SetTimer (
108 mTcp4Timer.TimerEvent,
109 TimerPeriodic,
110 (UINT64) (TICKS_PER_SECOND / TCP_TICK_HZ)
111 );
112 }
113 }
114
115 if (!EFI_ERROR (Status)) {
116
117 mTcp4Timer.RefCnt++;
118 }
119
120 return Status;
121 }
122
123
124 /**
125 Stop and destroy the heartbeat timer for TCP driver.
126
127 None.
128
129 @return None.
130
131 **/
132 VOID
133 Tcp4DestroyTimer (
134 VOID
135 )
136 {
137 ASSERT (mTcp4Timer.RefCnt > 0);
138
139 mTcp4Timer.RefCnt--;
140
141 if (mTcp4Timer.RefCnt > 0) {
142 return;
143 }
144
145 gBS->SetTimer (mTcp4Timer.TimerEvent, TimerCancel, 0);
146 gBS->CloseEvent (mTcp4Timer.TimerEvent);
147 mTcp4Timer.TimerEvent = NULL;
148 }
149
150
151 EFI_STATUS
152 EFIAPI
153 Tcp4DriverEntryPoint (
154 IN EFI_HANDLE ImageHandle,
155 IN EFI_SYSTEM_TABLE *SystemTable
156 )
157 /*++
158
159 Routine Description:
160
161 The entry point for Tcp4 driver. used to install
162 Tcp4 driver on the ImageHandle.
163
164 Arguments:
165
166 ImageHandle - The firmware allocated handle for this
167 driver image.
168 SystemTable - Pointer to the EFI system table.
169
170 Returns:
171
172 EFI_SUCCESS - Driver loaded.
173 other - Driver not loaded.
174
175 --*/
176 {
177 EFI_STATUS Status;
178 UINT32 Seed;
179
180 //
181 // Install the TCP4 Driver Binding Protocol
182 //
183 Status = EfiLibInstallDriverBindingComponentName2 (
184 ImageHandle,
185 SystemTable,
186 &mTcp4DriverBinding,
187 ImageHandle,
188 &gTcp4ComponentName,
189 &gTcp4ComponentName2
190 );
191 ASSERT_EFI_ERROR (Status);
192 //
193 // Initialize ISS and random port.
194 //
195 Seed = NetRandomInitSeed ();
196 mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;
197 mTcp4RandomPort = (UINT16) ( TCP4_PORT_KNOWN +
198 (UINT16) (NET_RANDOM(Seed) % TCP4_PORT_KNOWN));
199
200 return Status;
201 }
202
203
204 /**
205 Test to see if this driver supports ControllerHandle.
206
207 @param This Protocol instance pointer.
208 @param ControllerHandle Handle of device to test.
209 @param RemainingDevicePath Optional parameter use to pick a specific child
210 device to start.
211
212 @retval EFI_SUCCESS This driver supports this device.
213 @retval EFI_ALREADY_STARTED This driver is already running on this device.
214 @retval other This driver does not support this device.
215
216 **/
217 EFI_STATUS
218 EFIAPI
219 Tcp4DriverBindingSupported (
220 IN EFI_DRIVER_BINDING_PROTOCOL * This,
221 IN EFI_HANDLE ControllerHandle,
222 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
223 )
224 {
225 EFI_STATUS Status;
226
227 //
228 // Test for the Tcp4ServiceBinding Protocol
229 //
230 Status = gBS->OpenProtocol (
231 ControllerHandle,
232 &gEfiTcp4ServiceBindingProtocolGuid,
233 NULL,
234 This->DriverBindingHandle,
235 ControllerHandle,
236 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
237 );
238 if (!EFI_ERROR (Status)) {
239 return EFI_ALREADY_STARTED;
240 }
241
242 //
243 // Test for the Ip4 Protocol
244 //
245 Status = gBS->OpenProtocol (
246 ControllerHandle,
247 &gEfiIp4ServiceBindingProtocolGuid,
248 NULL,
249 This->DriverBindingHandle,
250 ControllerHandle,
251 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
252 );
253
254 return Status;
255 }
256
257
258 /**
259 Start this driver on ControllerHandle.
260
261 @param This Protocol instance pointer.
262 @param ControllerHandle Handle of device to bind driver to.
263 @param RemainingDevicePath Optional parameter use to pick a specific child
264 device to start.
265
266 @retval EFI_SUCCESS The driver is added to ControllerHandle.
267 @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the
268 driver.
269 @retval other The driver cannot be added to ControllerHandle.
270
271 **/
272 EFI_STATUS
273 EFIAPI
274 Tcp4DriverBindingStart (
275 IN EFI_DRIVER_BINDING_PROTOCOL * This,
276 IN EFI_HANDLE ControllerHandle,
277 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
278 )
279 {
280 EFI_STATUS Status;
281 TCP4_SERVICE_DATA *TcpServiceData;
282 IP_IO_OPEN_DATA OpenData;
283
284 TcpServiceData = AllocateZeroPool (sizeof (TCP4_SERVICE_DATA));
285
286 if (NULL == TcpServiceData) {
287 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Have no enough"
288 " resource to create a Tcp Servcie Data!\n"));
289
290 return EFI_OUT_OF_RESOURCES;
291 }
292
293 //
294 // Create a new IP IO to Consume it
295 //
296 TcpServiceData->IpIo = IpIoCreate (This->DriverBindingHandle, ControllerHandle);
297 if (NULL == TcpServiceData->IpIo) {
298
299 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Have no enough"
300 " resource to create an Ip Io!\n"));
301
302 Status = EFI_OUT_OF_RESOURCES;
303 goto ON_ERROR;
304 }
305
306 //
307 // Configure and start IpIo.
308 //
309 ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));
310
311 CopyMem (&OpenData.IpConfigData, &mIpIoDefaultIpConfigData, sizeof (OpenData.IpConfigData));
312 OpenData.IpConfigData.DefaultProtocol = EFI_IP_PROTO_TCP;
313
314 OpenData.PktRcvdNotify = Tcp4RxCallback;
315 Status = IpIoOpen (TcpServiceData->IpIo, &OpenData);
316
317 if (EFI_ERROR (Status)) {
318 goto ON_ERROR;
319 }
320
321 //
322 // Create the timer event used by TCP driver
323 //
324 Status = Tcp4CreateTimer ();
325 if (EFI_ERROR (Status)) {
326
327 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Create TcpTimer"
328 " Event failed with %r\n", Status));
329
330 goto ON_ERROR;
331 }
332
333 //
334 // Install the Tcp4ServiceBinding Protocol on the
335 // controller handle
336 //
337 TcpServiceData->Tcp4ServiceBinding = mTcp4ServiceBinding;
338
339 Status = gBS->InstallMultipleProtocolInterfaces (
340 &ControllerHandle,
341 &gEfiTcp4ServiceBindingProtocolGuid,
342 &TcpServiceData->Tcp4ServiceBinding,
343 NULL
344 );
345 if (EFI_ERROR (Status)) {
346
347 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Install Tcp4 Service Binding"
348 " Protocol failed for %r\n", Status));
349
350 Tcp4DestroyTimer ();
351 goto ON_ERROR;
352 }
353
354 //
355 // Initialize member in TcpServiceData
356 //
357 TcpServiceData->ControllerHandle = ControllerHandle;
358 TcpServiceData->Signature = TCP4_DRIVER_SIGNATURE;
359 TcpServiceData->DriverBindingHandle = This->DriverBindingHandle;
360
361 InitializeListHead (&TcpServiceData->SocketList);
362
363 TcpSetVariableData (TcpServiceData);
364
365 return EFI_SUCCESS;
366
367 ON_ERROR:
368
369 if (TcpServiceData->IpIo != NULL) {
370 IpIoDestroy (TcpServiceData->IpIo);
371 }
372
373 gBS->FreePool (TcpServiceData);
374
375 return Status;
376 }
377
378
379 /**
380 Stop this driver on ControllerHandle.
381
382 @param This Protocol instance pointer.
383 @param ControllerHandle Handle of device to stop driver on.
384 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
385 of children is zero stop the entire bus driver.
386 @param ChildHandleBuffer List of Child Handles to Stop.
387
388 @retval EFI_SUCCESS This driver is removed from ControllerHandle.
389 @retval other This driver is not removed from ControllerHandle.
390
391 **/
392 EFI_STATUS
393 EFIAPI
394 Tcp4DriverBindingStop (
395 IN EFI_DRIVER_BINDING_PROTOCOL *This,
396 IN EFI_HANDLE ControllerHandle,
397 IN UINTN NumberOfChildren,
398 IN EFI_HANDLE *ChildHandleBuffer
399 )
400 {
401 EFI_STATUS Status;
402 EFI_HANDLE NicHandle;
403 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
404 TCP4_SERVICE_DATA *TcpServiceData;
405 SOCKET *Sock;
406
407 // Find the NicHandle where Tcp4 ServiceBinding Protocol is installed.
408 //
409 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
410 if (NicHandle == NULL) {
411 return EFI_DEVICE_ERROR;
412 }
413
414 //
415 // Retrieve the TCP driver Data Structure
416 //
417 Status = gBS->OpenProtocol (
418 NicHandle,
419 &gEfiTcp4ServiceBindingProtocolGuid,
420 (VOID **) &ServiceBinding,
421 This->DriverBindingHandle,
422 ControllerHandle,
423 EFI_OPEN_PROTOCOL_GET_PROTOCOL
424 );
425 if (EFI_ERROR (Status)) {
426
427 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStop: Locate Tcp4 Service "
428 " Binding Protocol failed with %r\n", Status));
429
430 return EFI_DEVICE_ERROR;
431 }
432
433 TcpServiceData = TCP4_FROM_THIS (ServiceBinding);
434
435 if (NumberOfChildren == 0) {
436 //
437 // Uninstall TCP servicebinding protocol
438 //
439 gBS->UninstallMultipleProtocolInterfaces (
440 NicHandle,
441 &gEfiTcp4ServiceBindingProtocolGuid,
442 ServiceBinding,
443 NULL
444 );
445
446 //
447 // Destroy the IpIO consumed by TCP driver
448 //
449 IpIoDestroy (TcpServiceData->IpIo);
450
451 //
452 // Destroy the heartbeat timer.
453 //
454 Tcp4DestroyTimer ();
455
456 //
457 // Clear the variable.
458 //
459 TcpClearVariableData (TcpServiceData);
460
461 //
462 // Release the TCP service data
463 //
464 gBS->FreePool (TcpServiceData);
465 } else {
466
467 while (!IsListEmpty (&TcpServiceData->SocketList)) {
468 Sock = NET_LIST_HEAD (&TcpServiceData->SocketList, SOCKET, Link);
469
470 ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);
471 }
472 }
473
474 return Status;
475 }
476
477 EFI_STATUS
478 Tcp4CreateSocketCallback (
479 IN SOCKET *This,
480 IN VOID *Context
481 )
482 {
483 EFI_STATUS Status;
484 TCP4_SERVICE_DATA *TcpServiceData;
485 EFI_IP4_PROTOCOL *Ip4;
486
487 TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService;
488
489 //
490 // Open the default Ip4 protocol of IP_IO BY_DRIVER.
491 //
492 Status = gBS->OpenProtocol (
493 TcpServiceData->IpIo->ChildHandle,
494 &gEfiIp4ProtocolGuid,
495 (VOID **) &Ip4,
496 TcpServiceData->DriverBindingHandle,
497 This->SockHandle,
498 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
499 );
500 if (EFI_ERROR (Status)) {
501 return Status;
502 }
503
504 //
505 // Open the device path on the handle where service binding resides on.
506 //
507 Status = gBS->OpenProtocol (
508 TcpServiceData->ControllerHandle,
509 &gEfiDevicePathProtocolGuid,
510 (VOID **) &This->ParentDevicePath,
511 TcpServiceData->DriverBindingHandle,
512 This->SockHandle,
513 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
514 );
515 if (EFI_ERROR (Status)) {
516 gBS->CloseProtocol (
517 TcpServiceData->IpIo->ChildHandle,
518 &gEfiIp4ProtocolGuid,
519 TcpServiceData->DriverBindingHandle,
520 This->SockHandle
521 );
522 } else {
523 //
524 // Insert this socket into the SocketList.
525 //
526 InsertTailList (&TcpServiceData->SocketList, &This->Link);
527 }
528
529 return Status;
530 }
531
532 VOID
533 Tcp4DestroySocketCallback (
534 IN SOCKET *This,
535 IN VOID *Context
536 )
537 {
538 TCP4_SERVICE_DATA *TcpServiceData;
539
540 TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService;
541
542 //
543 // Remove this node from the list.
544 //
545 RemoveEntryList (&This->Link);
546
547 //
548 // Close the device path protocol
549 //
550 gBS->CloseProtocol (
551 TcpServiceData->ControllerHandle,
552 &gEfiDevicePathProtocolGuid,
553 TcpServiceData->DriverBindingHandle,
554 This->SockHandle
555 );
556
557 //
558 // Close the Ip4 protocol.
559 //
560 gBS->CloseProtocol (
561 TcpServiceData->IpIo->ChildHandle,
562 &gEfiIp4ProtocolGuid,
563 TcpServiceData->DriverBindingHandle,
564 This->SockHandle
565 );
566 }
567
568 /**
569 Creates a child handle with a set of TCP4 services.
570
571 @param This Protocol instance pointer.
572 @param ChildHandle Pointer to the handle of the child to create. If
573 it is NULL, then a new handle is created. If it is
574 not NULL, then the I/O services are added to the
575 existing child handle.
576
577 @retval EFI_SUCCESS The child handle is created.
578 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
579 @retval EFI_OUT_OF_RESOURCES There are not enough resources to create the
580 child.
581
582 **/
583 EFI_STATUS
584 EFIAPI
585 Tcp4ServiceBindingCreateChild (
586 IN EFI_SERVICE_BINDING_PROTOCOL *This,
587 IN EFI_HANDLE *ChildHandle
588 )
589 {
590 SOCKET *Sock;
591 TCP4_SERVICE_DATA *TcpServiceData;
592 TCP4_PROTO_DATA TcpProto;
593 EFI_STATUS Status;
594 EFI_TPL OldTpl;
595
596 if (NULL == This || NULL == ChildHandle) {
597 return EFI_INVALID_PARAMETER;
598 }
599
600 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
601 Status = EFI_SUCCESS;
602 TcpServiceData = TCP4_FROM_THIS (This);
603 TcpProto.TcpService = TcpServiceData;
604 TcpProto.TcpPcb = NULL;
605
606 //
607 // Create a tcp instance with defualt Tcp default
608 // sock init data and TcpProto
609 //
610 mTcp4DefaultSockData.ProtoData = &TcpProto;
611 mTcp4DefaultSockData.DataSize = sizeof (TCP4_PROTO_DATA);
612 mTcp4DefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;
613
614 Sock = SockCreateChild (&mTcp4DefaultSockData);
615 if (NULL == Sock) {
616 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingCreateChild: "
617 "No resource to create a Tcp Child\n"));
618
619 Status = EFI_OUT_OF_RESOURCES;
620 } else {
621 *ChildHandle = Sock->SockHandle;
622 }
623
624 gBS->RestoreTPL (OldTpl);
625 return Status;
626 }
627
628
629 /**
630 Destroys a child handle with a set of UDP4 services.
631
632 @param This Protocol instance pointer.
633 @param ChildHandle Handle of the child to be destroyed.
634
635 @retval EFI_SUCCESS The TCP4 services are removed from the child
636 handle.
637 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
638 @retval other The child handle is not destroyed.
639
640 **/
641 EFI_STATUS
642 EFIAPI
643 Tcp4ServiceBindingDestroyChild (
644 IN EFI_SERVICE_BINDING_PROTOCOL *This,
645 IN EFI_HANDLE ChildHandle
646 )
647 {
648 EFI_STATUS Status;
649 EFI_TCP4_PROTOCOL *Tcp4;
650 SOCKET *Sock;
651 EFI_TPL OldTpl;
652
653 if (NULL == This || NULL == ChildHandle) {
654 return EFI_INVALID_PARAMETER;
655 }
656
657 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
658
659 //
660 // retrieve the Tcp4 protocol from ChildHandle
661 //
662 Status = gBS->OpenProtocol (
663 ChildHandle,
664 &gEfiTcp4ProtocolGuid,
665 (VOID **) &Tcp4,
666 mTcp4DriverBinding.DriverBindingHandle,
667 ChildHandle,
668 EFI_OPEN_PROTOCOL_GET_PROTOCOL
669 );
670 if (EFI_ERROR (Status)) {
671 Status = EFI_UNSUPPORTED;
672 } else {
673 //
674 // destroy this sock and related Tcp protocol control
675 // block
676 //
677 Sock = SOCK_FROM_THIS (Tcp4);
678
679 SockDestroyChild (Sock);
680 }
681
682 gBS->RestoreTPL (OldTpl);
683 return Status;
684 }
685