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