VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c@ 105670

Last change on this file since 105670 was 105670, checked in by vboxsync, 4 months ago

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

  • Property svn:eol-style set to native
File size: 21.7 KB
Line 
1/** @file
2 Driver Binding functions and Service Binding functions
3 implementation for Dhcp6 Driver.
4
5 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
6 Copyright (c) Microsoft Corporation
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9**/
10
11#include "Dhcp6Impl.h"
12
13EFI_DRIVER_BINDING_PROTOCOL gDhcp6DriverBinding = {
14 Dhcp6DriverBindingSupported,
15 Dhcp6DriverBindingStart,
16 Dhcp6DriverBindingStop,
17 0xa,
18 NULL,
19 NULL
20};
21
22EFI_SERVICE_BINDING_PROTOCOL gDhcp6ServiceBindingTemplate = {
23 Dhcp6ServiceBindingCreateChild,
24 Dhcp6ServiceBindingDestroyChild
25};
26
27/**
28 Configure the default Udp6Io to receive all the DHCP6 traffic
29 on this network interface.
30
31 @param[in] UdpIo The pointer to Udp6Io to be configured.
32 @param[in] Context The pointer to the context.
33
34 @retval EFI_SUCCESS The Udp6Io is successfully configured.
35 @retval Others Failed to configure the Udp6Io.
36
37**/
38EFI_STATUS
39EFIAPI
40Dhcp6ConfigureUdpIo (
41 IN UDP_IO *UdpIo,
42 IN VOID *Context
43 )
44{
45 EFI_UDP6_PROTOCOL *Udp6;
46 EFI_UDP6_CONFIG_DATA *Config;
47
48 Udp6 = UdpIo->Protocol.Udp6;
49 Config = &(UdpIo->Config.Udp6);
50
51 ZeroMem (Config, sizeof (EFI_UDP6_CONFIG_DATA));
52
53 //
54 // Set Udp6 configure data for the Dhcp6 instance.
55 //
56 Config->AcceptPromiscuous = FALSE;
57 Config->AcceptAnyPort = FALSE;
58 Config->AllowDuplicatePort = FALSE;
59 Config->TrafficClass = 0;
60 Config->HopLimit = 128;
61 Config->ReceiveTimeout = 0;
62 Config->TransmitTimeout = 0;
63
64 //
65 // Configure an endpoint of client(0, 546), server(0, 0), the addresses
66 // will be overridden later. Note that we MUST not limit RemotePort.
67 // More details, refer to RFC 3315 section 5.2.
68 //
69 Config->StationPort = DHCP6_PORT_CLIENT;
70 Config->RemotePort = 0;
71
72 return Udp6->Configure (Udp6, Config);
73}
74
75/**
76 Destroy the Dhcp6 service. The Dhcp6 service may be partly initialized,
77 or partly destroyed. If a resource is destroyed, it is marked as such in
78 case the destroy failed and being called again later.
79
80 @param[in, out] Service The pointer to Dhcp6 service to be destroyed.
81
82**/
83VOID
84Dhcp6DestroyService (
85 IN OUT DHCP6_SERVICE *Service
86 )
87{
88 //
89 // All children instances should have been already destroyed here.
90 //
91 ASSERT (Service->NumOfChild == 0);
92
93 if (Service->ClientId != NULL) {
94 FreePool (Service->ClientId);
95 }
96
97 if (Service->UdpIo != NULL) {
98 UdpIoFreeIo (Service->UdpIo);
99 }
100
101 FreePool (Service);
102}
103
104/**
105 Create a new Dhcp6 service for the Nic controller.
106
107 @param[in] Controller The controller to be installed DHCP6 service
108 binding protocol.
109 @param[in] ImageHandle The image handle of the Dhcp6 driver.
110 @param[out] Service The return pointer of the new Dhcp6 service.
111
112 @retval EFI_SUCCESS The Dhcp6 service is created successfully.
113 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
114 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
115
116**/
117EFI_STATUS
118Dhcp6CreateService (
119 IN EFI_HANDLE Controller,
120 IN EFI_HANDLE ImageHandle,
121 OUT DHCP6_SERVICE **Service
122 )
123{
124 DHCP6_SERVICE *Dhcp6Srv;
125 EFI_STATUS Status;
126 UINT32 Random;
127
128 Status = PseudoRandomU32 (&Random);
129 if (EFI_ERROR (Status)) {
130 DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
131 return Status;
132 }
133
134 *Service = NULL;
135 Dhcp6Srv = AllocateZeroPool (sizeof (DHCP6_SERVICE));
136
137 if (Dhcp6Srv == NULL) {
138 return EFI_OUT_OF_RESOURCES;
139 }
140
141 //
142 // Open the SNP protocol to get mode data later.
143 //
144 Dhcp6Srv->Snp = NULL;
145 NetLibGetSnpHandle (Controller, &Dhcp6Srv->Snp);
146 if (Dhcp6Srv->Snp == NULL) {
147 FreePool (Dhcp6Srv);
148 return EFI_DEVICE_ERROR;
149 }
150
151 //
152 // Initialize the fields of the new Dhcp6 service.
153 //
154 Dhcp6Srv->Signature = DHCP6_SERVICE_SIGNATURE;
155 Dhcp6Srv->Controller = Controller;
156 Dhcp6Srv->Image = ImageHandle;
157 Dhcp6Srv->Xid = (0xffffff & Random);
158
159 CopyMem (
160 &Dhcp6Srv->ServiceBinding,
161 &gDhcp6ServiceBindingTemplate,
162 sizeof (EFI_SERVICE_BINDING_PROTOCOL)
163 );
164
165 //
166 // Locate Ip6->Ip6Config and store it for get IP6 Duplicate Address Detection transmits.
167 //
168 Status = gBS->HandleProtocol (
169 Controller,
170 &gEfiIp6ConfigProtocolGuid,
171 (VOID **)&Dhcp6Srv->Ip6Cfg
172 );
173 if (EFI_ERROR (Status)) {
174 FreePool (Dhcp6Srv);
175 return Status;
176 }
177
178 //
179 // Generate client Duid: If SMBIOS system UUID is located, generate DUID in DUID-UUID format.
180 // Otherwise, in DUID-LLT format.
181 //
182 Dhcp6Srv->ClientId = Dhcp6GenerateClientId (Dhcp6Srv->Snp->Mode);
183
184 if (Dhcp6Srv->ClientId == NULL) {
185 FreePool (Dhcp6Srv);
186 return EFI_DEVICE_ERROR;
187 }
188
189 //
190 // Create an Udp6Io for stateful transmit/receive of each Dhcp6 instance.
191 //
192 Dhcp6Srv->UdpIo = UdpIoCreateIo (
193 Controller,
194 ImageHandle,
195 Dhcp6ConfigureUdpIo,
196 UDP_IO_UDP6_VERSION,
197 NULL
198 );
199
200 if (Dhcp6Srv->UdpIo == NULL) {
201 FreePool (Dhcp6Srv->ClientId);
202 FreePool (Dhcp6Srv);
203 return EFI_DEVICE_ERROR;
204 }
205
206 InitializeListHead (&Dhcp6Srv->Child);
207
208 *Service = Dhcp6Srv;
209
210 return EFI_SUCCESS;
211}
212
213/**
214 Destroy the Dhcp6 instance and recycle the resources.
215
216 @param[in, out] Instance The pointer to the Dhcp6 instance.
217
218**/
219VOID
220Dhcp6DestroyInstance (
221 IN OUT DHCP6_INSTANCE *Instance
222 )
223{
224 //
225 // Clean up the retry list first.
226 //
227 Dhcp6CleanupRetry (Instance, DHCP6_PACKET_ALL);
228 gBS->CloseEvent (Instance->Timer);
229
230 //
231 // Clean up the current configure data.
232 //
233 if (Instance->Config != NULL) {
234 Dhcp6CleanupConfigData (Instance->Config);
235 FreePool (Instance->Config);
236 }
237
238 //
239 // Clean up the current Ia.
240 //
241 if (Instance->IaCb.Ia != NULL) {
242 if (Instance->IaCb.Ia->ReplyPacket != NULL) {
243 FreePool (Instance->IaCb.Ia->ReplyPacket);
244 }
245
246 FreePool (Instance->IaCb.Ia);
247 }
248
249 if (Instance->Unicast != NULL) {
250 FreePool (Instance->Unicast);
251 }
252
253 if (Instance->AdSelect != NULL) {
254 FreePool (Instance->AdSelect);
255 }
256
257 FreePool (Instance);
258}
259
260/**
261 Create the Dhcp6 instance and initialize it.
262
263 @param[in] Service The pointer to the Dhcp6 service.
264 @param[out] Instance The pointer to the Dhcp6 instance.
265
266 @retval EFI_SUCCESS The Dhcp6 instance is created.
267 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
268
269**/
270EFI_STATUS
271Dhcp6CreateInstance (
272 IN DHCP6_SERVICE *Service,
273 OUT DHCP6_INSTANCE **Instance
274 )
275{
276 EFI_STATUS Status;
277 DHCP6_INSTANCE *Dhcp6Ins;
278
279 *Instance = NULL;
280 Dhcp6Ins = AllocateZeroPool (sizeof (DHCP6_INSTANCE));
281
282 if (Dhcp6Ins == NULL) {
283 return EFI_OUT_OF_RESOURCES;
284 }
285
286 //
287 // Initialize the fields of the new Dhcp6 instance.
288 //
289 Dhcp6Ins->Signature = DHCP6_INSTANCE_SIGNATURE;
290 Dhcp6Ins->UdpSts = EFI_ALREADY_STARTED;
291 Dhcp6Ins->Service = Service;
292 Dhcp6Ins->InDestroy = FALSE;
293 Dhcp6Ins->MediaPresent = TRUE;
294
295 CopyMem (
296 &Dhcp6Ins->Dhcp6,
297 &gDhcp6ProtocolTemplate,
298 sizeof (EFI_DHCP6_PROTOCOL)
299 );
300
301 InitializeListHead (&Dhcp6Ins->TxList);
302 InitializeListHead (&Dhcp6Ins->InfList);
303
304 //
305 // There is a timer for each Dhcp6 instance, which is used to track the
306 // lease time of Ia and the retransmission time of all sent packets.
307 //
308 Status = gBS->CreateEvent (
309 EVT_NOTIFY_SIGNAL | EVT_TIMER,
310 TPL_CALLBACK,
311 Dhcp6OnTimerTick,
312 Dhcp6Ins,
313 &Dhcp6Ins->Timer
314 );
315
316 if (EFI_ERROR (Status)) {
317 FreePool (Dhcp6Ins);
318 return Status;
319 }
320
321 *Instance = Dhcp6Ins;
322
323 return EFI_SUCCESS;
324}
325
326/**
327 Callback function which provided by user to remove one node in NetDestroyLinkList process.
328
329 @param[in] Entry The entry to be removed.
330 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
331
332 @retval EFI_SUCCESS The entry has been removed successfully.
333 @retval Others Fail to remove the entry.
334
335**/
336EFI_STATUS
337EFIAPI
338Dhcp6DestroyChildEntry (
339 IN LIST_ENTRY *Entry,
340 IN VOID *Context
341 )
342{
343 DHCP6_INSTANCE *Instance;
344 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
345
346 if ((Entry == NULL) || (Context == NULL)) {
347 return EFI_INVALID_PARAMETER;
348 }
349
350 Instance = NET_LIST_USER_STRUCT_S (Entry, DHCP6_INSTANCE, Link, DHCP6_INSTANCE_SIGNATURE);
351 ServiceBinding = (EFI_SERVICE_BINDING_PROTOCOL *)Context;
352
353 return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
354}
355
356/**
357 Entry point of the DHCP6 driver to install various protocols.
358
359 @param[in] ImageHandle The handle of the UEFI image file.
360 @param[in] SystemTable The pointer to the EFI System Table.
361
362 @retval EFI_SUCCESS The operation completed successfully.
363 @retval Others Unexpected error occurs.
364
365**/
366EFI_STATUS
367EFIAPI
368Dhcp6DriverEntryPoint (
369 IN EFI_HANDLE ImageHandle,
370 IN EFI_SYSTEM_TABLE *SystemTable
371 )
372{
373 return EfiLibInstallDriverBindingComponentName2 (
374 ImageHandle,
375 SystemTable,
376 &gDhcp6DriverBinding,
377 ImageHandle,
378 &gDhcp6ComponentName,
379 &gDhcp6ComponentName2
380 );
381}
382
383/**
384 Test to see if this driver supports ControllerHandle. This service
385 is called by the EFI boot service ConnectController(). In
386 order to make drivers as small as possible, there are a few calling
387 restrictions for this service. ConnectController() must
388 follow these calling restrictions. If any other agent wishes to call
389 Supported() it must also follow these calling restrictions.
390
391 @param[in] This The pointer to the driver binding protocol.
392 @param[in] ControllerHandle The handle of device to be tested.
393 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
394 device to be started.
395
396 @retval EFI_SUCCESS This driver supports this device.
397 @retval Others This driver does not support this device.
398
399**/
400EFI_STATUS
401EFIAPI
402Dhcp6DriverBindingSupported (
403 IN EFI_DRIVER_BINDING_PROTOCOL *This,
404 IN EFI_HANDLE ControllerHandle,
405 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
406 )
407{
408 return gBS->OpenProtocol (
409 ControllerHandle,
410 &gEfiUdp6ServiceBindingProtocolGuid,
411 NULL,
412 This->DriverBindingHandle,
413 ControllerHandle,
414 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
415 );
416}
417
418/**
419 Start this driver on ControllerHandle. This service is called by the
420 EFI boot service ConnectController(). In order to make
421 drivers as small as possible, there are a few calling restrictions for
422 this service. ConnectController() must follow these
423 calling restrictions. If any other agent wishes to call Start() it
424 must also follow these calling restrictions.
425
426 @param[in] This The pointer to the driver binding protocol.
427 @param[in] ControllerHandle The handle of device to be started.
428 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
429 device to be started.
430
431 @retval EFI_SUCCESS This driver is installed to ControllerHandle.
432 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
433 @retval other This driver does not support this device.
434
435**/
436EFI_STATUS
437EFIAPI
438Dhcp6DriverBindingStart (
439 IN EFI_DRIVER_BINDING_PROTOCOL *This,
440 IN EFI_HANDLE ControllerHandle,
441 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
442 )
443{
444 EFI_STATUS Status;
445 DHCP6_SERVICE *Service;
446
447 //
448 // Check the Dhcp6 service whether already started.
449 //
450 Status = gBS->OpenProtocol (
451 ControllerHandle,
452 &gEfiDhcp6ServiceBindingProtocolGuid,
453 NULL,
454 This->DriverBindingHandle,
455 ControllerHandle,
456 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
457 );
458
459 if (!EFI_ERROR (Status)) {
460 return EFI_ALREADY_STARTED;
461 }
462
463 //
464 // Create and initialize the Dhcp6 service.
465 //
466 Status = Dhcp6CreateService (
467 ControllerHandle,
468 This->DriverBindingHandle,
469 &Service
470 );
471
472 if (EFI_ERROR (Status)) {
473 return Status;
474 }
475
476 ASSERT (Service != NULL);
477
478 Status = gBS->InstallMultipleProtocolInterfaces (
479 &ControllerHandle,
480 &gEfiDhcp6ServiceBindingProtocolGuid,
481 &Service->ServiceBinding,
482 NULL
483 );
484
485 if (EFI_ERROR (Status)) {
486 Dhcp6DestroyService (Service);
487 return Status;
488 }
489
490 return EFI_SUCCESS;
491}
492
493/**
494 Stop this driver on ControllerHandle. This service is called by the
495 EFI boot service DisconnectController(). In order to
496 make drivers as small as possible, there are a few calling
497 restrictions for this service. DisconnectController()
498 must follow these calling restrictions. If any other agent wishes
499 to call Stop() it must also follow these calling restrictions.
500
501 @param[in] This Protocol instance pointer.
502 @param[in] ControllerHandle Handle of device to stop driver on
503 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
504 children is zero stop the entire bus driver.
505 @param[in] ChildHandleBuffer List of Child Handles to Stop.
506
507 @retval EFI_SUCCESS This driver is removed ControllerHandle
508 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
509 @retval other This driver was not removed from this device
510
511**/
512EFI_STATUS
513EFIAPI
514Dhcp6DriverBindingStop (
515 IN EFI_DRIVER_BINDING_PROTOCOL *This,
516 IN EFI_HANDLE ControllerHandle,
517 IN UINTN NumberOfChildren,
518 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
519 )
520{
521 EFI_STATUS Status;
522 EFI_HANDLE NicHandle;
523 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
524 DHCP6_SERVICE *Service;
525 LIST_ENTRY *List;
526 UINTN ListLength;
527
528 //
529 // Find and check the Nic handle by the controller handle.
530 //
531 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp6ProtocolGuid);
532
533 if (NicHandle == NULL) {
534 return EFI_SUCCESS;
535 }
536
537 Status = gBS->OpenProtocol (
538 NicHandle,
539 &gEfiDhcp6ServiceBindingProtocolGuid,
540 (VOID **)&ServiceBinding,
541 This->DriverBindingHandle,
542 NicHandle,
543 EFI_OPEN_PROTOCOL_GET_PROTOCOL
544 );
545
546 if (EFI_ERROR (Status)) {
547 return Status;
548 }
549
550 Service = DHCP6_SERVICE_FROM_THIS (ServiceBinding);
551 if (!IsListEmpty (&Service->Child)) {
552 //
553 // Destroy all the children instances before destroy the service.
554 //
555 List = &Service->Child;
556 Status = NetDestroyLinkList (
557 List,
558 Dhcp6DestroyChildEntry,
559 ServiceBinding,
560 &ListLength
561 );
562 if (EFI_ERROR (Status) || (ListLength != 0)) {
563 Status = EFI_DEVICE_ERROR;
564 }
565 }
566
567 if ((NumberOfChildren == 0) && !IsListEmpty (&Service->Child)) {
568 Status = EFI_DEVICE_ERROR;
569 }
570
571 if ((NumberOfChildren == 0) && IsListEmpty (&Service->Child)) {
572 //
573 // Destroy the service itself if no child instance left.
574 //
575 Status = gBS->UninstallProtocolInterface (
576 NicHandle,
577 &gEfiDhcp6ServiceBindingProtocolGuid,
578 ServiceBinding
579 );
580 if (EFI_ERROR (Status)) {
581 goto ON_EXIT;
582 }
583
584 Dhcp6DestroyService (Service);
585 Status = EFI_SUCCESS;
586 }
587
588ON_EXIT:
589 return Status;
590}
591
592/**
593 Creates a child handle and installs a protocol.
594
595 The CreateChild() function installs a protocol on ChildHandle.
596 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
597 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
598
599 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
600 @param[in, out] ChildHandle Pointer to the handle of the child to create. If it is NULL,
601 then a new handle is created. If it is a pointer to an existing
602 UEFI handle, then the protocol is added to the existing UEFI handle.
603
604 @retval EFI_SUCCESS The protocol was added to ChildHandle.
605 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
606 @retval other The child handle was not created.
607
608**/
609EFI_STATUS
610EFIAPI
611Dhcp6ServiceBindingCreateChild (
612 IN EFI_SERVICE_BINDING_PROTOCOL *This,
613 IN OUT EFI_HANDLE *ChildHandle
614 )
615{
616 EFI_STATUS Status;
617 EFI_TPL OldTpl;
618 DHCP6_SERVICE *Service;
619 DHCP6_INSTANCE *Instance;
620 VOID *Udp6;
621
622 if ((This == NULL) || (ChildHandle == NULL)) {
623 return EFI_INVALID_PARAMETER;
624 }
625
626 Service = DHCP6_SERVICE_FROM_THIS (This);
627
628 Status = Dhcp6CreateInstance (Service, &Instance);
629
630 if (EFI_ERROR (Status)) {
631 return Status;
632 }
633
634 ASSERT (Instance != NULL);
635
636 //
637 // Start the timer when the instance is ready to use.
638 //
639 Status = gBS->SetTimer (
640 Instance->Timer,
641 TimerPeriodic,
642 TICKS_PER_SECOND
643 );
644
645 if (EFI_ERROR (Status)) {
646 goto ON_ERROR;
647 }
648
649 //
650 // Install the DHCP6 protocol onto ChildHandle.
651 //
652 Status = gBS->InstallMultipleProtocolInterfaces (
653 ChildHandle,
654 &gEfiDhcp6ProtocolGuid,
655 &Instance->Dhcp6,
656 NULL
657 );
658
659 if (EFI_ERROR (Status)) {
660 goto ON_ERROR;
661 }
662
663 Instance->Handle = *ChildHandle;
664
665 //
666 // Open the UDP6 protocol BY_CHILD.
667 //
668 Status = gBS->OpenProtocol (
669 Service->UdpIo->UdpHandle,
670 &gEfiUdp6ProtocolGuid,
671 (VOID **)&Udp6,
672 gDhcp6DriverBinding.DriverBindingHandle,
673 Instance->Handle,
674 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
675 );
676
677 if (EFI_ERROR (Status)) {
678 gBS->UninstallMultipleProtocolInterfaces (
679 Instance->Handle,
680 &gEfiDhcp6ProtocolGuid,
681 &Instance->Dhcp6,
682 NULL
683 );
684 goto ON_ERROR;
685 }
686
687 //
688 // Add into the children list of its parent service.
689 //
690 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
691
692 InsertTailList (&Service->Child, &Instance->Link);
693 Service->NumOfChild++;
694
695 gBS->RestoreTPL (OldTpl);
696 return EFI_SUCCESS;
697
698ON_ERROR:
699
700 Dhcp6DestroyInstance (Instance);
701 return Status;
702}
703
704/**
705 Destroys a child handle with a protocol installed on it.
706
707 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
708 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
709 last protocol on ChildHandle, then ChildHandle is destroyed.
710
711 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
712 @param[in] ChildHandle Handle of the child to destroy
713
714 @retval EFI_SUCCESS The protocol was removed from ChildHandle.
715 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
716 @retval EFI_INVALID_PARAMETER Child handle is NULL.
717 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
718 because its services are being used.
719 @retval other The child handle was not destroyed
720
721**/
722EFI_STATUS
723EFIAPI
724Dhcp6ServiceBindingDestroyChild (
725 IN EFI_SERVICE_BINDING_PROTOCOL *This,
726 IN EFI_HANDLE ChildHandle
727 )
728{
729 EFI_STATUS Status;
730 EFI_TPL OldTpl;
731 EFI_DHCP6_PROTOCOL *Dhcp6;
732 DHCP6_SERVICE *Service;
733 DHCP6_INSTANCE *Instance;
734
735 if ((This == NULL) || (ChildHandle == NULL)) {
736 return EFI_INVALID_PARAMETER;
737 }
738
739 //
740 // Retrieve the private context data structures
741 //
742 Status = gBS->OpenProtocol (
743 ChildHandle,
744 &gEfiDhcp6ProtocolGuid,
745 (VOID **)&Dhcp6,
746 gDhcp6DriverBinding.DriverBindingHandle,
747 ChildHandle,
748 EFI_OPEN_PROTOCOL_GET_PROTOCOL
749 );
750
751 if (EFI_ERROR (Status)) {
752 return EFI_UNSUPPORTED;
753 }
754
755 Instance = DHCP6_INSTANCE_FROM_THIS (Dhcp6);
756 Service = DHCP6_SERVICE_FROM_THIS (This);
757
758 if (Instance->Service != Service) {
759 return EFI_INVALID_PARAMETER;
760 }
761
762 if (Instance->InDestroy) {
763 return EFI_SUCCESS;
764 }
765
766 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
767
768 Instance->InDestroy = TRUE;
769
770 Status = gBS->CloseProtocol (
771 Service->UdpIo->UdpHandle,
772 &gEfiUdp6ProtocolGuid,
773 gDhcp6DriverBinding.DriverBindingHandle,
774 ChildHandle
775 );
776
777 if (EFI_ERROR (Status)) {
778 Instance->InDestroy = FALSE;
779 gBS->RestoreTPL (OldTpl);
780 return Status;
781 }
782
783 //
784 // Uninstall the MTFTP6 protocol first to enable a top down destruction.
785 //
786 gBS->RestoreTPL (OldTpl);
787 Status = gBS->UninstallProtocolInterface (
788 ChildHandle,
789 &gEfiDhcp6ProtocolGuid,
790 Dhcp6
791 );
792 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
793 if (EFI_ERROR (Status)) {
794 Instance->InDestroy = FALSE;
795 gBS->RestoreTPL (OldTpl);
796 return Status;
797 }
798
799 //
800 // Remove it from the children list of its parent service.
801 //
802 RemoveEntryList (&Instance->Link);
803 Service->NumOfChild--;
804
805 gBS->RestoreTPL (OldTpl);
806
807 Dhcp6DestroyInstance (Instance);
808 return EFI_SUCCESS;
809}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette