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