2 Implementation of Platform Driver Override Library.
4 Copyright (c) 2007 - 2008, Intel Corporation
5 All rights reserved. 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
8 http://opensource.org/licenses/bsd-license.php
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.
15 #include "PlatDriOver.h"
17 LIST_ENTRY mDevicePathStack
= INITIALIZE_LIST_HEAD_VARIABLE (mDevicePathStack
);
21 Installs the Platform Driver Override Protocol.
23 This function installs the Platform Driver Override Protocol, and ensure there is only one
24 Platform Driver Override Protocol in the system.
26 @param gPlatformDriverOverride PlatformDriverOverride protocol interface which
29 @retval EFI_SUCCESS The protocol is installed successfully.
30 @retval EFI_ALREADY_STARTED There has been a Platform Driver Override
31 Protocol in the system, cannot install it again.
36 InstallPlatformDriverOverrideProtocol (
37 EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL
*gPlatformDriverOverride
43 EFI_HANDLE
*HandleBuffer
;
46 // According to UEFI spec, there can be at most a single instance
47 // in the system of the EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL.
48 // So here we check the existence.
50 Status
= gBS
->LocateHandleBuffer (
52 &gEfiPlatformDriverOverrideProtocolGuid
,
58 // If there was no error, assume there is an installation and return error
60 if (!EFI_ERROR (Status
)) {
61 if (HandleBuffer
!= NULL
) {
62 FreePool (HandleBuffer
);
64 return EFI_ALREADY_STARTED
;
68 // Install platform driver override protocol
71 Status
= gBS
->InstallProtocolInterface (
73 &gEfiPlatformDriverOverrideProtocolGuid
,
75 gPlatformDriverOverride
77 ASSERT_EFI_ERROR (Status
);
83 Free all the mapping database memory resource and initialize the mapping list entry.
85 @param MappingDataBase Mapping database list entry pointer
87 @retval EFI_SUCCESS Mapping database successfully freed
88 @retval EFI_INVALID_PARAMETER MappingDataBase is NULL
94 IN OUT LIST_ENTRY
*MappingDataBase
97 LIST_ENTRY
*OverrideItemListIndex
;
98 LIST_ENTRY
*ImageInfoListIndex
;
99 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
100 DRIVER_IMAGE_INFO
*DriverImageInfo
;
102 if (MappingDataBase
== NULL
) {
103 return EFI_INVALID_PARAMETER
;
106 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
107 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
108 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
110 // Free PLATFORM_OVERRIDE_ITEM.ControllerDevicePath[]
112 if (OverrideItem
->ControllerDevicePath
!= NULL
){
113 FreePool (OverrideItem
->ControllerDevicePath
);
116 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
117 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
119 // Free DRIVER_IMAGE_INFO.DriverImagePath[]
121 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
122 if (DriverImageInfo
->DriverImagePath
!= NULL
) {
123 FreePool(DriverImageInfo
->DriverImagePath
);
126 // Free DRIVER_IMAGE_INFO itself
128 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
129 RemoveEntryList (&DriverImageInfo
->Link
);
130 FreePool (DriverImageInfo
);
133 // Free PLATFORM_OVERRIDE_ITEM itself
135 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
136 RemoveEntryList (&OverrideItem
->Link
);
137 FreePool (OverrideItem
);
140 InitializeListHead (MappingDataBase
);
146 Create the mappging database according to variable.
148 Read the environment variable(s) that contain the override mappings from Controller Device Path to
149 a set of Driver Device Paths, and create the mapping database in memory with those variable info.
152 // NotEnd indicate whether the variable is the last one, and has no subsequent variable need to load.
153 // Each variable has MaximumVariableSize limitation, so we maybe need multiple variables to store
154 // large mapping infos.
155 // The variable(s) name rule is PlatDriOver, PlatDriOver1, PlatDriOver2, ....
159 // The entry which contains the mapping that Controller Device Path to a set of Driver Device Paths
160 // There are often multi mapping entries in a variable.
162 UINT32 SIGNATURE; //SIGNATURE_32('p','d','o','i')
164 EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[];
165 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
166 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
167 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
171 EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[];
172 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
173 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
174 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
178 @param MappingDataBase Mapping database list entry pointer
180 @retval EFI_SUCCESS Create the mapping database in memory successfully
181 @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null
182 @retval EFI_NOT_FOUND Cannot find the 'PlatDriOver' NV variable
183 @retval EFI_VOLUME_CORRUPTED The found NV variable is corrupted
188 InitOverridesMapping (
189 OUT LIST_ENTRY
*MappingDataBase
193 VOID
*VariableBuffer
;
194 UINT8
*VariableIndex
;
196 CHAR16 OverrideVariableName
[40];
199 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
200 DRIVER_IMAGE_INFO
*DriverImageInfo
;
203 EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
;
204 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
207 if (MappingDataBase
== NULL
) {
208 return EFI_INVALID_PARAMETER
;
212 // Check the environment variable(s) that contain the override mappings .
214 VariableBuffer
= GetVariableAndSize (L
"PlatDriOver", &gEfiOverrideVariableGuid
, &BufferSize
);
215 ASSERT ((UINTN
) VariableBuffer
% sizeof(UINTN
) == 0);
216 if (VariableBuffer
== NULL
) {
217 return EFI_NOT_FOUND
;
221 // Traverse all variables.
226 VariableIndex
= VariableBuffer
;
227 NotEnd
= *(UINT32
*) VariableIndex
;
229 // Traverse the entries containing the mapping that Controller Device Path
230 // to a set of Driver Device Paths within this variable.
232 VariableIndex
= VariableIndex
+ sizeof (UINT32
);
233 while (VariableIndex
< ((UINT8
*)VariableBuffer
+ BufferSize
)) {
235 // Check signature of this entry
237 Signature
= *(UINT32
*) VariableIndex
;
238 if (Signature
!= PLATFORM_OVERRIDE_ITEM_SIGNATURE
) {
243 // Create PLATFORM_OVERRIDE_ITEM for this mapping
245 OverrideItem
= AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM
));
246 ASSERT (OverrideItem
!= NULL
);
247 OverrideItem
->Signature
= PLATFORM_OVERRIDE_ITEM_SIGNATURE
;
248 InitializeListHead (&OverrideItem
->DriverInfoList
);
249 VariableIndex
= VariableIndex
+ sizeof (UINT32
);
253 DriverNumber
= *(UINT32
*) VariableIndex
;
254 OverrideItem
->DriverInfoNum
= DriverNumber
;
255 VariableIndex
= VariableIndex
+ sizeof (UINT32
);
257 // Get ControllerDevicePath[]
259 ControllerDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) VariableIndex
;
260 OverrideItem
->ControllerDevicePath
= DuplicateDevicePath (ControllerDevicePath
);
261 VariableIndex
= VariableIndex
+ GetDevicePathSize (ControllerDevicePath
);
263 // Align the VariableIndex since the controller device path may not be aligned, refer to the SaveOverridesMapping()
265 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
268 // Get all DriverDevicePath[]
270 for (Index
= 0; Index
< DriverNumber
; Index
++) {
272 // Create DRIVER_IMAGE_INFO for this DriverDevicePath[]
274 DriverImageInfo
= AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO
));
275 ASSERT (DriverImageInfo
!= NULL
);
276 DriverImageInfo
->Signature
= DRIVER_IMAGE_INFO_SIGNATURE
;
278 DriverDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) VariableIndex
;
279 DriverImageInfo
->DriverImagePath
= DuplicateDevicePath (DriverDevicePath
);
280 VariableIndex
= VariableIndex
+ GetDevicePathSize (DriverDevicePath
);
282 // Align the VariableIndex since the driver image device path may not be aligned, refer to the SaveOverridesMapping()
284 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
286 InsertTailList (&OverrideItem
->DriverInfoList
, &DriverImageInfo
->Link
);
288 InsertTailList (MappingDataBase
, &OverrideItem
->Link
);
291 FreePool (VariableBuffer
);
293 FreeMappingDatabase (MappingDataBase
);
294 return EFI_VOLUME_CORRUPTED
;
298 // If there are additional variables (PlatDriOver1, PlatDriOver2, PlatDriOver3.....), get them.
299 // NotEnd indicates whether current variable is the end variable.
302 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", VariableNum
);
303 VariableBuffer
= GetVariableAndSize (OverrideVariableName
, &gEfiOverrideVariableGuid
, &BufferSize
);
304 ASSERT ((UINTN
) VariableBuffer
% sizeof(UINTN
) == 0);
306 if (VariableBuffer
== NULL
) {
307 FreeMappingDatabase (MappingDataBase
);
308 return EFI_VOLUME_CORRUPTED
;
312 } while (NotEnd
!= 0);
319 Calculate the needed size in NV variable for recording a specific PLATFORM_OVERRIDE_ITEM info.
321 @param OverrideItemListIndex Pointer to the list of a specific PLATFORM_OVERRIDE_ITEM
323 @return The needed size number
328 GetOneItemNeededSize (
329 IN LIST_ENTRY
*OverrideItemListIndex
333 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
334 LIST_ENTRY
*ImageInfoListIndex
;
335 DRIVER_IMAGE_INFO
*DriverImageInfo
;
336 UINTN DevicePathSize
;
339 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
340 NeededSize
+= sizeof (UINT32
); //UINT32 SIGNATURE;
341 NeededSize
+= sizeof (UINT32
); //UINT32 DriverNum;
342 DevicePathSize
= GetDevicePathSize (OverrideItem
->ControllerDevicePath
);
343 NeededSize
+= DevicePathSize
; // ControllerDevicePath
345 // Align the controller device path
347 NeededSize
+= ((sizeof(UINT32
) - DevicePathSize
) & (sizeof(UINT32
) - 1));
349 // Traverse the Driver Info List of this Override Item
351 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
352 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
353 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
354 DevicePathSize
= GetDevicePathSize (DriverImageInfo
->DriverImagePath
);
355 NeededSize
+= DevicePathSize
; //DriverDevicePath
357 // Align the driver image device path
359 NeededSize
+= ((sizeof(UINT32
) - DevicePathSize
) & (sizeof(UINT32
) - 1));
360 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
369 Save the memory mapping database into NV environment variable(s).
371 @param MappingDataBase Mapping database list entry pointer
373 @retval EFI_SUCCESS Save memory mapping database successfully
374 @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null
379 SaveOverridesMapping (
380 IN LIST_ENTRY
*MappingDataBase
384 VOID
*VariableBuffer
;
385 UINT8
*VariableIndex
;
387 CHAR16 OverrideVariableName
[40];
389 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
390 DRIVER_IMAGE_INFO
*DriverImageInfo
;
391 LIST_ENTRY
*OverrideItemListIndex
;
392 LIST_ENTRY
*ItemIndex
;
393 LIST_ENTRY
*ImageInfoListIndex
;
394 UINTN VariableNeededSize
;
395 UINT64 MaximumVariableStorageSize
;
396 UINT64 RemainingVariableStorageSize
;
397 UINT64 MaximumVariableSize
;
398 UINTN OneItemNeededSize
;
400 if (MappingDataBase
== NULL
) {
401 return EFI_INVALID_PARAMETER
;
404 if (IsListEmpty (MappingDataBase
)) {
405 Status
= DeleteOverridesVariables ();
406 ASSERT_EFI_ERROR (Status
);
411 // Get the the maximum size of an individual EFI variable in current system
413 gRT
->QueryVariableInfo (
414 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
415 &MaximumVariableStorageSize
,
416 &RemainingVariableStorageSize
,
421 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
422 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
424 // Try to find the most proper variable size which <= MaximumVariableSize,
425 // but can contain mapping info as much as possible
427 VariableNeededSize
= sizeof (UINT32
); // NotEnd;
428 ItemIndex
= OverrideItemListIndex
;
431 // Traverse all PLATFORM_OVERRIDE_ITEMs and get the total size.
433 while (!IsNull (MappingDataBase
, ItemIndex
)) {
434 OneItemNeededSize
= GetOneItemNeededSize (ItemIndex
);
436 // If the total size exceeds the MaximumVariableSize, then we must use
437 // multiple variables.
439 if ((VariableNeededSize
+
441 sizeof (VARIABLE_HEADER
) +
442 StrSize (L
"PlatDriOver ")
443 ) >= MaximumVariableSize
449 VariableNeededSize
+= OneItemNeededSize
;
450 ItemIndex
= GetNextNode (MappingDataBase
, ItemIndex
);
454 if (VariableNeededSize
== sizeof (UINT32
)) {
456 // If an individual EFI variable cannot contain a single Item, return error
458 return EFI_OUT_OF_RESOURCES
;
463 // VariableNeededSize is the most proper variable size, allocate variable buffer
464 // ItemIndex now points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize
466 VariableBuffer
= AllocateZeroPool (VariableNeededSize
);
467 ASSERT ((UINTN
) VariableBuffer
% sizeof(UINTN
) == 0);
470 // Fill the variable buffer according to MappingDataBase
472 VariableIndex
= VariableBuffer
;
473 *(UINT32
*) VariableIndex
= NotEnd
;
474 VariableIndex
+= sizeof (UINT32
); // pass NotEnd
476 // ItemIndex points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize
478 while (OverrideItemListIndex
!= ItemIndex
){
479 *(UINT32
*) VariableIndex
= PLATFORM_OVERRIDE_ITEM_SIGNATURE
;
480 VariableIndex
+= sizeof (UINT32
); // pass SIGNATURE
482 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
483 *(UINT32
*) VariableIndex
= OverrideItem
->DriverInfoNum
;
484 VariableIndex
+= sizeof (UINT32
); // pass DriverNum
486 CopyMem (VariableIndex
, OverrideItem
->ControllerDevicePath
, GetDevicePathSize (OverrideItem
->ControllerDevicePath
));
487 VariableIndex
+= GetDevicePathSize (OverrideItem
->ControllerDevicePath
); // pass ControllerDevicePath
490 // Align the VariableIndex since the controller device path may not be aligned
492 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
494 // Save the Driver Info List of this PLATFORM_OVERRIDE_ITEM
496 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
497 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
498 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
499 CopyMem (VariableIndex
, DriverImageInfo
->DriverImagePath
, GetDevicePathSize (DriverImageInfo
->DriverImagePath
));
500 VariableIndex
+= GetDevicePathSize (DriverImageInfo
->DriverImagePath
); // pass DriverImageDevicePath
502 // Align the VariableIndex since the driver image device path may not be aligned
504 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
505 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
508 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
511 ASSERT (((UINTN
)VariableIndex
- (UINTN
)VariableBuffer
) == VariableNeededSize
);
514 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver");
516 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", NumIndex
);
519 Status
= gRT
->SetVariable (
520 OverrideVariableName
,
521 &gEfiOverrideVariableGuid
,
522 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
526 ASSERT (!EFI_ERROR(Status
));
529 FreePool (VariableBuffer
);
536 Get the first Binding protocol which has the specific image handle.
538 @param ImageHandle The Image handle
539 @param BindingHandle The BindingHandle of the found Driver Binding protocol.
540 If Binding protocol is not found, it is set to NULL.
542 @return Pointer into the Binding Protocol interface
543 @retval NULL The paramter is not valid or the binding protocol is not found.
546 EFI_DRIVER_BINDING_PROTOCOL
*
548 GetBindingProtocolFromImageHandle (
549 IN EFI_HANDLE ImageHandle
,
550 OUT EFI_HANDLE
*BindingHandle
555 UINTN DriverBindingHandleCount
;
556 EFI_HANDLE
*DriverBindingHandleBuffer
;
557 EFI_DRIVER_BINDING_PROTOCOL
*DriverBindingInterface
;
559 if (BindingHandle
== NULL
|| ImageHandle
== NULL
) {
563 // Get all drivers which support driver binding protocol
565 DriverBindingHandleCount
= 0;
566 Status
= gBS
->LocateHandleBuffer (
568 &gEfiDriverBindingProtocolGuid
,
570 &DriverBindingHandleCount
,
571 &DriverBindingHandleBuffer
573 if (EFI_ERROR (Status
) || (DriverBindingHandleCount
== 0)) {
577 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
578 DriverBindingInterface
= NULL
;
579 Status
= gBS
->OpenProtocol (
580 DriverBindingHandleBuffer
[Index
],
581 &gEfiDriverBindingProtocolGuid
,
582 (VOID
**) &DriverBindingInterface
,
585 EFI_OPEN_PROTOCOL_GET_PROTOCOL
587 if (EFI_ERROR (Status
)) {
591 if (DriverBindingInterface
->ImageHandle
== ImageHandle
) {
592 *BindingHandle
= DriverBindingHandleBuffer
[Index
];
593 FreePool (DriverBindingHandleBuffer
);
594 return DriverBindingInterface
;
599 // If no Driver Binding Protocol instance is found
601 FreePool (DriverBindingHandleBuffer
);
602 *BindingHandle
= NULL
;
607 Return the current TPL.
619 Tpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
620 gBS
->RestoreTPL (Tpl
);
627 Retrieves the image handle of the platform override driver for a controller in
628 the system from the memory mapping database.
630 @param This A pointer to the
631 EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL instance.
632 @param ControllerHandle The device handle of the controller to check if
633 a driver override exists.
634 @param DriverImageHandle On input, the previously returnd driver image handle.
635 On output, a pointer to the next driver handle.
636 Passing in a pointer to NULL, will return the
637 first driver handle for ControllerHandle.
638 @param MappingDataBase Mapping database list entry pointer
639 @param CallerImageHandle The caller driver's image handle, for
640 UpdateFvFileDevicePath use.
642 @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not
643 a valid handle. Or DriverImagePath is not a
644 device path that was returned on a previous call
646 @retval EFI_NOT_FOUND A driver override for ControllerHandle was not
648 @retval EFI_UNSUPPORTED The operation is not supported.
649 @retval EFI_SUCCESS The driver override for ControllerHandle was
650 returned in DriverImagePath.
655 GetDriverFromMapping (
656 IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL
*This
,
657 IN EFI_HANDLE ControllerHandle
,
658 IN OUT EFI_HANDLE
*DriverImageHandle
,
659 IN LIST_ENTRY
*MappingDataBase
,
660 IN EFI_HANDLE CallerImageHandle
664 EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
;
665 BOOLEAN ControllerFound
;
667 EFI_HANDLE
*ImageHandleBuffer
;
668 UINTN ImageHandleCount
;
670 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
671 EFI_HANDLE DriverBindingHandle
;
672 BOOLEAN FoundLastReturned
;
673 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
674 DRIVER_IMAGE_INFO
*DriverImageInfo
;
675 LIST_ENTRY
*OverrideItemListIndex
;
676 LIST_ENTRY
*ImageInfoListIndex
;
677 EFI_DEVICE_PATH_PROTOCOL
*TempDriverImagePath
;
678 EFI_HANDLE ImageHandle
;
680 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
681 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*BusSpecificDriverOverride
;
682 UINTN DevicePathSize
;
685 // Check that ControllerHandle is a valid handle
687 if (ControllerHandle
== NULL
) {
688 return EFI_INVALID_PARAMETER
;
691 // Get the device path of ControllerHandle
693 Status
= gBS
->HandleProtocol (
695 &gEfiDevicePathProtocolGuid
,
696 (VOID
**) &ControllerDevicePath
698 if (EFI_ERROR (Status
) || ControllerDevicePath
== NULL
) {
699 return EFI_INVALID_PARAMETER
;
703 // Search ControllerDevicePath in MappingDataBase
706 ControllerFound
= FALSE
;
707 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
709 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
710 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
711 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
712 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
714 ControllerDevicePath
,
715 OverrideItem
->ControllerDevicePath
,
719 ControllerFound
= TRUE
;
723 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
726 if (!ControllerFound
) {
727 return EFI_NOT_FOUND
;
730 // Passing in a pointer to NULL, will return the first driver device path for ControllerHandle.
731 // Check whether the driverImagePath is not a device path that was returned on a previous call to GetDriverPath().
733 if (*DriverImageHandle
!= NULL
) {
734 if (*DriverImageHandle
!= OverrideItem
->LastReturnedImageHandle
) {
735 return EFI_INVALID_PARAMETER
;
739 // The GetDriverPath() may be called recursively, because it use ConnectDevicePath() internally,
740 // so should check whether there is a dead loop.
741 // Here use a controller device path stack to record all processed controller device path during a GetDriverPath() call,
742 // and check the controller device path whether appear again during the GetDriverPath() call.
744 if (CheckExistInStack (OverrideItem
->ControllerDevicePath
)) {
746 // There is a dependecy dead loop if the ControllerDevicePath appear in stack twice
748 return EFI_UNSUPPORTED
;
750 PushDevPathStack (OverrideItem
->ControllerDevicePath
);
753 // Check every override driver, try to load and start them
755 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
756 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
757 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
758 if (DriverImageInfo
->ImageHandle
== NULL
) {
760 // Skip if the image is unloadable or unstartable
762 if ((!DriverImageInfo
->UnLoadable
) && ((!DriverImageInfo
->UnStartable
))) {
763 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
765 // If the image device path contains an FV node, check the FV file device path is valid.
766 // If it is invalid, try to return the valid device path.
767 // FV address maybe changes for memory layout adjust from time to time,
768 // use this funciton could promise the FV file device path is right.
770 Status
= UpdateFvFileDevicePath (&TempDriverImagePath
, NULL
, CallerImageHandle
);
771 if (!EFI_ERROR (Status
)) {
772 FreePool (DriverImageInfo
->DriverImagePath
);
773 DriverImageInfo
->DriverImagePath
= TempDriverImagePath
;
776 // Get all Loaded Image protocol to check whether the driver image has been loaded and started
779 ImageHandleCount
= 0;
780 Status
= gBS
->LocateHandleBuffer (
782 &gEfiLoadedImageProtocolGuid
,
787 if (EFI_ERROR (Status
) || (ImageHandleCount
== 0)) {
788 return EFI_NOT_FOUND
;
791 for(Index
= 0; Index
< ImageHandleCount
; Index
++) {
793 // Get the EFI Loaded Image Device Path Protocol
795 LoadedImageDevicePath
= NULL
;
796 Status
= gBS
->HandleProtocol (
797 ImageHandleBuffer
[Index
],
798 &gEfiLoadedImageDevicePathProtocolGuid
,
799 (VOID
**) &LoadedImageDevicePath
801 if (EFI_ERROR (Status
)) {
803 // Maybe not all EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL existed.
808 DevicePathSize
= GetDevicePathSize (DriverImageInfo
->DriverImagePath
);
809 if (DevicePathSize
== GetDevicePathSize (LoadedImageDevicePath
)) {
811 DriverImageInfo
->DriverImagePath
,
812 LoadedImageDevicePath
,
813 GetDevicePathSize (LoadedImageDevicePath
)
824 // Find its related driver binding protocol
825 // Driver binding handle may be different with its driver's Image Handle.
827 DriverBindingHandle
= NULL
;
828 DriverBinding
= GetBindingProtocolFromImageHandle (
829 ImageHandleBuffer
[Index
],
832 ASSERT (DriverBinding
!= NULL
);
833 DriverImageInfo
->ImageHandle
= ImageHandleBuffer
[Index
];
834 } else if (GetCurrentTpl() <= TPL_CALLBACK
){
836 // The driver image has not been loaded and started. Try to load and start it now.
837 // Try to connect all device in the driver image path.
839 // Note: LoadImage() and StartImage() should be called under CALLBACK TPL in theory, but
840 // since many device need to be connected in CALLBACK level environment( e.g. Usb devices )
841 // and the Fat and Patition driver can endure executing in CALLBACK level in fact, so here permit
842 // to use LoadImage() and StartImage() in CALLBACK TPL.
844 Status
= ConnectDevicePath (DriverImageInfo
->DriverImagePath
);
846 // check whether it points to a PCI Option Rom image,
847 // and try to use bus override protocol to get its first option rom image driver
849 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
850 gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &TempDriverImagePath
, &Handle
);
852 // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
854 Status
= gBS
->HandleProtocol(
856 &gEfiBusSpecificDriverOverrideProtocolGuid
,
857 (VOID
**) &BusSpecificDriverOverride
859 if (!EFI_ERROR (Status
) && (BusSpecificDriverOverride
!= NULL
)) {
861 Status
= BusSpecificDriverOverride
->GetDriver (
862 BusSpecificDriverOverride
,
865 if (!EFI_ERROR (Status
)) {
867 // Find its related driver binding protocol
868 // Driver binding handle may be different with its driver's Image handle
870 DriverBindingHandle
= NULL
;
871 DriverBinding
= GetBindingProtocolFromImageHandle (
875 ASSERT (DriverBinding
!= NULL
);
876 DriverImageInfo
->ImageHandle
= ImageHandle
;
880 // Skip if any device cannot be connected now, future passes through GetDriver() may be able to load that driver.
881 // Only file path media or FwVol Device Path Node remain if all device is connected
883 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
884 gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &TempDriverImagePath
, &Handle
);
885 if (((DevicePathType (TempDriverImagePath
) == MEDIA_DEVICE_PATH
) &&
886 (DevicePathSubType (TempDriverImagePath
) == MEDIA_FILEPATH_DP
)) ||
887 (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempDriverImagePath
) != NULL
)
890 // Try to load the driver
892 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
893 Status
= gBS
->LoadImage (
901 if (!EFI_ERROR (Status
)) {
903 // Try to start the driver
905 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
906 if (EFI_ERROR (Status
)){
907 DriverImageInfo
->UnStartable
= TRUE
;
908 DriverImageInfo
->ImageHandle
= NULL
;
911 // Find its related driver binding protocol
912 // Driver binding handle may be different with its driver's Image handle
914 DriverBindingHandle
= NULL
;
915 DriverBinding
= GetBindingProtocolFromImageHandle (
919 ASSERT (DriverBinding
!= NULL
);
920 DriverImageInfo
->ImageHandle
= ImageHandle
;
923 DriverImageInfo
->UnLoadable
= TRUE
;
924 DriverImageInfo
->ImageHandle
= NULL
;
928 FreePool (ImageHandleBuffer
);
931 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
934 // Finish try to load and start the override driver of a controller, popup the controller's device path
936 PopDevPathStack (NULL
);
939 // return the DriverImageHandle for ControllerHandle
941 FoundLastReturned
= FALSE
;
942 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
943 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
944 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
945 if (DriverImageInfo
->ImageHandle
!= NULL
) {
946 if ((*DriverImageHandle
== NULL
) || FoundLastReturned
) {
948 // If DriverImageHandle is NULL, then we just need to return the first driver.
949 // If FoundLastReturned, this means we have just encountered the previously returned driver.
950 // For both cases, we just return the image handle of this driver.
952 OverrideItem
->LastReturnedImageHandle
= DriverImageInfo
->ImageHandle
;
953 *DriverImageHandle
= DriverImageInfo
->ImageHandle
;
955 } else if (*DriverImageHandle
== DriverImageInfo
->ImageHandle
){
957 // We have found the previously returned driver.
959 FoundLastReturned
= TRUE
;
962 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
965 return EFI_NOT_FOUND
;
970 Check mapping database whether already has the mapping info which
971 records the input Controller to input DriverImage.
973 @param ControllerDevicePath The controller device path is to be check.
974 @param DriverImageDevicePath The driver image device path is to be check.
975 @param MappingDataBase Mapping database list entry pointer
976 @param DriverInfoNum the controller's total override driver number
977 @param DriverImageNO The driver order number for the input DriverImage.
978 If the DriverImageDevicePath is NULL, DriverImageNO is not set.
980 @retval EFI_INVALID_PARAMETER ControllerDevicePath or MappingDataBase is NULL.
981 @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or
982 DriverImageDevicePath is not found in the found DriverImage Info list.
983 @retval EFI_SUCCESS The controller's total override driver number and
984 input DriverImage's order number is correctly return.
989 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
990 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath OPTIONAL
,
991 IN LIST_ENTRY
*MappingDataBase
,
992 OUT UINT32
*DriverInfoNum OPTIONAL
,
993 OUT UINT32
*DriverImageNO OPTIONAL
996 LIST_ENTRY
*OverrideItemListIndex
;
997 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
998 LIST_ENTRY
*ImageInfoListIndex
;
999 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1002 UINTN DevicePathSize
;
1004 if (ControllerDevicePath
== NULL
) {
1005 return EFI_INVALID_PARAMETER
;
1007 if (MappingDataBase
== NULL
) {
1008 return EFI_INVALID_PARAMETER
;
1012 // Search ControllerDevicePath in MappingDataBase
1015 OverrideItem
= NULL
;
1016 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1017 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1018 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1019 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1020 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1022 ControllerDevicePath
,
1023 OverrideItem
->ControllerDevicePath
,
1031 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1036 // ControllerDevicePath is not in MappingDataBase
1038 return EFI_NOT_FOUND
;
1041 ASSERT (OverrideItem
->DriverInfoNum
!= 0);
1042 if (DriverInfoNum
!= NULL
) {
1043 *DriverInfoNum
= OverrideItem
->DriverInfoNum
;
1047 // If DriverImageDevicePath is NULL, skip checking DriverImageDevicePath
1048 // in the controller's Driver Image Info List
1050 if (DriverImageDevicePath
== NULL
) {
1054 // return the DriverImageHandle for ControllerHandle
1058 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1059 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1060 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1062 DevicePathSize
= GetDevicePathSize (DriverImageDevicePath
);
1063 if (DevicePathSize
== GetDevicePathSize (DriverImageInfo
->DriverImagePath
)) {
1065 DriverImageDevicePath
,
1066 DriverImageInfo
->DriverImagePath
,
1067 GetDevicePathSize (DriverImageInfo
->DriverImagePath
)
1074 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1079 // DriverImageDevicePath is not found in the controller's Driver Image Info List
1081 return EFI_NOT_FOUND
;
1083 if (DriverImageNO
!= NULL
) {
1084 *DriverImageNO
= ImageNO
;
1092 Insert a driver image as a controller's override driver into the mapping database.
1093 The driver image's order number is indicated by DriverImageNO.
1095 @param ControllerDevicePath The controller device path need to add a
1096 override driver image item
1097 @param DriverImageDevicePath The driver image device path need to be insert
1098 @param MappingDataBase Mapping database list entry pointer
1099 @param DriverImageNO The inserted order number. If this number is taken,
1100 the larger available number will be used.
1102 @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or DriverImageDevicePath is NULL
1103 or MappingDataBase is NULL
1104 @retval EFI_ALREADY_STARTED The input Controller to input DriverImage has been
1105 recorded into the mapping database.
1106 @retval EFI_SUCCESS The Controller and DriverImage are inserted into
1107 the mapping database successfully.
1113 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
1114 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath
,
1115 IN LIST_ENTRY
*MappingDataBase
,
1116 IN UINT32 DriverImageNO
1120 LIST_ENTRY
*OverrideItemListIndex
;
1121 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1122 LIST_ENTRY
*ImageInfoListIndex
;
1123 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1126 UINTN DevicePathSize
;
1128 if (ControllerDevicePath
== NULL
) {
1129 return EFI_INVALID_PARAMETER
;
1131 if (DriverImageDevicePath
== NULL
) {
1132 return EFI_INVALID_PARAMETER
;
1134 if (MappingDataBase
== NULL
) {
1135 return EFI_INVALID_PARAMETER
;
1139 // If the driver is already in the controller's Driver Image Info List,
1140 // just return EFI_ALREADY_STARTED.
1142 Status
= CheckMapping (
1143 ControllerDevicePath
,
1144 DriverImageDevicePath
,
1149 if (Status
== EFI_SUCCESS
) {
1150 return EFI_ALREADY_STARTED
;
1154 // Search the input ControllerDevicePath in MappingDataBase
1157 OverrideItem
= NULL
;
1158 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1159 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1160 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1161 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1162 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1164 ControllerDevicePath
,
1165 OverrideItem
->ControllerDevicePath
,
1173 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1176 // If cannot find, this is a new controller item
1177 // Add the Controller related PLATFORM_OVERRIDE_ITEM structrue in mapping data base
1180 OverrideItem
= AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM
));
1181 ASSERT (OverrideItem
!= NULL
);
1182 OverrideItem
->Signature
= PLATFORM_OVERRIDE_ITEM_SIGNATURE
;
1183 OverrideItem
->ControllerDevicePath
= DuplicateDevicePath (ControllerDevicePath
);
1184 InitializeListHead (&OverrideItem
->DriverInfoList
);
1185 InsertTailList (MappingDataBase
, &OverrideItem
->Link
);
1189 // Prepare the driver image related DRIVER_IMAGE_INFO structure.
1191 DriverImageInfo
= AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO
));
1192 ASSERT (DriverImageInfo
!= NULL
);
1193 DriverImageInfo
->Signature
= DRIVER_IMAGE_INFO_SIGNATURE
;
1194 DriverImageInfo
->DriverImagePath
= DuplicateDevicePath (DriverImageDevicePath
);
1196 // Find the driver image wanted order location
1200 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1201 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1202 if (ImageNO
== (DriverImageNO
- 1)) {
1204 // find the wanted order location, insert it
1206 InsertTailList (ImageInfoListIndex
, &DriverImageInfo
->Link
);
1207 OverrideItem
->DriverInfoNum
++;
1212 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1217 // if not find the wantted order location, add it as last item of the controller mapping item
1219 InsertTailList (&OverrideItem
->DriverInfoList
, &DriverImageInfo
->Link
);
1220 OverrideItem
->DriverInfoNum
++;
1228 Delete a controller's override driver from the mapping database.
1230 @param ControllerDevicePath The controller device path will be deleted
1231 when all drivers images on it are removed.
1232 @param DriverImageDevicePath The driver image device path will be delete.
1233 If NULL, all driver image will be delete.
1234 @param MappingDataBase Mapping database list entry pointer
1236 @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or MappingDataBase is NULL
1237 @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or
1238 DriverImageDevicePath is not found in the found DriverImage Info list.
1239 @retval EFI_SUCCESS Delete the specified driver successfully.
1245 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
1246 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath
,
1247 IN LIST_ENTRY
*MappingDataBase
1251 LIST_ENTRY
*OverrideItemListIndex
;
1252 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1253 LIST_ENTRY
*ImageInfoListIndex
;
1254 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1256 UINTN DevicePathSize
;
1258 if (ControllerDevicePath
== NULL
) {
1259 return EFI_INVALID_PARAMETER
;
1262 if (MappingDataBase
== NULL
) {
1263 return EFI_INVALID_PARAMETER
;
1267 // If ControllerDevicePath is not found in mapping database, return EFI_NOT_FOUND.
1269 Status
= CheckMapping (
1270 ControllerDevicePath
,
1271 DriverImageDevicePath
,
1276 if (EFI_ERROR (Status
)) {
1277 return EFI_NOT_FOUND
;
1281 // Search ControllerDevicePath in MappingDataBase
1284 OverrideItem
= NULL
;
1285 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1286 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1287 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1288 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1289 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1291 ControllerDevicePath
,
1292 OverrideItem
->ControllerDevicePath
,
1300 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1304 ASSERT (OverrideItem
->DriverInfoNum
!= 0);
1307 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1308 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1309 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1310 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1311 if (DriverImageDevicePath
!= NULL
) {
1313 // Search for the specified DriverImageDevicePath and remove it, then break.
1315 DevicePathSize
= GetDevicePathSize (DriverImageDevicePath
);
1316 if (DevicePathSize
== GetDevicePathSize (DriverImageInfo
->DriverImagePath
)) {
1318 DriverImageDevicePath
,
1319 DriverImageInfo
->DriverImagePath
,
1320 GetDevicePathSize (DriverImageInfo
->DriverImagePath
)
1324 FreePool(DriverImageInfo
->DriverImagePath
);
1325 RemoveEntryList (&DriverImageInfo
->Link
);
1326 OverrideItem
->DriverInfoNum
--;
1332 // Remove all existing driver image info entries, so no break here.
1335 FreePool(DriverImageInfo
->DriverImagePath
);
1336 RemoveEntryList (&DriverImageInfo
->Link
);
1337 OverrideItem
->DriverInfoNum
--;
1342 // Confirm all driver image info entries have been removed,
1343 // if DriverImageDevicePath is NULL.
1345 if (DriverImageDevicePath
== NULL
) {
1346 ASSERT (OverrideItem
->DriverInfoNum
== 0);
1349 // If Override Item has no driver image info entry, then delete this item.
1351 if (OverrideItem
->DriverInfoNum
== 0) {
1352 FreePool(OverrideItem
->ControllerDevicePath
);
1353 RemoveEntryList (&OverrideItem
->Link
);
1354 FreePool (OverrideItem
);
1359 // DriverImageDevicePath is not NULL and cannot be found in the controller's
1360 // driver image info list.
1362 return EFI_NOT_FOUND
;
1370 Deletes all environment variable(s) that contain the override mappings from Controller Device Path to
1371 a set of Driver Device Paths.
1373 @retval EFI_SUCCESS Delete all variable(s) successfully.
1378 DeleteOverridesVariables (
1383 VOID
*VariableBuffer
;
1387 CHAR16 OverrideVariableName
[40];
1390 // Get environment variable(s) number
1393 VariableBuffer
= GetVariableAndSize (L
"PlatDriOver", &gEfiOverrideVariableGuid
, &BufferSize
);
1395 if (VariableBuffer
== NULL
) {
1396 return EFI_NOT_FOUND
;
1399 // Check NotEnd to get all PlatDriOverX variable(s)
1401 while ((*(UINT32
*)VariableBuffer
) != 0) {
1402 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", VariableNum
);
1403 VariableBuffer
= GetVariableAndSize (OverrideVariableName
, &gEfiOverrideVariableGuid
, &BufferSize
);
1405 ASSERT (VariableBuffer
!= NULL
);
1409 // Delete PlatDriOver and all additional variables, if exist.
1411 Status
= gRT
->SetVariable (
1413 &gEfiOverrideVariableGuid
,
1414 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1418 ASSERT (!EFI_ERROR (Status
));
1419 for (Index
= 1; Index
< VariableNum
; Index
++) {
1420 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", Index
);
1421 Status
= gRT
->SetVariable (
1422 OverrideVariableName
,
1423 &gEfiOverrideVariableGuid
,
1424 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1428 ASSERT (!EFI_ERROR (Status
));
1435 Push a controller device path into a globle device path list.
1437 @param DevicePath The controller device path to push into stack
1439 @retval EFI_SUCCESS Device path successfully pushed into the stack.
1445 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
1448 DEVICE_PATH_STACK_ITEM
*DevicePathStackItem
;
1450 DevicePathStackItem
= AllocateZeroPool (sizeof (DEVICE_PATH_STACK_ITEM
));
1451 ASSERT (DevicePathStackItem
!= NULL
);
1452 DevicePathStackItem
->Signature
= DEVICE_PATH_STACK_ITEM_SIGNATURE
;
1453 DevicePathStackItem
->DevicePath
= DuplicateDevicePath (DevicePath
);
1454 InsertTailList (&mDevicePathStack
, &DevicePathStackItem
->Link
);
1460 Pop a controller device path from a globle device path list
1462 @param DevicePath The controller device path popped from stack
1464 @retval EFI_SUCCESS Controller device path successfully popped.
1465 @retval EFI_NOT_FOUND Stack is empty.
1471 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
1474 DEVICE_PATH_STACK_ITEM
*DevicePathStackItem
;
1475 LIST_ENTRY
*ItemListIndex
;
1477 ItemListIndex
= mDevicePathStack
.BackLink
;
1479 // Check if the stack is empty
1481 if (ItemListIndex
!= &mDevicePathStack
){
1482 DevicePathStackItem
= CR(ItemListIndex
, DEVICE_PATH_STACK_ITEM
, Link
, DEVICE_PATH_STACK_ITEM_SIGNATURE
);
1483 if (DevicePath
!= NULL
) {
1484 *DevicePath
= DuplicateDevicePath (DevicePathStackItem
->DevicePath
);
1486 FreePool (DevicePathStackItem
->DevicePath
);
1487 RemoveEntryList (&DevicePathStackItem
->Link
);
1488 FreePool (DevicePathStackItem
);
1491 return EFI_NOT_FOUND
;
1496 Check whether a controller device path is in a globle device path list
1498 @param DevicePath The controller device path to check
1500 @retval TRUE DevicePath exists in the stack.
1501 @retval FALSE DevicePath does not exist in the stack.
1507 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
1510 DEVICE_PATH_STACK_ITEM
*DevicePathStackItem
;
1511 LIST_ENTRY
*ItemListIndex
;
1512 UINTN DevicePathSize
;
1514 ItemListIndex
= mDevicePathStack
.BackLink
;
1515 while (ItemListIndex
!= &mDevicePathStack
){
1516 DevicePathStackItem
= CR(ItemListIndex
, DEVICE_PATH_STACK_ITEM
, Link
, DEVICE_PATH_STACK_ITEM_SIGNATURE
);
1517 DevicePathSize
= GetDevicePathSize (DevicePath
);
1518 if (DevicePathSize
== GetDevicePathSize (DevicePathStackItem
->DevicePath
)) {
1519 if (CompareMem (DevicePath
, DevicePathStackItem
->DevicePath
, DevicePathSize
) == 0) {
1523 ItemListIndex
= ItemListIndex
->BackLink
;
1531 Update the FV file device path if it is not valid.
1533 According to a file GUID, check a Fv file device path is valid. If it is invalid,
1534 try to return the valid device path.
1535 FV address maybe changes for memory layout adjust from time to time, use this funciton
1536 could promise the Fv file device path is right.
1538 @param DevicePath On input, the FV file device path to check
1539 On output, the updated valid FV file device path
1540 @param FileGuid The FV file GUID
1541 @param CallerImageHandle Image handle of the caller
1543 @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid
1545 @retval EFI_UNSUPPORTED the input DevicePath does not contain FV file
1547 @retval EFI_ALREADY_STARTED the input DevicePath has pointed to FV file, it
1549 @retval EFI_SUCCESS Successfully updated the invalid DevicePath,
1550 and return the updated device path in DevicePath
1555 UpdateFvFileDevicePath (
1556 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
1557 IN EFI_GUID
*FileGuid
,
1558 IN EFI_HANDLE CallerImageHandle
1561 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1562 EFI_DEVICE_PATH_PROTOCOL
*LastDeviceNode
;
1564 EFI_GUID
*GuidPoint
;
1566 UINTN FvHandleCount
;
1567 EFI_HANDLE
*FvHandleBuffer
;
1568 EFI_FV_FILETYPE Type
;
1570 EFI_FV_FILE_ATTRIBUTES Attributes
;
1571 UINT32 AuthenticationStatus
;
1573 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
1574 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
1575 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode
;
1576 EFI_HANDLE FoundFvHandle
;
1577 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
1580 if (DevicePath
== NULL
) {
1581 return EFI_INVALID_PARAMETER
;
1584 if (*DevicePath
== NULL
) {
1585 return EFI_INVALID_PARAMETER
;
1589 // Check whether the device path points to the default the input FV file
1591 TempDevicePath
= *DevicePath
;
1592 LastDeviceNode
= TempDevicePath
;
1593 while (!IsDevicePathEnd (TempDevicePath
)) {
1594 LastDeviceNode
= TempDevicePath
;
1595 TempDevicePath
= NextDevicePathNode (TempDevicePath
);
1597 GuidPoint
= EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) LastDeviceNode
);
1598 if (GuidPoint
== NULL
) {
1600 // If this option does not point to a FV file, just return EFI_UNSUPPORTED.
1602 return EFI_UNSUPPORTED
;
1605 if (FileGuid
!= NULL
) {
1606 if (!CompareGuid (GuidPoint
, FileGuid
)) {
1608 // If the FV file is not the input file GUID, just return EFI_UNSUPPORTED
1610 return EFI_UNSUPPORTED
;
1613 FileGuid
= GuidPoint
;
1617 // Check to see if the device path contains memory map node
1619 TempDevicePath
= *DevicePath
;
1621 while (!IsDevicePathEnd (TempDevicePath
)) {
1623 // Use old Device Path
1625 if (DevicePathType (TempDevicePath
) == HARDWARE_DEVICE_PATH
&&
1626 DevicePathSubType (TempDevicePath
) == HW_MEMMAP_DP
) {
1630 TempDevicePath
= NextDevicePathNode (TempDevicePath
);
1634 return EFI_UNSUPPORTED
;
1638 // Check whether the input Fv file device path is valid
1640 TempDevicePath
= *DevicePath
;
1641 FoundFvHandle
= NULL
;
1642 Status
= gBS
->LocateDevicePath (
1643 &gEfiFirmwareVolume2ProtocolGuid
,
1647 if (!EFI_ERROR (Status
)) {
1648 Status
= gBS
->HandleProtocol (
1650 &gEfiFirmwareVolume2ProtocolGuid
,
1653 if (!EFI_ERROR (Status
)) {
1655 // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there
1657 Status
= Fv
->ReadFile (
1664 &AuthenticationStatus
1666 if (!EFI_ERROR (Status
)) {
1667 return EFI_ALREADY_STARTED
;
1673 // Look for the input wanted FV file in current FV
1674 // First, try to look for in Caller own FV. Caller and input wanted FV file usually are in the same FV
1677 FoundFvHandle
= NULL
;
1678 Status
= gBS
->HandleProtocol (
1680 &gEfiLoadedImageProtocolGuid
,
1681 (VOID
**) &LoadedImage
1683 if (!EFI_ERROR (Status
)) {
1684 Status
= gBS
->HandleProtocol (
1685 LoadedImage
->DeviceHandle
,
1686 &gEfiFirmwareVolume2ProtocolGuid
,
1689 if (!EFI_ERROR (Status
)) {
1690 Status
= Fv
->ReadFile (
1697 &AuthenticationStatus
1699 if (!EFI_ERROR (Status
)) {
1701 FoundFvHandle
= LoadedImage
->DeviceHandle
;
1706 // Second, if fail to find, try to enumerate all FV
1709 gBS
->LocateHandleBuffer (
1711 &gEfiFirmwareVolume2ProtocolGuid
,
1716 for (Index
= 0; Index
< FvHandleCount
; Index
++) {
1717 gBS
->HandleProtocol (
1718 FvHandleBuffer
[Index
],
1719 &gEfiFirmwareVolume2ProtocolGuid
,
1723 Status
= Fv
->ReadFile (
1730 &AuthenticationStatus
1732 if (EFI_ERROR (Status
)) {
1734 // Skip if input Fv file not in the FV
1739 FoundFvHandle
= FvHandleBuffer
[Index
];
1746 // Build the shell device path
1748 NewDevicePath
= DevicePathFromHandle (FoundFvHandle
);
1749 EfiInitializeFwVolDevicepathNode (&FvFileNode
, FileGuid
);
1750 NewDevicePath
= AppendDevicePathNode (NewDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) &FvFileNode
);
1751 *DevicePath
= NewDevicePath
;
1754 return EFI_NOT_FOUND
;
1759 Gets the data and size of a variable.
1761 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1762 buffer, and the size of the buffer. If failure return NULL.
1764 @param Name String part of EFI variable name
1765 @param VendorGuid GUID part of EFI variable name
1766 @param VariableSize Returns the size of the EFI variable that was
1769 @return Dynamically allocated memory that contains a copy of the EFI variable.
1770 Caller is responsible freeing the buffer.
1771 @retval NULL Variable was not read
1776 GetVariableAndSize (
1778 IN EFI_GUID
*VendorGuid
,
1779 OUT UINTN
*VariableSize
1789 // Pass in a zero size buffer to find the required buffer size.
1792 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1793 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1795 // Allocate the buffer to return
1797 Buffer
= AllocateZeroPool (BufferSize
);
1798 if (Buffer
== NULL
) {
1802 // Read variable into the allocated buffer.
1804 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1805 if (EFI_ERROR (Status
)) {
1810 *VariableSize
= BufferSize
;
1816 Connect to the handle to a device on the device path.
1818 This function will create all handles associate with every device
1819 path node. If the handle associate with one device path node can not
1820 be created success, then still give one chance to do the dispatch,
1821 which load the missing drivers if possible.
1823 @param DevicePathToConnect The device path which will be connected, it can
1824 be a multi-instance device path
1826 @retval EFI_SUCCESS All handles associate with every device path
1827 node have been created
1828 @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles
1829 @retval EFI_NOT_FOUND Create the handle associate with one device
1836 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePathToConnect
1840 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1841 EFI_DEVICE_PATH_PROTOCOL
*CopyOfDevicePath
;
1842 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
1843 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
1844 EFI_DEVICE_PATH_PROTOCOL
*Next
;
1846 EFI_HANDLE PreviousHandle
;
1849 if (DevicePathToConnect
== NULL
) {
1853 DevicePath
= DuplicateDevicePath (DevicePathToConnect
);
1854 CopyOfDevicePath
= DevicePath
;
1855 if (DevicePath
== NULL
) {
1856 return EFI_OUT_OF_RESOURCES
;
1861 // The outer loop handles multi instance device paths.
1862 // Only console variables contain multiple instance device paths.
1864 // After this call DevicePath points to the next Instance
1866 Instance
= GetNextDevicePathInstance (&DevicePath
, &Size
);
1868 while (!IsDevicePathEndType (Next
)) {
1869 Next
= NextDevicePathNode (Next
);
1872 SetDevicePathEndNode (Next
);
1875 // Start the real work of connect with RemainingDevicePath
1877 PreviousHandle
= NULL
;
1880 // Find the handle that best matches the Device Path. If it is only a
1881 // partial match the remaining part of the device path is returned in
1882 // RemainingDevicePath.
1884 RemainingDevicePath
= Instance
;
1885 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingDevicePath
, &Handle
);
1887 if (!EFI_ERROR (Status
)) {
1888 if (Handle
== PreviousHandle
) {
1890 // If no forward progress is made try invoking the Dispatcher.
1891 // A new FV may have been added to the system an new drivers
1892 // may now be found.
1893 // Status == EFI_SUCCESS means a driver was dispatched
1894 // Status == EFI_NOT_FOUND means no new drivers were dispatched
1896 Status
= gDS
->Dispatch ();
1899 if (!EFI_ERROR (Status
)) {
1900 PreviousHandle
= Handle
;
1902 // Connect all drivers that apply to Handle and RemainingDevicePath,
1903 // the Recursive flag is FALSE so only one level will be expanded.
1905 // Do not check the connect status here, if the connect controller fail,
1906 // then still give the chance to do dispatch, because partial
1907 // RemainingDevicepath may be in the new FV
1909 // 1. If the connect fails, RemainingDevicepath and handle will not
1910 // change, so next time will do the dispatch, then dispatch's status
1912 // 2. If the connect succeeds, the RemainingDevicepath and handle will
1913 // change, then avoid the dispatch, we have chance to continue the
1916 gBS
->ConnectController (Handle
, NULL
, RemainingDevicePath
, FALSE
);
1920 // Loop until RemainingDevicePath is an empty device path
1922 } while (!EFI_ERROR (Status
) && !IsDevicePathEnd (RemainingDevicePath
));
1924 } while (DevicePath
!= NULL
);
1926 if (CopyOfDevicePath
!= NULL
) {
1927 FreePool (CopyOfDevicePath
);
1930 // All handle with DevicePath exists in the handle database