]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.c
Fix coding style issues for Tcp4Dxe driver.
[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 None
130
131 **/
132 VOID
133 Tcp4DestroyTimer ()
134 {
135 ASSERT (mTcp4Timer.RefCnt > 0);
136
137 mTcp4Timer.RefCnt--;
138
139 if (mTcp4Timer.RefCnt > 0) {
140 return;
141 }
142
143 gBS->SetTimer (mTcp4Timer.TimerEvent, TimerCancel, 0);
144 gBS->CloseEvent (mTcp4Timer.TimerEvent);
145 mTcp4Timer.TimerEvent = NULL;
146 }
147
148 /**
149 The entry point for Tcp4 driver.
150 Used to install Tcp4 driver on the ImageHandle.
151
152 @param ImageHandle The firmware allocated handle for this
153 driver image.
154 @param SystemTable Pointer to the EFI system table.
155
156 @retval EFI_SUCCESS Driver loaded.
157 @retval other Driver not loaded.
158
159 **/
160 EFI_STATUS
161 EFIAPI
162 Tcp4DriverEntryPoint (
163 IN EFI_HANDLE ImageHandle,
164 IN EFI_SYSTEM_TABLE *SystemTable
165 )
166 {
167 EFI_STATUS Status;
168 UINT32 Seed;
169
170 //
171 // Install the TCP4 Driver Binding Protocol
172 //
173 Status = EfiLibInstallDriverBindingComponentName2 (
174 ImageHandle,
175 SystemTable,
176 &mTcp4DriverBinding,
177 ImageHandle,
178 &gTcp4ComponentName,
179 &gTcp4ComponentName2
180 );
181 ASSERT_EFI_ERROR (Status);
182 //
183 // Initialize ISS and random port.
184 //
185 Seed = NetRandomInitSeed ();
186 mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;
187 mTcp4RandomPort = (UINT16) ( TCP4_PORT_KNOWN +
188 (UINT16) (NET_RANDOM(Seed) % TCP4_PORT_KNOWN));
189
190 return Status;
191 }
192
193
194 /**
195 Test to see if this driver supports ControllerHandle.
196
197 @param This Protocol instance pointer.
198 @param ControllerHandle Handle of device to test.
199 @param RemainingDevicePath Optional parameter use to pick a specific child
200 device to start.
201
202 @retval EFI_SUCCESS This driver supports this device.
203 @retval EFI_ALREADY_STARTED This driver is already running on this device.
204 @retval other This driver does not support this device.
205
206 **/
207 EFI_STATUS
208 EFIAPI
209 Tcp4DriverBindingSupported (
210 IN EFI_DRIVER_BINDING_PROTOCOL * This,
211 IN EFI_HANDLE ControllerHandle,
212 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
213 )
214 {
215 EFI_STATUS Status;
216
217 //
218 // Test for the Tcp4ServiceBinding Protocol
219 //
220 Status = gBS->OpenProtocol (
221 ControllerHandle,
222 &gEfiTcp4ServiceBindingProtocolGuid,
223 NULL,
224 This->DriverBindingHandle,
225 ControllerHandle,
226 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
227 );
228 if (!EFI_ERROR (Status)) {
229 return EFI_ALREADY_STARTED;
230 }
231
232 //
233 // Test for the Ip4 Protocol
234 //
235 Status = gBS->OpenProtocol (
236 ControllerHandle,
237 &gEfiIp4ServiceBindingProtocolGuid,
238 NULL,
239 This->DriverBindingHandle,
240 ControllerHandle,
241 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
242 );
243
244 return Status;
245 }
246
247
248 /**
249 Start this driver on ControllerHandle.
250
251 @param This Protocol instance pointer.
252 @param ControllerHandle Handle of device to bind driver to.
253 @param RemainingDevicePath Optional parameter use to pick a specific child
254 device to start.
255
256 @retval EFI_SUCCESS The driver is added to ControllerHandle.
257 @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the
258 driver.
259 @retval other The driver cannot be added to ControllerHandle.
260
261 **/
262 EFI_STATUS
263 EFIAPI
264 Tcp4DriverBindingStart (
265 IN EFI_DRIVER_BINDING_PROTOCOL * This,
266 IN EFI_HANDLE ControllerHandle,
267 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
268 )
269 {
270 EFI_STATUS Status;
271 TCP4_SERVICE_DATA *TcpServiceData;
272 IP_IO_OPEN_DATA OpenData;
273
274 TcpServiceData = AllocateZeroPool (sizeof (TCP4_SERVICE_DATA));
275
276 if (NULL == TcpServiceData) {
277 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Have no enough"
278 " resource to create a Tcp Servcie Data!\n"));
279
280 return EFI_OUT_OF_RESOURCES;
281 }
282
283 //
284 // Create a new IP IO to Consume it
285 //
286 TcpServiceData->IpIo = IpIoCreate (This->DriverBindingHandle, ControllerHandle);
287 if (NULL == TcpServiceData->IpIo) {
288
289 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Have no enough"
290 " resource to create an Ip Io!\n"));
291
292 Status = EFI_OUT_OF_RESOURCES;
293 goto ON_ERROR;
294 }
295
296 //
297 // Configure and start IpIo.
298 //
299 ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));
300
301 CopyMem (&OpenData.IpConfigData, &mIpIoDefaultIpConfigData, sizeof (OpenData.IpConfigData));
302 OpenData.IpConfigData.DefaultProtocol = EFI_IP_PROTO_TCP;
303
304 OpenData.PktRcvdNotify = Tcp4RxCallback;
305 Status = IpIoOpen (TcpServiceData->IpIo, &OpenData);
306
307 if (EFI_ERROR (Status)) {
308 goto ON_ERROR;
309 }
310
311 //
312 // Create the timer event used by TCP driver
313 //
314 Status = Tcp4CreateTimer ();
315 if (EFI_ERROR (Status)) {
316
317 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Create TcpTimer"
318 " Event failed with %r\n", Status));
319
320 goto ON_ERROR;
321 }
322
323 //
324 // Install the Tcp4ServiceBinding Protocol on the
325 // controller handle
326 //
327 TcpServiceData->Tcp4ServiceBinding = mTcp4ServiceBinding;
328
329 Status = gBS->InstallMultipleProtocolInterfaces (
330 &ControllerHandle,
331 &gEfiTcp4ServiceBindingProtocolGuid,
332 &TcpServiceData->Tcp4ServiceBinding,
333 NULL
334 );
335 if (EFI_ERROR (Status)) {
336
337 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Install Tcp4 Service Binding"
338 " Protocol failed for %r\n", Status));
339
340 Tcp4DestroyTimer ();
341 goto ON_ERROR;
342 }
343
344 //
345 // Initialize member in TcpServiceData
346 //
347 TcpServiceData->ControllerHandle = ControllerHandle;
348 TcpServiceData->Signature = TCP4_DRIVER_SIGNATURE;
349 TcpServiceData->DriverBindingHandle = This->DriverBindingHandle;
350
351 InitializeListHead (&TcpServiceData->SocketList);
352
353 TcpSetVariableData (TcpServiceData);
354
355 return EFI_SUCCESS;
356
357 ON_ERROR:
358
359 if (TcpServiceData->IpIo != NULL) {
360 IpIoDestroy (TcpServiceData->IpIo);
361 }
362
363 gBS->FreePool (TcpServiceData);
364
365 return Status;
366 }
367
368
369 /**
370 Stop this driver on ControllerHandle.
371
372 @param This Protocol instance pointer.
373 @param ControllerHandle Handle of device to stop driver on.
374 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
375 of children is zero stop the entire bus driver.
376 @param ChildHandleBuffer List of Child Handles to Stop.
377
378 @retval EFI_SUCCESS This driver is removed from ControllerHandle.
379 @retval other This driver is not removed from ControllerHandle.
380
381 **/
382 EFI_STATUS
383 EFIAPI
384 Tcp4DriverBindingStop (
385 IN EFI_DRIVER_BINDING_PROTOCOL *This,
386 IN EFI_HANDLE ControllerHandle,
387 IN UINTN NumberOfChildren,
388 IN EFI_HANDLE *ChildHandleBuffer
389 )
390 {
391 EFI_STATUS Status;
392 EFI_HANDLE NicHandle;
393 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
394 TCP4_SERVICE_DATA *TcpServiceData;
395 SOCKET *Sock;
396
397 // Find the NicHandle where Tcp4 ServiceBinding Protocol is installed.
398 //
399 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
400 if (NicHandle == NULL) {
401 return EFI_DEVICE_ERROR;
402 }
403
404 //
405 // Retrieve the TCP driver Data Structure
406 //
407 Status = gBS->OpenProtocol (
408 NicHandle,
409 &gEfiTcp4ServiceBindingProtocolGuid,
410 (VOID **) &ServiceBinding,
411 This->DriverBindingHandle,
412 ControllerHandle,
413 EFI_OPEN_PROTOCOL_GET_PROTOCOL
414 );
415 if (EFI_ERROR (Status)) {
416
417 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStop: Locate Tcp4 Service "
418 " Binding Protocol failed with %r\n", Status));
419
420 return EFI_DEVICE_ERROR;
421 }
422
423 TcpServiceData = TCP4_FROM_THIS (ServiceBinding);
424
425 if (NumberOfChildren == 0) {
426 //
427 // Uninstall TCP servicebinding protocol
428 //
429 gBS->UninstallMultipleProtocolInterfaces (
430 NicHandle,
431 &gEfiTcp4ServiceBindingProtocolGuid,
432 ServiceBinding,
433 NULL
434 );
435
436 //
437 // Destroy the IpIO consumed by TCP driver
438 //
439 IpIoDestroy (TcpServiceData->IpIo);
440
441 //
442 // Destroy the heartbeat timer.
443 //
444 Tcp4DestroyTimer ();
445
446 //
447 // Clear the variable.
448 //
449 TcpClearVariableData (TcpServiceData);
450
451 //
452 // Release the TCP service data
453 //
454 gBS->FreePool (TcpServiceData);
455 } else {
456
457 while (!IsListEmpty (&TcpServiceData->SocketList)) {
458 Sock = NET_LIST_HEAD (&TcpServiceData->SocketList, SOCKET, Link);
459
460 ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);
461 }
462 }
463
464 return Status;
465 }
466
467 EFI_STATUS
468 Tcp4CreateSocketCallback (
469 IN SOCKET *This,
470 IN VOID *Context
471 )
472 {
473 EFI_STATUS Status;
474 TCP4_SERVICE_DATA *TcpServiceData;
475 EFI_IP4_PROTOCOL *Ip4;
476
477 TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService;
478
479 //
480 // Open the default Ip4 protocol of IP_IO BY_DRIVER.
481 //
482 Status = gBS->OpenProtocol (
483 TcpServiceData->IpIo->ChildHandle,
484 &gEfiIp4ProtocolGuid,
485 (VOID **) &Ip4,
486 TcpServiceData->DriverBindingHandle,
487 This->SockHandle,
488 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
489 );
490 if (EFI_ERROR (Status)) {
491 return Status;
492 }
493
494 //
495 // Open the device path on the handle where service binding resides on.
496 //
497 Status = gBS->OpenProtocol (
498 TcpServiceData->ControllerHandle,
499 &gEfiDevicePathProtocolGuid,
500 (VOID **) &This->ParentDevicePath,
501 TcpServiceData->DriverBindingHandle,
502 This->SockHandle,
503 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
504 );
505 if (EFI_ERROR (Status)) {
506 gBS->CloseProtocol (
507 TcpServiceData->IpIo->ChildHandle,
508 &gEfiIp4ProtocolGuid,
509 TcpServiceData->DriverBindingHandle,
510 This->SockHandle
511 );
512 } else {
513 //
514 // Insert this socket into the SocketList.
515 //
516 InsertTailList (&TcpServiceData->SocketList, &This->Link);
517 }
518
519 return Status;
520 }
521
522 VOID
523 Tcp4DestroySocketCallback (
524 IN SOCKET *This,
525 IN VOID *Context
526 )
527 {
528 TCP4_SERVICE_DATA *TcpServiceData;
529
530 TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService;
531
532 //
533 // Remove this node from the list.
534 //
535 RemoveEntryList (&This->Link);
536
537 //
538 // Close the device path protocol
539 //
540 gBS->CloseProtocol (
541 TcpServiceData->ControllerHandle,
542 &gEfiDevicePathProtocolGuid,
543 TcpServiceData->DriverBindingHandle,
544 This->SockHandle
545 );
546
547 //
548 // Close the Ip4 protocol.
549 //
550 gBS->CloseProtocol (
551 TcpServiceData->IpIo->ChildHandle,
552 &gEfiIp4ProtocolGuid,
553 TcpServiceData->DriverBindingHandle,
554 This->SockHandle
555 );
556 }
557
558 /**
559 Creates a child handle with a set of TCP4 services.
560
561 @param This Protocol instance pointer.
562 @param ChildHandle Pointer to the handle of the child to create. If
563 it is NULL, then a new handle is created. If it is
564 not NULL, then the I/O services are added to the
565 existing child handle.
566
567 @retval EFI_SUCCESS The child handle is created.
568 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
569 @retval EFI_OUT_OF_RESOURCES There are not enough resources to create the
570 child.
571
572 **/
573 EFI_STATUS
574 EFIAPI
575 Tcp4ServiceBindingCreateChild (
576 IN EFI_SERVICE_BINDING_PROTOCOL *This,
577 IN EFI_HANDLE *ChildHandle
578 )
579 {
580 SOCKET *Sock;
581 TCP4_SERVICE_DATA *TcpServiceData;
582 TCP4_PROTO_DATA TcpProto;
583 EFI_STATUS Status;
584 EFI_TPL OldTpl;
585
586 if (NULL == This || NULL == ChildHandle) {
587 return EFI_INVALID_PARAMETER;
588 }
589
590 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
591 Status = EFI_SUCCESS;
592 TcpServiceData = TCP4_FROM_THIS (This);
593 TcpProto.TcpService = TcpServiceData;
594 TcpProto.TcpPcb = NULL;
595
596 //
597 // Create a tcp instance with defualt Tcp default
598 // sock init data and TcpProto
599 //
600 mTcp4DefaultSockData.ProtoData = &TcpProto;
601 mTcp4DefaultSockData.DataSize = sizeof (TCP4_PROTO_DATA);
602 mTcp4DefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;
603
604 Sock = SockCreateChild (&mTcp4DefaultSockData);
605 if (NULL == Sock) {
606 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingCreateChild: "
607 "No resource to create a Tcp Child\n"));
608
609 Status = EFI_OUT_OF_RESOURCES;
610 } else {
611 *ChildHandle = Sock->SockHandle;
612 }
613
614 gBS->RestoreTPL (OldTpl);
615 return Status;
616 }
617
618
619 /**
620 Destroys a child handle with a set of UDP4 services.
621
622 @param This Protocol instance pointer.
623 @param ChildHandle Handle of the child to be destroyed.
624
625 @retval EFI_SUCCESS The TCP4 services are removed from the child
626 handle.
627 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
628 @retval other The child handle is not destroyed.
629
630 **/
631 EFI_STATUS
632 EFIAPI
633 Tcp4ServiceBindingDestroyChild (
634 IN EFI_SERVICE_BINDING_PROTOCOL *This,
635 IN EFI_HANDLE ChildHandle
636 )
637 {
638 EFI_STATUS Status;
639 EFI_TCP4_PROTOCOL *Tcp4;
640 SOCKET *Sock;
641 EFI_TPL OldTpl;
642
643 if (NULL == This || NULL == ChildHandle) {
644 return EFI_INVALID_PARAMETER;
645 }
646
647 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
648
649 //
650 // retrieve the Tcp4 protocol from ChildHandle
651 //
652 Status = gBS->OpenProtocol (
653 ChildHandle,
654 &gEfiTcp4ProtocolGuid,
655 (VOID **) &Tcp4,
656 mTcp4DriverBinding.DriverBindingHandle,
657 ChildHandle,
658 EFI_OPEN_PROTOCOL_GET_PROTOCOL
659 );
660 if (EFI_ERROR (Status)) {
661 Status = EFI_UNSUPPORTED;
662 } else {
663 //
664 // destroy this sock and related Tcp protocol control
665 // block
666 //
667 Sock = SOCK_FROM_THIS (Tcp4);
668
669 SockDestroyChild (Sock);
670 }
671
672 gBS->RestoreTPL (OldTpl);
673 return Status;
674 }
675