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