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