]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Driver.c
Fixed one bug when calculating timeout value in timeout function for UDP protocol.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Udp4Dxe / Udp4Driver.c
1 /** @file
2
3 Copyright (c) 2006, 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 Udp4Driver.c
15
16 Abstract:
17
18
19 **/
20
21
22 #include "Udp4Impl.h"
23
24 EFI_DRIVER_BINDING_PROTOCOL gUdp4DriverBinding = {
25 Udp4DriverBindingSupported,
26 Udp4DriverBindingStart,
27 Udp4DriverBindingStop,
28 0xa,
29 NULL,
30 NULL
31 };
32
33 EFI_SERVICE_BINDING_PROTOCOL mUdp4ServiceBinding = {
34 Udp4ServiceBindingCreateChild,
35 Udp4ServiceBindingDestroyChild
36 };
37
38
39 /**
40 Test to see if this driver supports ControllerHandle. This service
41 is called by the EFI boot service ConnectController(). In
42 order to make drivers as small as possible, there are a few calling
43 restrictions for this service. ConnectController() must
44 follow these calling restrictions. If any other agent wishes to call
45 Supported() it must also follow these calling restrictions.
46
47 @param This Protocol instance pointer.
48 @param ControllerHandle Handle of device to test
49 @param RemainingDevicePath Optional parameter use to pick a specific child
50 device to start.
51
52 @retval EFI_SUCCESS This driver supports this device
53 @retval EFI_ALREADY_STARTED This driver is already running on this device
54 @retval other This driver does not support this device
55
56 **/
57 EFI_STATUS
58 EFIAPI
59 Udp4DriverBindingSupported (
60 IN EFI_DRIVER_BINDING_PROTOCOL *This,
61 IN EFI_HANDLE ControllerHandle,
62 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
63 )
64 {
65 EFI_STATUS Status;
66
67 //
68 // Test for the Udp4ServiceBinding Protocol
69 //
70 Status = gBS->OpenProtocol (
71 ControllerHandle,
72 &gEfiUdp4ServiceBindingProtocolGuid,
73 NULL,
74 This->DriverBindingHandle,
75 ControllerHandle,
76 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
77 );
78 if (!EFI_ERROR (Status)) {
79 return EFI_ALREADY_STARTED;
80 }
81
82 //
83 // Test for the Ip4 Protocol
84 //
85 Status = gBS->OpenProtocol (
86 ControllerHandle,
87 &gEfiIp4ServiceBindingProtocolGuid,
88 NULL,
89 This->DriverBindingHandle,
90 ControllerHandle,
91 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
92 );
93
94 return Status;
95 }
96
97
98 /**
99 Start this driver on ControllerHandle. This service is called by the
100 EFI boot service ConnectController(). In order to make
101 drivers as small as possible, there are a few calling restrictions for
102 this service. ConnectController() must follow these
103 calling restrictions. If any other agent wishes to call Start() it
104 must also follow these calling restrictions.
105
106 @param This Protocol instance pointer.
107 @param ControllerHandle Handle of device to bind driver to
108 @param RemainingDevicePath Optional parameter use to pick a specific child
109 device to start.
110
111 @retval EFI_SUCCESS This driver is added to ControllerHandle
112 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
113 @retval other This driver does not support this device
114
115 **/
116 EFI_STATUS
117 EFIAPI
118 Udp4DriverBindingStart (
119 IN EFI_DRIVER_BINDING_PROTOCOL *This,
120 IN EFI_HANDLE ControllerHandle,
121 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
122 )
123 {
124 EFI_STATUS Status;
125 UDP4_SERVICE_DATA *Udp4Service;
126
127 //
128 // Allocate Private Context Data Structure.
129 //
130 Udp4Service = AllocatePool (sizeof (UDP4_SERVICE_DATA));
131 if (Udp4Service == NULL) {
132 return EFI_OUT_OF_RESOURCES;
133 }
134
135 Status = Udp4CreateService (Udp4Service, This->DriverBindingHandle, ControllerHandle);
136 if (EFI_ERROR (Status)) {
137 gBS->FreePool (Udp4Service);
138 return Status;
139 }
140
141 //
142 // Install the Udp4ServiceBindingProtocol on the ControllerHandle.
143 //
144 Status = gBS->InstallMultipleProtocolInterfaces (
145 &ControllerHandle,
146 &gEfiUdp4ServiceBindingProtocolGuid,
147 &Udp4Service->ServiceBinding,
148 NULL
149 );
150 if (EFI_ERROR (Status)) {
151 Udp4CleanService (Udp4Service);
152 gBS->FreePool (Udp4Service);
153 } else {
154 Udp4SetVariableData (Udp4Service);
155 }
156
157 return Status;
158 }
159
160
161 /**
162 Stop this driver on ControllerHandle. This service is called by the
163 EFI boot service DisconnectController(). In order to
164 make drivers as small as possible, there are a few calling
165 restrictions for this service. DisconnectController()
166 must follow these calling restrictions. If any other agent wishes
167 to call Stop() it must also follow these calling restrictions.
168
169 @param This Protocol instance pointer.
170 @param ControllerHandle Handle of device to stop driver on
171 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
172 children is zero stop the entire bus driver.
173 @param ChildHandleBuffer List of Child Handles to Stop.
174
175 @retval EFI_SUCCESS This driver is removed ControllerHandle
176 @retval other This driver was not removed from this device
177
178 **/
179 EFI_STATUS
180 EFIAPI
181 Udp4DriverBindingStop (
182 IN EFI_DRIVER_BINDING_PROTOCOL *This,
183 IN EFI_HANDLE ControllerHandle,
184 IN UINTN NumberOfChildren,
185 IN EFI_HANDLE *ChildHandleBuffer
186 )
187 {
188 EFI_STATUS Status;
189 EFI_HANDLE NicHandle;
190 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
191 UDP4_SERVICE_DATA *Udp4Service;
192 UDP4_INSTANCE_DATA *Instance;
193
194 //
195 // Find the NicHandle where UDP4 ServiceBinding Protocol is installed.
196 //
197 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
198 if (NicHandle == NULL) {
199 return EFI_DEVICE_ERROR;
200 }
201
202 //
203 // Retrieve the UDP4 ServiceBinding Protocol.
204 //
205 Status = gBS->OpenProtocol (
206 NicHandle,
207 &gEfiUdp4ServiceBindingProtocolGuid,
208 (VOID **) &ServiceBinding,
209 This->DriverBindingHandle,
210 NicHandle,
211 EFI_OPEN_PROTOCOL_GET_PROTOCOL
212 );
213 if (EFI_ERROR (Status)) {
214 return EFI_DEVICE_ERROR;
215 }
216
217 Udp4Service = UDP4_SERVICE_DATA_FROM_THIS (ServiceBinding);
218
219 if (NumberOfChildren == 0) {
220
221 gBS->UninstallMultipleProtocolInterfaces (
222 NicHandle,
223 &gEfiUdp4ServiceBindingProtocolGuid,
224 &Udp4Service->ServiceBinding,
225 NULL
226 );
227
228 Udp4ClearVariableData (Udp4Service);
229
230 Udp4CleanService (Udp4Service);
231
232 gBS->FreePool (Udp4Service);
233 } else {
234
235 while (!IsListEmpty (&Udp4Service->ChildrenList)) {
236 Instance = NET_LIST_HEAD (&Udp4Service->ChildrenList, UDP4_INSTANCE_DATA, Link);
237
238 ServiceBinding->DestroyChild (ServiceBinding, Instance->ChildHandle);
239 }
240 }
241
242 return Status;
243 }
244
245
246 /**
247 Creates a child handle with a set of I/O services.
248
249 @param This Protocol instance pointer.
250 @param ChildHandle Pointer to the handle of the child to create. If it is NULL,
251 then a new handle is created. If it is not NULL, then the
252 I/O services are added to the existing child handle.
253
254 @retval EFI_SUCCES The child handle was created with the I/O services
255 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
256 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
257 the child
258 @retval other The child handle was not created
259
260 **/
261 EFI_STATUS
262 EFIAPI
263 Udp4ServiceBindingCreateChild (
264 IN EFI_SERVICE_BINDING_PROTOCOL *This,
265 IN EFI_HANDLE *ChildHandle
266 )
267 {
268 EFI_STATUS Status;
269 UDP4_SERVICE_DATA *Udp4Service;
270 UDP4_INSTANCE_DATA *Instance;
271 EFI_TPL OldTpl;
272 VOID *Ip4;
273
274 if ((This == NULL) || (ChildHandle == NULL)) {
275 return EFI_INVALID_PARAMETER;
276 }
277
278 Udp4Service = UDP4_SERVICE_DATA_FROM_THIS (This);
279
280 //
281 // Allocate the instance private data structure.
282 //
283 Instance = AllocateZeroPool (sizeof (UDP4_INSTANCE_DATA));
284 if (Instance == NULL) {
285 return EFI_OUT_OF_RESOURCES;
286 }
287
288 Udp4InitInstance (Udp4Service, Instance);
289
290 //
291 // Add an IpInfo for this instance.
292 //
293 Instance->IpInfo = IpIoAddIp (Udp4Service->IpIo);
294 if (Instance->IpInfo == NULL) {
295 Status = EFI_OUT_OF_RESOURCES;
296 goto ON_ERROR;
297 }
298
299 //
300 // Install the Udp4Protocol for this instance.
301 //
302 Status = gBS->InstallMultipleProtocolInterfaces (
303 ChildHandle,
304 &gEfiUdp4ProtocolGuid,
305 &Instance->Udp4Proto,
306 NULL
307 );
308 if (EFI_ERROR (Status)) {
309 goto ON_ERROR;
310 }
311
312 Instance->ChildHandle = *ChildHandle;
313
314 //
315 // Open the default Ip4 protocol in the IP_IO BY_CHILD.
316 //
317 Status = gBS->OpenProtocol (
318 Udp4Service->IpIo->ChildHandle,
319 &gEfiIp4ProtocolGuid,
320 (VOID **) &Ip4,
321 gUdp4DriverBinding.DriverBindingHandle,
322 Instance->ChildHandle,
323 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
324 );
325 if (EFI_ERROR (Status)) {
326 goto ON_ERROR;
327 }
328
329 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
330
331 //
332 // Link this instance into the service context data and increase the ChildrenNumber.
333 //
334 InsertTailList (&Udp4Service->ChildrenList, &Instance->Link);
335 Udp4Service->ChildrenNumber++;
336
337 gBS->RestoreTPL (OldTpl);
338
339 return EFI_SUCCESS;
340
341 ON_ERROR:
342
343 if (Instance->ChildHandle != NULL) {
344 gBS->UninstallMultipleProtocolInterfaces (
345 Instance->ChildHandle,
346 &gEfiUdp4ProtocolGuid,
347 &Instance->Udp4Proto,
348 NULL
349 );
350 }
351
352 if (Instance->IpInfo != NULL) {
353 IpIoRemoveIp (Udp4Service->IpIo, Instance->IpInfo);
354 }
355
356 Udp4CleanInstance (Instance);
357
358 gBS->FreePool (Instance);
359
360 return Status;
361 }
362
363
364 /**
365 Destroys a child handle with a set of I/O services.
366
367 @param This Protocol instance pointer.
368 @param ChildHandle Handle of the child to destroy
369
370 @retval EFI_SUCCES The I/O services were removed from the child handle
371 @retval EFI_UNSUPPORTED The child handle does not support the I/O services
372 that are being removed.
373 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
374 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because its
375 I/O services are being used.
376 @retval other The child handle was not destroyed
377
378 **/
379 EFI_STATUS
380 EFIAPI
381 Udp4ServiceBindingDestroyChild (
382 IN EFI_SERVICE_BINDING_PROTOCOL *This,
383 IN EFI_HANDLE ChildHandle
384 )
385 {
386 EFI_STATUS Status;
387 UDP4_SERVICE_DATA *Udp4Service;
388 EFI_UDP4_PROTOCOL *Udp4Proto;
389 UDP4_INSTANCE_DATA *Instance;
390 EFI_TPL OldTpl;
391
392 if ((This == NULL) || (ChildHandle == NULL)) {
393 return EFI_INVALID_PARAMETER;
394 }
395
396 Udp4Service = UDP4_SERVICE_DATA_FROM_THIS (This);
397
398 //
399 // Try to get the Udp4 protocol from the ChildHandle.
400 //
401 Status = gBS->OpenProtocol (
402 ChildHandle,
403 &gEfiUdp4ProtocolGuid,
404 (VOID **) &Udp4Proto,
405 gUdp4DriverBinding.DriverBindingHandle,
406 ChildHandle,
407 EFI_OPEN_PROTOCOL_GET_PROTOCOL
408 );
409 if (EFI_ERROR (Status)) {
410 return EFI_UNSUPPORTED;
411 }
412
413 Instance = UDP4_INSTANCE_DATA_FROM_THIS (Udp4Proto);
414
415 if (Instance->Destroyed) {
416 return EFI_SUCCESS;
417 }
418
419 //
420 // Use the Destroyed flag to avoid the re-entering of the following code.
421 //
422 Instance->Destroyed = TRUE;
423
424 //
425 // Close the Ip4 protocol.
426 //
427 gBS->CloseProtocol (
428 Udp4Service->IpIo->ChildHandle,
429 &gEfiIp4ProtocolGuid,
430 gUdp4DriverBinding.DriverBindingHandle,
431 Instance->ChildHandle
432 );
433
434 //
435 // Uninstall the Udp4Protocol previously installed on the ChildHandle.
436 //
437 Status = gBS->UninstallMultipleProtocolInterfaces (
438 ChildHandle,
439 &gEfiUdp4ProtocolGuid,
440 (VOID *) &Instance->Udp4Proto,
441 NULL
442 );
443 if (EFI_ERROR (Status)) {
444 Instance->Destroyed = FALSE;
445 return Status;
446 }
447
448 //
449 // Reset the configuration in case the instance's consumer forgets to do this.
450 //
451 Udp4Proto->Configure (Udp4Proto, NULL);
452
453 //
454 // Remove the IpInfo this instance consumes.
455 //
456 IpIoRemoveIp (Udp4Service->IpIo, Instance->IpInfo);
457
458 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
459
460 //
461 // Remove this instance from the service context data's ChildrenList.
462 //
463 RemoveEntryList (&Instance->Link);
464 Udp4Service->ChildrenNumber--;
465
466 //
467 // Clean the instance.
468 //
469 Udp4CleanInstance (Instance);
470
471 gBS->RestoreTPL (OldTpl);
472
473 gBS->FreePool (Instance);
474
475 return EFI_SUCCESS;
476 }
477
478 /**
479 This is the declaration of an EFI image entry point. This entry point is
480 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
481 both device drivers and bus drivers.
482
483 The entry point for Udp4 driver which installs the driver binding
484 and component name protocol on its ImageHandle.
485
486 @param ImageHandle The firmware allocated handle for the UEFI image.
487 @param SystemTable A pointer to the EFI System Table.
488
489 @retval EFI_SUCCESS The operation completed successfully.
490 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
491
492 **/
493 EFI_STATUS
494 EFIAPI
495 Udp4DriverEntryPoint (
496 IN EFI_HANDLE ImageHandle,
497 IN EFI_SYSTEM_TABLE *SystemTable
498 )
499 {
500 EFI_STATUS Status;
501
502 //
503 // Install the Udp4DriverBinding and Udp4ComponentName protocols.
504 //
505 Status = EfiLibInstallDriverBindingComponentName2 (
506 ImageHandle,
507 SystemTable,
508 &gUdp4DriverBinding,
509 ImageHandle,
510 &gUdp4ComponentName,
511 &gUdp4ComponentName2
512 );
513 if (!EFI_ERROR (Status)) {
514 //
515 // Initialize the UDP random port.
516 //
517 mUdp4RandomPort = (UINT16) (((UINT16) NetRandomInitSeed ()) % UDP4_PORT_KNOWN + UDP4_PORT_KNOWN);
518 }
519
520 return Status;
521 }
522