1 /** @file
2 ARP driver functions.
3
4 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at<BR>
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "ArpDriver.h"
16 #include "ArpImpl.h"
17
18 EFI_DRIVER_BINDING_PROTOCOL gArpDriverBinding = {
19 ArpDriverBindingSupported,
20 ArpDriverBindingStart,
21 ArpDriverBindingStop,
22 0xa,
23 NULL,
24 NULL
25 };
26
27
28 /**
29 Create and initialize the arp service context data.
30
31 @param[in] ImageHandle The image handle representing the loaded driver
32 image.
33 @param[in] ControllerHandle The controller handle the driver binds to.
34 @param[in, out] ArpService Pointer to the buffer containing the arp service
35 context data.
36
37 @retval EFI_SUCCESS The arp service context is initialized.
38
39 @retval EFI_UNSUPPORTED The underlayer Snp mode type is not ethernet.
40 Failed to initialize the service context.
41 @retval other Failed to initialize the arp service context.
42
43 **/
44 EFI_STATUS
ArpCreateService(IN EFI_HANDLE ImageHandle,IN EFI_HANDLE ControllerHandle,IN OUT ARP_SERVICE_DATA * ArpService)45 ArpCreateService (
46 IN EFI_HANDLE ImageHandle,
47 IN EFI_HANDLE ControllerHandle,
48 IN OUT ARP_SERVICE_DATA *ArpService
49 )
50 {
51 EFI_STATUS Status;
52
53 ASSERT (ArpService != NULL);
54
55 ArpService->Signature = ARP_SERVICE_DATA_SIGNATURE;
56
57 //
58 // Init the lists.
59 //
60 InitializeListHead (&ArpService->ChildrenList);
61 InitializeListHead (&ArpService->PendingRequestTable);
62 InitializeListHead (&ArpService->DeniedCacheTable);
63 InitializeListHead (&ArpService->ResolvedCacheTable);
64
65 //
66 // Init the servicebinding protocol members.
67 //
68 ArpService->ServiceBinding.CreateChild = ArpServiceBindingCreateChild;
69 ArpService->ServiceBinding.DestroyChild = ArpServiceBindingDestroyChild;
70
71 //
72 // Save the handles.
73 //
74 ArpService->ImageHandle = ImageHandle;
75 ArpService->ControllerHandle = ControllerHandle;
76
77 //
78 // Create a MNP child instance.
79 //
80 Status = NetLibCreateServiceChild (
81 ControllerHandle,
82 ImageHandle,
83 &gEfiManagedNetworkServiceBindingProtocolGuid,
84 &ArpService->MnpChildHandle
85 );
86 if (EFI_ERROR (Status)) {
87 return Status;
88 }
89
90 //
91 // Open the MNP protocol.
92 //
93 Status = gBS->OpenProtocol (
94 ArpService->MnpChildHandle,
95 &gEfiManagedNetworkProtocolGuid,
96 (VOID **)&ArpService->Mnp,
97 ImageHandle,
98 ControllerHandle,
99 EFI_OPEN_PROTOCOL_BY_DRIVER
100 );
101 if (EFI_ERROR (Status)) {
102 goto ERROR_EXIT;
103 }
104
105 //
106 // Get the underlayer Snp mode data.
107 //
108 Status = ArpService->Mnp->GetModeData (ArpService->Mnp, NULL, &ArpService->SnpMode);
109 if ((Status != EFI_NOT_STARTED) && EFI_ERROR (Status)) {
110 goto ERROR_EXIT;
111 }
112
113 if (ArpService->SnpMode.IfType != NET_IFTYPE_ETHERNET) {
114 //
115 // Only support the ethernet.
116 //
117 Status = EFI_UNSUPPORTED;
118 goto ERROR_EXIT;
119 }
120
121 //
122 // Set the Mnp config parameters.
123 //
124 ArpService->MnpConfigData.ReceivedQueueTimeoutValue = 0;
125 ArpService->MnpConfigData.TransmitQueueTimeoutValue = 0;
126 ArpService->MnpConfigData.ProtocolTypeFilter = ARP_ETHER_PROTO_TYPE;
127 ArpService->MnpConfigData.EnableUnicastReceive = TRUE;
128 ArpService->MnpConfigData.EnableMulticastReceive = FALSE;
129 ArpService->MnpConfigData.EnableBroadcastReceive = TRUE;
130 ArpService->MnpConfigData.EnablePromiscuousReceive = FALSE;
131 ArpService->MnpConfigData.FlushQueuesOnReset = TRUE;
132 ArpService->MnpConfigData.EnableReceiveTimestamps = FALSE;
133 ArpService->MnpConfigData.DisableBackgroundPolling = FALSE;
134
135 //
136 // Configure the Mnp child.
137 //
138 Status = ArpService->Mnp->Configure (ArpService->Mnp, &ArpService->MnpConfigData);
139 if (EFI_ERROR (Status)) {
140 goto ERROR_EXIT;
141 }
142
143 //
144 // Create the event used in the RxToken.
145 //
146 Status = gBS->CreateEvent (
147 EVT_NOTIFY_SIGNAL,
148 TPL_NOTIFY,
149 ArpOnFrameRcvd,
150 ArpService,
151 &ArpService->RxToken.Event
152 );
153 if (EFI_ERROR (Status)) {
154 goto ERROR_EXIT;
155 }
156
157 //
158 // Create the Arp heartbeat timer.
159 //
160 Status = gBS->CreateEvent (
161 EVT_NOTIFY_SIGNAL | EVT_TIMER,
162 TPL_CALLBACK,
163 ArpTimerHandler,
164 ArpService,
165 &ArpService->PeriodicTimer
166 );
167 if (EFI_ERROR (Status)) {
168 goto ERROR_EXIT;
169 }
170
171 //
172 // Start the heartbeat timer.
173 //
174 Status = gBS->SetTimer (
175 ArpService->PeriodicTimer,
176 TimerPeriodic,
177 ARP_PERIODIC_TIMER_INTERVAL
178 );
179
180 ERROR_EXIT:
181
182 return Status;
183 }
184
185
186 /**
187 Clean the arp service context data.
188
189 @param[in, out] ArpService Pointer to the buffer containing the arp service
190 context data.
191
192 @return None.
193
194 **/
195 VOID
ArpCleanService(IN OUT ARP_SERVICE_DATA * ArpService)196 ArpCleanService (
197 IN OUT ARP_SERVICE_DATA *ArpService
198 )
199 {
200 NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
201
202 if (ArpService->PeriodicTimer != NULL) {
203 //
204 // Cancle and close the PeriodicTimer.
205 //
206 gBS->SetTimer (ArpService->PeriodicTimer, TimerCancel, 0);
207 gBS->CloseEvent (ArpService->PeriodicTimer);
208 }
209
210 if (ArpService->RxToken.Event != NULL) {
211 //
212 // Cancle the RxToken and close the event in the RxToken.
213 //
214 ArpService->Mnp->Cancel (ArpService->Mnp, NULL);
215 gBS->CloseEvent (ArpService->RxToken.Event);
216 }
217
218 if (ArpService->Mnp != NULL) {
219 //
220 // Reset the Mnp child and close the Mnp protocol.
221 //
222 ArpService->Mnp->Configure (ArpService->Mnp, NULL);
223 gBS->CloseProtocol (
224 ArpService->MnpChildHandle,
225 &gEfiManagedNetworkProtocolGuid,
226 ArpService->ImageHandle,
227 ArpService->ControllerHandle
228 );
229 }
230
231 if (ArpService->MnpChildHandle != NULL) {
232 //
233 // Destroy the mnp child.
234 //
235 NetLibDestroyServiceChild(
236 ArpService->ControllerHandle,
237 ArpService->ImageHandle,
238 &gEfiManagedNetworkServiceBindingProtocolGuid,
239 ArpService->MnpChildHandle
240 );
241 }
242 }
243
244 /**
245 Callback function which provided by user to remove one node in NetDestroyLinkList process.
246
247 @param[in] Entry The entry to be removed.
248 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
249
250 @retval EFI_SUCCESS The entry has been removed successfully.
251 @retval Others Fail to remove the entry.
252
253 **/
254 EFI_STATUS
255 EFIAPI
ArpDestroyChildEntryInHandleBuffer(IN LIST_ENTRY * Entry,IN VOID * Context)256 ArpDestroyChildEntryInHandleBuffer (
257 IN LIST_ENTRY *Entry,
258 IN VOID *Context
259 )
260 {
261 ARP_INSTANCE_DATA *Instance;
262 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
263
264 if (Entry == NULL || Context == NULL) {
265 return EFI_INVALID_PARAMETER;
266 }
267
268 Instance = NET_LIST_USER_STRUCT_S (Entry, ARP_INSTANCE_DATA, List, ARP_INSTANCE_DATA_SIGNATURE);
269 ServiceBinding = (EFI_SERVICE_BINDING_PROTOCOL *) Context;
270
271 return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
272 }
273
274 /**
275 Tests to see if this driver supports a given controller.
276
277 If a child device is provided, it further tests to see if this driver supports
278 creating a handle for the specified child device.
279
280 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
281 @param[in] ControllerHandle The handle of the controller to test. This handle
282 must support a protocol interface that supplies
283 an I/O abstraction to the driver.
284 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
285 This parameter is ignored by device drivers,
286 and is optional for bus drivers.
287
288 @retval EFI_SUCCESS The device specified by ControllerHandle and
289 RemainingDevicePath is supported by the driver
290 specified by This.
291 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
292 RemainingDevicePath is already being managed
293 by the driver specified by This.
294 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
295 RemainingDevicePath is already being managed by
296 a different driver or an application that
297 requires exclusive acces. Currently not implemented.
298 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
299 RemainingDevicePath is not supported by the
300 driver specified by This.
301
302 **/
303 EFI_STATUS
304 EFIAPI
ArpDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)305 ArpDriverBindingSupported (
306 IN EFI_DRIVER_BINDING_PROTOCOL *This,
307 IN EFI_HANDLE ControllerHandle,
308 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
309 )
310 {
311 EFI_STATUS Status;
312
313 //
314 // Test to see if Arp SB is already installed.
315 //
316 Status = gBS->OpenProtocol (
317 ControllerHandle,
318 &gEfiArpServiceBindingProtocolGuid,
319 NULL,
320 This->DriverBindingHandle,
321 ControllerHandle,
322 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
323 );
324 if (Status == EFI_SUCCESS) {
325 return EFI_ALREADY_STARTED;
326 }
327
328 //
329 // Test to see if MNP SB is installed.
330 //
331 Status = gBS->OpenProtocol (
332 ControllerHandle,
333 &gEfiManagedNetworkServiceBindingProtocolGuid,
334 NULL,
335 This->DriverBindingHandle,
336 ControllerHandle,
337 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
338 );
339
340 return Status;
341 }
342
343
344 /**
345 Start this driver on ControllerHandle.
346
347 The Start() function is designed to be invoked from the EFI boot service ConnectController().
348 As a result, much of the error checking on the parameters to Start() has been
349 moved into this common boot service. It is legal to call Start() from other locations,
350 but the following calling restrictions must be followed or the system behavior
351 will not be deterministic.
352 1. ControllerHandle must be a valid EFI_HANDLE.
353 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally
354 aligned EFI_DEVICE_PATH_PROTOCOL.
355 3. Prior to calling Start(), the Supported() function for the driver specified
356 by This must have been called with the same calling parameters, and Supported()
357 must have returned EFI_SUCCESS.
358
359 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
360 @param[in] ControllerHandle The handle of the controller to start. This handle
361 must support a protocol interface that supplies
362 an I/O abstraction to the driver.
363 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
364 This parameter is ignored by device drivers,
365 and is optional for bus drivers.
366
367 @retval EFI_SUCCESS The device was started.
368 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.
369 Currently not implemented.
370 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of
371 resources.
372 @retval Others The driver failded to start the device.
373
374 **/
375 EFI_STATUS
376 EFIAPI
ArpDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)377 ArpDriverBindingStart (
378 IN EFI_DRIVER_BINDING_PROTOCOL *This,
379 IN EFI_HANDLE ControllerHandle,
380 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
381 )
382 {
383 EFI_STATUS Status;
384 ARP_SERVICE_DATA *ArpService;
385
386 //
387 // Allocate a zero pool for ArpService.
388 //
389 ArpService = AllocateZeroPool (sizeof(ARP_SERVICE_DATA));
390 if (ArpService == NULL) {
391 return EFI_OUT_OF_RESOURCES;
392 }
393
394 //
395 // Initialize the arp service context data.
396 //
397 Status = ArpCreateService (This->DriverBindingHandle, ControllerHandle, ArpService);
398 if (EFI_ERROR (Status)) {
399 goto ERROR;
400 }
401
402 //
403 // Install the ARP service binding protocol.
404 //
405 Status = gBS->InstallMultipleProtocolInterfaces (
406 &ControllerHandle,
407 &gEfiArpServiceBindingProtocolGuid,
408 &ArpService->ServiceBinding,
409 NULL
410 );
411 if (EFI_ERROR (Status)) {
412 goto ERROR;
413 }
414
415 //
416 // OK, start to receive arp packets from Mnp.
417 //
418 Status = ArpService->Mnp->Receive (ArpService->Mnp, &ArpService->RxToken);
419 if (EFI_ERROR (Status)) {
420 goto ERROR;
421 }
422
423 return Status;
424
425 ERROR:
426
427 //
428 // On error, clean the arp service context data, and free the memory allocated.
429 //
430 ArpCleanService (ArpService);
431 FreePool (ArpService);
432
433 return Status;
434 }
435
436
437 /**
438 Stop this driver on ControllerHandle.
439
440 Release the control of this controller and remove the IScsi functions. The Stop()
441 function is designed to be invoked from the EFI boot service DisconnectController().
442 As a result, much of the error checking on the parameters to Stop() has been moved
443 into this common boot service. It is legal to call Stop() from other locations,
444 but the following calling restrictions must be followed or the system behavior
445 will not be deterministic.
446 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
447 same driver's Start() function.
448 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
449 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
450 Start() function, and the Start() function must have called OpenProtocol() on
451 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
452
453 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
454 @param[in] ControllerHandle A handle to the device being stopped. The handle must
455 support a bus specific I/O protocol for the driver
456 to use to stop the device.
457 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
458 Not used.
459 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
460 if NumberOfChildren is 0.Not used.
461
462 @retval EFI_SUCCESS The device was stopped.
463 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
464
465 **/
466 EFI_STATUS
467 EFIAPI
ArpDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)468 ArpDriverBindingStop (
469 IN EFI_DRIVER_BINDING_PROTOCOL *This,
470 IN EFI_HANDLE ControllerHandle,
471 IN UINTN NumberOfChildren,
472 IN EFI_HANDLE *ChildHandleBuffer
473 )
474 {
475 EFI_STATUS Status;
476 EFI_HANDLE NicHandle;
477 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
478 ARP_SERVICE_DATA *ArpService;
479 LIST_ENTRY *List;
480
481 //
482 // Get the NicHandle which the arp servicebinding is installed on.
483 //
484 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
485 if (NicHandle == NULL) {
486 return EFI_SUCCESS;
487 }
488
489 //
490 // Try to get the arp servicebinding protocol on the NicHandle.
491 //
492 Status = gBS->OpenProtocol (
493 NicHandle,
494 &gEfiArpServiceBindingProtocolGuid,
495 (VOID **)&ServiceBinding,
496 This->DriverBindingHandle,
497 ControllerHandle,
498 EFI_OPEN_PROTOCOL_GET_PROTOCOL
499 );
500 if (EFI_ERROR (Status)) {
501 DEBUG ((EFI_D_ERROR, "ArpDriverBindingStop: Open ArpSb failed, %r.\n", Status));
502 return EFI_DEVICE_ERROR;
503 }
504
505 ArpService = ARP_SERVICE_DATA_FROM_THIS (ServiceBinding);
506
507 if (NumberOfChildren != 0) {
508 //
509 // NumberOfChildren is not zero, destroy all the ARP children instances.
510 //
511 List = &ArpService->ChildrenList;
512 Status = NetDestroyLinkList (
513 List,
514 ArpDestroyChildEntryInHandleBuffer,
515 ServiceBinding,
516 NULL
517 );
518 ASSERT (IsListEmpty (&ArpService->PendingRequestTable));
519 ASSERT (IsListEmpty (&ArpService->DeniedCacheTable));
520 ASSERT (IsListEmpty (&ArpService->ResolvedCacheTable));
521 } else if (IsListEmpty (&ArpService->ChildrenList)) {
522 //
523 // Uninstall the ARP ServiceBinding protocol.
524 //
525 gBS->UninstallMultipleProtocolInterfaces (
526 NicHandle,
527 &gEfiArpServiceBindingProtocolGuid,
528 &ArpService->ServiceBinding,
529 NULL
530 );
531
532 //
533 // Clean the arp servicebinding context data and free the memory allocated.
534 //
535 ArpCleanService (ArpService);
536
537 FreePool (ArpService);
538 }
539
540 return EFI_SUCCESS;
541 }
542
543 /**
544 Creates a child handle and installs a protocol.
545
546 The CreateChild() function installs a protocol on ChildHandle.
547 If ChildHandle is a pointer to NULL, then a new handle is created and returned
548 in ChildHandle. If ChildHandle is not a pointer to NULL, then the protocol
549 installs on the existing ChildHandle.
550
551 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
552 @param ChildHandle Pointer to the handle of the child to create. If it is NULL,
553 then a new handle is created. If it is a pointer to an existing
554 UEFI handle, then the protocol is added to the existing UEFI handle.
555
556 @retval EFI_SUCCES The protocol was added to ChildHandle.
557 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
558 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
559 the child
560 @retval other The child handle was not created
561
562 **/
563 EFI_STATUS
564 EFIAPI
ArpServiceBindingCreateChild(IN EFI_SERVICE_BINDING_PROTOCOL * This,IN EFI_HANDLE * ChildHandle)565 ArpServiceBindingCreateChild (
566 IN EFI_SERVICE_BINDING_PROTOCOL *This,
567 IN EFI_HANDLE *ChildHandle
568 )
569 {
570 EFI_STATUS Status;
571 ARP_SERVICE_DATA *ArpService;
572 ARP_INSTANCE_DATA *Instance;
573 VOID *Mnp;
574 EFI_TPL OldTpl;
575
576 if ((This == NULL) || (ChildHandle == NULL)) {
577 return EFI_INVALID_PARAMETER;
578 }
579
580 ArpService = ARP_SERVICE_DATA_FROM_THIS (This);
581
582 //
583 // Allocate memory for the instance context data.
584 //
585 Instance = AllocateZeroPool (sizeof(ARP_INSTANCE_DATA));
586 if (Instance == NULL) {
587 DEBUG ((EFI_D_ERROR, "ArpSBCreateChild: Failed to allocate memory for Instance.\n"));
588
589 return EFI_OUT_OF_RESOURCES;
590 }
591
592 //
593 // Init the instance context data.
594 //
595 ArpInitInstance (ArpService, Instance);
596
597 //
598 // Install the ARP protocol onto the ChildHandle.
599 //
600 Status = gBS->InstallMultipleProtocolInterfaces (
601 ChildHandle,
602 &gEfiArpProtocolGuid,
603 (VOID *)&Instance->ArpProto,
604 NULL
605 );
606 if (EFI_ERROR (Status)) {
607 DEBUG ((EFI_D_ERROR, "ArpSBCreateChild: faild to install ARP protocol, %r.\n", Status));
608
609 FreePool (Instance);
610 return Status;
611 }
612
613 //
614 // Save the ChildHandle.
615 //
616 Instance->Handle = *ChildHandle;
617
618 //
619 // Open the Managed Network protocol BY_CHILD.
620 //
621 Status = gBS->OpenProtocol (
622 ArpService->MnpChildHandle,
623 &gEfiManagedNetworkProtocolGuid,
624 (VOID **) &Mnp,
625 gArpDriverBinding.DriverBindingHandle,
626 Instance->Handle,
627 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
628 );
629 if (EFI_ERROR (Status)) {
630 goto ERROR;
631 }
632
633 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
634
635 //
636 // Insert the instance into children list managed by the arp service context data.
637 //
638 InsertTailList (&ArpService->ChildrenList, &Instance->List);
639 ArpService->ChildrenNumber++;
640
641 gBS->RestoreTPL (OldTpl);
642
643 ERROR:
644
645 if (EFI_ERROR (Status)) {
646
647 gBS->CloseProtocol (
648 ArpService->MnpChildHandle,
649 &gEfiManagedNetworkProtocolGuid,
650 gArpDriverBinding.DriverBindingHandle,
651 Instance->Handle
652 );
653
654 gBS->UninstallMultipleProtocolInterfaces (
655 Instance->Handle,
656 &gEfiArpProtocolGuid,
657 &Instance->ArpProto,
658 NULL
659 );
660
661 //
662 // Free the allocated memory.
663 //
664 FreePool (Instance);
665 }
666
667 return Status;
668 }
669
670
671 /**
672 Destroys a child handle with a protocol installed on it.
673
674 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
675 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
676 last protocol on ChildHandle, then ChildHandle is destroyed.
677
678 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
679 @param ChildHandle Handle of the child to destroy
680
681 @retval EFI_SUCCES The protocol was removed from ChildHandle.
682 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is
683 being removed.
684 @retval EFI_INVALID_PARAMETER Child handle is NULL.
685 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
686 because its services are being used.
687 @retval other The child handle was not destroyed
688
689 **/
690 EFI_STATUS
691 EFIAPI
ArpServiceBindingDestroyChild(IN EFI_SERVICE_BINDING_PROTOCOL * This,IN EFI_HANDLE ChildHandle)692 ArpServiceBindingDestroyChild (
693 IN EFI_SERVICE_BINDING_PROTOCOL *This,
694 IN EFI_HANDLE ChildHandle
695 )
696 {
697 EFI_STATUS Status;
698 ARP_SERVICE_DATA *ArpService;
699 ARP_INSTANCE_DATA *Instance;
700 EFI_ARP_PROTOCOL *Arp;
701 EFI_TPL OldTpl;
702
703 if ((This == NULL) || (ChildHandle == NULL)) {
704 return EFI_INVALID_PARAMETER;
705 }
706
707 ArpService = ARP_SERVICE_DATA_FROM_THIS (This);
708
709 //
710 // Get the arp protocol.
711 //
712 Status = gBS->OpenProtocol (
713 ChildHandle,
714 &gEfiArpProtocolGuid,
715 (VOID **)&Arp,
716 ArpService->ImageHandle,
717 ChildHandle,
718 EFI_OPEN_PROTOCOL_GET_PROTOCOL
719 );
720 if (EFI_ERROR (Status)) {
721 return EFI_UNSUPPORTED;
722 }
723
724 Instance = ARP_INSTANCE_DATA_FROM_THIS (Arp);
725
726 if (Instance->InDestroy) {
727 return EFI_SUCCESS;
728 }
729
730 //
731 // Use the InDestroy as a flag to avoid re-entrance.
732 //
733 Instance->InDestroy = TRUE;
734
735 //
736 // Close the Managed Network protocol.
737 //
738 gBS->CloseProtocol (
739 ArpService->MnpChildHandle,
740 &gEfiManagedNetworkProtocolGuid,
741 gArpDriverBinding.DriverBindingHandle,
742 ChildHandle
743 );
744
745 //
746 // Uninstall the ARP protocol.
747 //
748 Status = gBS->UninstallMultipleProtocolInterfaces (
749 ChildHandle,
750 &gEfiArpProtocolGuid,
751 &Instance->ArpProto,
752 NULL
753 );
754 if (EFI_ERROR (Status)) {
755 DEBUG ((EFI_D_ERROR, "ArpSBDestroyChild: Failed to uninstall the arp protocol, %r.\n",
756 Status));
757
758 Instance->InDestroy = FALSE;
759 return Status;
760 }
761
762 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
763
764 if (Instance->Configured) {
765 //
766 // Delete the related cache entry.
767 //
768 ArpDeleteCacheEntry (Instance, FALSE, NULL, TRUE);
769
770 //
771 // Reset the instance configuration.
772 //
773 ArpConfigureInstance (Instance, NULL);
774 }
775
776 //
777 // Remove this instance from the ChildrenList.
778 //
779 RemoveEntryList (&Instance->List);
780 ArpService->ChildrenNumber--;
781
782 gBS->RestoreTPL (OldTpl);
783
784 FreePool (Instance);
785
786 return Status;
787 }
788
789 /**
790 The entry point for Arp driver which installs the driver binding and component name
791 protocol on its ImageHandle.
792
793 @param[in] ImageHandle The image handle of the driver.
794 @param[in] SystemTable The system table.
795
796 @retval EFI_SUCCESS if the driver binding and component name protocols
797 are successfully
798 @retval Others Failed to install the protocols.
799
800 **/
801 EFI_STATUS
802 EFIAPI
ArpDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)803 ArpDriverEntryPoint (
804 IN EFI_HANDLE ImageHandle,
805 IN EFI_SYSTEM_TABLE *SystemTable
806 )
807 {
808 return EfiLibInstallDriverBindingComponentName2 (
809 ImageHandle,
810 SystemTable,
811 &gArpDriverBinding,
812 ImageHandle,
813 &gArpComponentName,
814 &gArpComponentName2
815 );
816 }
817
818