2 Implementation of the shared functions to do the platform driver vverride mapping.
4 Copyright (c) 2007 - 2015, 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
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 "InternalPlatDriOverrideDxe.h"
17 #define PLATFORM_OVERRIDE_ITEM_SIGNATURE SIGNATURE_32('p','d','o','i')
18 typedef struct _PLATFORM_OVERRIDE_ITEM
{
22 EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
;
24 /// List of DRIVER_IMAGE_INFO
26 LIST_ENTRY DriverInfoList
;
27 EFI_HANDLE LastReturnedImageHandle
;
28 } PLATFORM_OVERRIDE_ITEM
;
30 #define DRIVER_IMAGE_INFO_SIGNATURE SIGNATURE_32('p','d','i','i')
31 typedef struct _DRIVER_IMAGE_INFO
{
34 EFI_HANDLE ImageHandle
;
35 EFI_DEVICE_PATH_PROTOCOL
*DriverImagePath
;
40 #define DEVICE_PATH_STACK_ITEM_SIGNATURE SIGNATURE_32('d','p','s','i')
41 typedef struct _DEVICE_PATH_STACK_ITEM
{
44 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
45 } DEVICE_PATH_STACK_ITEM
;
48 LIST_ENTRY mDevicePathStack
= INITIALIZE_LIST_HEAD_VARIABLE (mDevicePathStack
);
51 Push a controller device path into a globle device path list.
53 @param DevicePath The controller device path to push into stack
55 @retval EFI_SUCCESS Device path successfully pushed into the stack.
61 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
64 DEVICE_PATH_STACK_ITEM
*DevicePathStackItem
;
66 DevicePathStackItem
= AllocateZeroPool (sizeof (DEVICE_PATH_STACK_ITEM
));
67 ASSERT (DevicePathStackItem
!= NULL
);
68 DevicePathStackItem
->Signature
= DEVICE_PATH_STACK_ITEM_SIGNATURE
;
69 DevicePathStackItem
->DevicePath
= DuplicateDevicePath (DevicePath
);
70 InsertTailList (&mDevicePathStack
, &DevicePathStackItem
->Link
);
76 Pop a controller device path from a globle device path list
78 @param DevicePath The controller device path popped from stack
80 @retval EFI_SUCCESS Controller device path successfully popped.
81 @retval EFI_NOT_FOUND Stack is empty.
87 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
90 DEVICE_PATH_STACK_ITEM
*DevicePathStackItem
;
91 LIST_ENTRY
*ItemListIndex
;
93 ItemListIndex
= mDevicePathStack
.BackLink
;
95 // Check if the stack is empty
97 if (ItemListIndex
!= &mDevicePathStack
){
98 DevicePathStackItem
= CR(ItemListIndex
, DEVICE_PATH_STACK_ITEM
, Link
, DEVICE_PATH_STACK_ITEM_SIGNATURE
);
99 if (DevicePath
!= NULL
) {
100 *DevicePath
= DuplicateDevicePath (DevicePathStackItem
->DevicePath
);
102 FreePool (DevicePathStackItem
->DevicePath
);
103 RemoveEntryList (&DevicePathStackItem
->Link
);
104 FreePool (DevicePathStackItem
);
107 return EFI_NOT_FOUND
;
112 Check whether a controller device path is in a globle device path list
114 @param DevicePath The controller device path to check
116 @retval TRUE DevicePath exists in the stack.
117 @retval FALSE DevicePath does not exist in the stack.
123 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
126 DEVICE_PATH_STACK_ITEM
*DevicePathStackItem
;
127 LIST_ENTRY
*ItemListIndex
;
128 UINTN DevicePathSize
;
130 ItemListIndex
= mDevicePathStack
.BackLink
;
131 while (ItemListIndex
!= &mDevicePathStack
){
132 DevicePathStackItem
= CR(ItemListIndex
, DEVICE_PATH_STACK_ITEM
, Link
, DEVICE_PATH_STACK_ITEM_SIGNATURE
);
133 DevicePathSize
= GetDevicePathSize (DevicePath
);
134 if (DevicePathSize
== GetDevicePathSize (DevicePathStackItem
->DevicePath
)) {
135 if (CompareMem (DevicePath
, DevicePathStackItem
->DevicePath
, DevicePathSize
) == 0) {
139 ItemListIndex
= ItemListIndex
->BackLink
;
146 Update the FV file device path if it is not valid.
148 According to a file GUID, check a Fv file device path is valid. If it is invalid,
149 try to return the valid device path.
150 FV address maybe changes for memory layout adjust from time to time, use this funciton
151 could promise the Fv file device path is right.
153 @param DevicePath On input, the FV file device path to check
154 On output, the updated valid FV file device path
155 @param FileGuid The FV file GUID
156 @param CallerImageHandle Image handle of the caller
158 @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid
160 @retval EFI_UNSUPPORTED the input DevicePath does not contain FV file
162 @retval EFI_ALREADY_STARTED the input DevicePath has pointed to FV file, it
164 @retval EFI_SUCCESS Successfully updated the invalid DevicePath,
165 and return the updated device path in DevicePath
170 UpdateFvFileDevicePath (
171 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
172 IN EFI_GUID
*FileGuid
,
173 IN EFI_HANDLE CallerImageHandle
176 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
177 EFI_DEVICE_PATH_PROTOCOL
*LastDeviceNode
;
182 EFI_HANDLE
*FvHandleBuffer
;
183 EFI_FV_FILETYPE Type
;
185 EFI_FV_FILE_ATTRIBUTES Attributes
;
186 UINT32 AuthenticationStatus
;
188 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
189 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
190 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode
;
191 EFI_HANDLE FoundFvHandle
;
192 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
195 if (DevicePath
== NULL
) {
196 return EFI_INVALID_PARAMETER
;
199 if (*DevicePath
== NULL
) {
200 return EFI_INVALID_PARAMETER
;
204 // Check whether the device path points to the default the input FV file
206 TempDevicePath
= *DevicePath
;
207 LastDeviceNode
= TempDevicePath
;
208 while (!IsDevicePathEnd (TempDevicePath
)) {
209 LastDeviceNode
= TempDevicePath
;
210 TempDevicePath
= NextDevicePathNode (TempDevicePath
);
212 GuidPoint
= EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) LastDeviceNode
);
213 if (GuidPoint
== NULL
) {
215 // If this option does not point to a FV file, just return EFI_UNSUPPORTED.
217 return EFI_UNSUPPORTED
;
220 if (FileGuid
!= NULL
) {
221 if (!CompareGuid (GuidPoint
, FileGuid
)) {
223 // If the FV file is not the input file GUID, just return EFI_UNSUPPORTED
225 return EFI_UNSUPPORTED
;
228 FileGuid
= GuidPoint
;
232 // Check to see if the device path contains memory map node
234 TempDevicePath
= *DevicePath
;
236 while (!IsDevicePathEnd (TempDevicePath
)) {
238 // Use old Device Path
240 if (DevicePathType (TempDevicePath
) == HARDWARE_DEVICE_PATH
&&
241 DevicePathSubType (TempDevicePath
) == HW_MEMMAP_DP
) {
245 TempDevicePath
= NextDevicePathNode (TempDevicePath
);
249 return EFI_UNSUPPORTED
;
253 // Check whether the input Fv file device path is valid
255 TempDevicePath
= *DevicePath
;
256 FoundFvHandle
= NULL
;
257 Status
= gBS
->LocateDevicePath (
258 &gEfiFirmwareVolume2ProtocolGuid
,
262 if (!EFI_ERROR (Status
)) {
263 Status
= gBS
->HandleProtocol (
265 &gEfiFirmwareVolume2ProtocolGuid
,
268 if (!EFI_ERROR (Status
)) {
270 // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there
272 Status
= Fv
->ReadFile (
279 &AuthenticationStatus
281 if (!EFI_ERROR (Status
)) {
282 return EFI_ALREADY_STARTED
;
288 // Look for the input wanted FV file in current FV
289 // First, try to look for in Caller own FV. Caller and input wanted FV file usually are in the same FV
292 FoundFvHandle
= NULL
;
293 Status
= gBS
->HandleProtocol (
295 &gEfiLoadedImageProtocolGuid
,
296 (VOID
**) &LoadedImage
298 if (!EFI_ERROR (Status
)) {
299 Status
= gBS
->HandleProtocol (
300 LoadedImage
->DeviceHandle
,
301 &gEfiFirmwareVolume2ProtocolGuid
,
304 if (!EFI_ERROR (Status
)) {
305 Status
= Fv
->ReadFile (
312 &AuthenticationStatus
314 if (!EFI_ERROR (Status
)) {
316 FoundFvHandle
= LoadedImage
->DeviceHandle
;
321 // Second, if fail to find, try to enumerate all FV
324 gBS
->LocateHandleBuffer (
326 &gEfiFirmwareVolume2ProtocolGuid
,
331 for (Index
= 0; Index
< FvHandleCount
; Index
++) {
332 gBS
->HandleProtocol (
333 FvHandleBuffer
[Index
],
334 &gEfiFirmwareVolume2ProtocolGuid
,
338 Status
= Fv
->ReadFile (
345 &AuthenticationStatus
347 if (EFI_ERROR (Status
)) {
349 // Skip if input Fv file not in the FV
354 FoundFvHandle
= FvHandleBuffer
[Index
];
361 // Build the shell device path
363 NewDevicePath
= DevicePathFromHandle (FoundFvHandle
);
364 EfiInitializeFwVolDevicepathNode (&FvFileNode
, FileGuid
);
365 NewDevicePath
= AppendDevicePathNode (NewDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) &FvFileNode
);
366 *DevicePath
= NewDevicePath
;
369 return EFI_NOT_FOUND
;
373 Gets the data and size of a variable.
375 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
376 buffer, and the size of the buffer. If failure return NULL.
378 @param Name String part of EFI variable name
379 @param VendorGuid GUID part of EFI variable name
380 @param VariableSize Returns the size of the EFI variable that was
383 @return Dynamically allocated memory that contains a copy of the EFI variable.
384 Caller is responsible freeing the buffer.
385 @retval NULL Variable was not read
392 IN EFI_GUID
*VendorGuid
,
393 OUT UINTN
*VariableSize
403 // Pass in a zero size buffer to find the required buffer size.
406 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
407 if (Status
== EFI_BUFFER_TOO_SMALL
) {
409 // Allocate the buffer to return
411 Buffer
= AllocateZeroPool (BufferSize
);
412 if (Buffer
== NULL
) {
416 // Read variable into the allocated buffer.
418 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
419 if (EFI_ERROR (Status
)) {
424 *VariableSize
= BufferSize
;
429 Connect to the handle to a device on the device path.
431 This function will create all handles associate with every device
432 path node. If the handle associate with one device path node can not
433 be created success, then still give one chance to do the dispatch,
434 which load the missing drivers if possible.
436 @param DevicePathToConnect The device path which will be connected, it can
437 be a multi-instance device path
439 @retval EFI_SUCCESS All handles associate with every device path
440 node have been created
441 @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles
442 @retval EFI_NOT_FOUND Create the handle associate with one device
449 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePathToConnect
453 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
454 EFI_DEVICE_PATH_PROTOCOL
*CopyOfDevicePath
;
455 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
456 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
457 EFI_DEVICE_PATH_PROTOCOL
*Next
;
459 EFI_HANDLE PreviousHandle
;
462 if (DevicePathToConnect
== NULL
) {
466 DevicePath
= DuplicateDevicePath (DevicePathToConnect
);
467 CopyOfDevicePath
= DevicePath
;
468 if (DevicePath
== NULL
) {
469 return EFI_OUT_OF_RESOURCES
;
474 // The outer loop handles multi instance device paths.
475 // Only console variables contain multiple instance device paths.
477 // After this call DevicePath points to the next Instance
479 Instance
= GetNextDevicePathInstance (&DevicePath
, &Size
);
480 ASSERT (Instance
!= NULL
);
483 while (!IsDevicePathEndType (Next
)) {
484 Next
= NextDevicePathNode (Next
);
487 SetDevicePathEndNode (Next
);
490 // Start the real work of connect with RemainingDevicePath
492 PreviousHandle
= NULL
;
495 // Find the handle that best matches the Device Path. If it is only a
496 // partial match the remaining part of the device path is returned in
497 // RemainingDevicePath.
499 RemainingDevicePath
= Instance
;
500 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingDevicePath
, &Handle
);
502 if (!EFI_ERROR (Status
)) {
503 if (Handle
== PreviousHandle
) {
505 // If no forward progress is made try invoking the Dispatcher.
506 // A new FV may have been added to the system an new drivers
508 // Status == EFI_SUCCESS means a driver was dispatched
509 // Status == EFI_NOT_FOUND means no new drivers were dispatched
511 Status
= gDS
->Dispatch ();
514 if (!EFI_ERROR (Status
)) {
515 PreviousHandle
= Handle
;
517 // Connect all drivers that apply to Handle and RemainingDevicePath,
518 // the Recursive flag is FALSE so only one level will be expanded.
520 // Do not check the connect status here, if the connect controller fail,
521 // then still give the chance to do dispatch, because partial
522 // RemainingDevicepath may be in the new FV
524 // 1. If the connect fails, RemainingDevicepath and handle will not
525 // change, so next time will do the dispatch, then dispatch's status
527 // 2. If the connect succeeds, the RemainingDevicepath and handle will
528 // change, then avoid the dispatch, we have chance to continue the
531 gBS
->ConnectController (Handle
, NULL
, RemainingDevicePath
, FALSE
);
535 // Loop until RemainingDevicePath is an empty device path
537 } while (!EFI_ERROR (Status
) && !IsDevicePathEnd (RemainingDevicePath
));
539 } while (DevicePath
!= NULL
);
541 if (CopyOfDevicePath
!= NULL
) {
542 FreePool (CopyOfDevicePath
);
545 // All handle with DevicePath exists in the handle database
551 Free all the mapping database memory resource and initialize the mapping list entry.
553 @param MappingDataBase Mapping database list entry pointer
555 @retval EFI_SUCCESS Mapping database successfully freed
556 @retval EFI_INVALID_PARAMETER MappingDataBase is NULL
561 FreeMappingDatabase (
562 IN OUT LIST_ENTRY
*MappingDataBase
565 LIST_ENTRY
*OverrideItemListIndex
;
566 LIST_ENTRY
*ImageInfoListIndex
;
567 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
568 DRIVER_IMAGE_INFO
*DriverImageInfo
;
570 if (MappingDataBase
== NULL
) {
571 return EFI_INVALID_PARAMETER
;
574 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
575 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
576 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
578 // Free PLATFORM_OVERRIDE_ITEM.ControllerDevicePath[]
580 if (OverrideItem
->ControllerDevicePath
!= NULL
){
581 FreePool (OverrideItem
->ControllerDevicePath
);
584 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
585 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
587 // Free DRIVER_IMAGE_INFO.DriverImagePath[]
589 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
590 if (DriverImageInfo
->DriverImagePath
!= NULL
) {
591 FreePool(DriverImageInfo
->DriverImagePath
);
594 // Free DRIVER_IMAGE_INFO itself
596 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
597 RemoveEntryList (&DriverImageInfo
->Link
);
598 FreePool (DriverImageInfo
);
601 // Free PLATFORM_OVERRIDE_ITEM itself
603 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
604 RemoveEntryList (&OverrideItem
->Link
);
605 FreePool (OverrideItem
);
608 InitializeListHead (MappingDataBase
);
614 Create the mapping database according to variable.
616 Read the environment variable(s) that contain the override mappings from Controller Device Path to
617 a set of Driver Device Paths, and create the mapping database in memory with those variable info.
620 // NotEnd indicate whether the variable is the last one, and has no subsequent variable need to load.
621 // Each variable has MaximumVariableSize limitation, so we maybe need multiple variables to store
622 // large mapping infos.
623 // The variable(s) name rule is PlatDriOver, PlatDriOver1, PlatDriOver2, ....
625 UINT32 NotEnd; //Zero is the last one.
627 // The entry which contains the mapping that Controller Device Path to a set of Driver Device Paths
628 // There are often multi mapping entries in a variable.
630 UINT32 SIGNATURE; //SIGNATURE_32('p','d','o','i')
632 EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[];
633 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
634 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
635 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
637 UINT32 NotEnd; //Zero is the last one.
640 EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[];
641 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
642 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
643 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
647 @param MappingDataBase Mapping database list entry pointer
649 @retval EFI_SUCCESS Create the mapping database in memory successfully
650 @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null
651 @retval EFI_NOT_FOUND Cannot find the 'PlatDriOver' NV variable
652 @retval EFI_VOLUME_CORRUPTED The found NV variable is corrupted
657 InitOverridesMapping (
658 OUT LIST_ENTRY
*MappingDataBase
662 VOID
*VariableBuffer
;
663 UINT8
*VariableIndex
;
665 CHAR16 OverrideVariableName
[40];
668 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
669 DRIVER_IMAGE_INFO
*DriverImageInfo
;
672 EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
;
673 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
676 if (MappingDataBase
== NULL
) {
677 return EFI_INVALID_PARAMETER
;
681 // Check the environment variable(s) that contain the override mappings .
683 VariableBuffer
= GetVariableAndSize (L
"PlatDriOver", &gEfiCallerIdGuid
, &BufferSize
);
684 ASSERT ((UINTN
) VariableBuffer
% sizeof(UINTN
) == 0);
685 if (VariableBuffer
== NULL
) {
686 return EFI_NOT_FOUND
;
690 // Traverse all variables.
696 VariableIndex
= VariableBuffer
;
697 if (VariableIndex
+ sizeof (UINT32
) > (UINT8
*) VariableBuffer
+ BufferSize
) {
703 NotEnd
= *(UINT32
*) VariableIndex
;
706 // Traverse the entries containing the mapping that Controller Device Path
707 // to a set of Driver Device Paths within this variable.
709 VariableIndex
= VariableIndex
+ sizeof (UINT32
);
710 while (VariableIndex
< ((UINT8
*)VariableBuffer
+ BufferSize
)) {
712 // Check signature of this entry
714 if (VariableIndex
+ sizeof (UINT32
) > (UINT8
*) VariableBuffer
+ BufferSize
) {
718 Signature
= *(UINT32
*) VariableIndex
;
719 if (Signature
!= PLATFORM_OVERRIDE_ITEM_SIGNATURE
) {
724 // Create PLATFORM_OVERRIDE_ITEM for this mapping
726 OverrideItem
= AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM
));
727 ASSERT (OverrideItem
!= NULL
);
728 OverrideItem
->Signature
= PLATFORM_OVERRIDE_ITEM_SIGNATURE
;
729 InitializeListHead (&OverrideItem
->DriverInfoList
);
730 VariableIndex
= VariableIndex
+ sizeof (UINT32
);
734 if (VariableIndex
+ sizeof (UINT32
) >= (UINT8
*) VariableBuffer
+ BufferSize
) {
738 DriverNumber
= *(UINT32
*) VariableIndex
;
739 OverrideItem
->DriverInfoNum
= DriverNumber
;
740 VariableIndex
= VariableIndex
+ sizeof (UINT32
);
742 // Get ControllerDevicePath[]
744 ControllerDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) VariableIndex
;
745 OverrideItem
->ControllerDevicePath
= DuplicateDevicePath (ControllerDevicePath
);
746 VariableIndex
= VariableIndex
+ GetDevicePathSize (ControllerDevicePath
);
748 // Align the VariableIndex since the controller device path may not be aligned, refer to the SaveOverridesMapping()
750 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
752 // Check buffer overflow.
754 if ((OverrideItem
->ControllerDevicePath
== NULL
) || (VariableIndex
< (UINT8
*) ControllerDevicePath
) ||
755 (VariableIndex
> (UINT8
*) VariableBuffer
+ BufferSize
)) {
761 // Get all DriverImageDevicePath[]
763 for (Index
= 0; Index
< DriverNumber
; Index
++) {
765 // Create DRIVER_IMAGE_INFO for this DriverDevicePath[]
767 DriverImageInfo
= AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO
));
768 ASSERT (DriverImageInfo
!= NULL
);
769 DriverImageInfo
->Signature
= DRIVER_IMAGE_INFO_SIGNATURE
;
771 DriverDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) VariableIndex
;
772 DriverImageInfo
->DriverImagePath
= DuplicateDevicePath (DriverDevicePath
);
773 VariableIndex
= VariableIndex
+ GetDevicePathSize (DriverDevicePath
);
775 // Align the VariableIndex since the driver image device path may not be aligned, refer to the SaveOverridesMapping()
777 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
779 InsertTailList (&OverrideItem
->DriverInfoList
, &DriverImageInfo
->Link
);
782 // Check buffer overflow
784 if ((DriverImageInfo
->DriverImagePath
== NULL
) || (VariableIndex
< (UINT8
*) DriverDevicePath
) ||
785 (VariableIndex
< (UINT8
*) VariableBuffer
+ BufferSize
)) {
790 InsertTailList (MappingDataBase
, &OverrideItem
->Link
);
796 FreePool (VariableBuffer
);
798 FreeMappingDatabase (MappingDataBase
);
799 return EFI_VOLUME_CORRUPTED
;
803 // If there are additional variables (PlatDriOver1, PlatDriOver2, PlatDriOver3.....), get them.
804 // NotEnd indicates whether current variable is the end variable.
807 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", VariableNum
++);
808 VariableBuffer
= GetVariableAndSize (OverrideVariableName
, &gEfiCallerIdGuid
, &BufferSize
);
809 ASSERT ((UINTN
) VariableBuffer
% sizeof(UINTN
) == 0);
810 if (VariableBuffer
== NULL
) {
811 FreeMappingDatabase (MappingDataBase
);
812 return EFI_VOLUME_CORRUPTED
;
816 } while (NotEnd
!= 0);
823 Calculate the needed size in NV variable for recording a specific PLATFORM_OVERRIDE_ITEM info.
825 @param OverrideItemListIndex Pointer to the list of a specific PLATFORM_OVERRIDE_ITEM
827 @return The needed size number
832 GetOneItemNeededSize (
833 IN LIST_ENTRY
*OverrideItemListIndex
837 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
838 LIST_ENTRY
*ImageInfoListIndex
;
839 DRIVER_IMAGE_INFO
*DriverImageInfo
;
840 UINTN DevicePathSize
;
843 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
844 NeededSize
+= sizeof (UINT32
); //UINT32 SIGNATURE;
845 NeededSize
+= sizeof (UINT32
); //UINT32 DriverNum;
846 DevicePathSize
= GetDevicePathSize (OverrideItem
->ControllerDevicePath
);
847 NeededSize
+= DevicePathSize
; // ControllerDevicePath
849 // Align the controller device path
851 NeededSize
+= ((sizeof(UINT32
) - DevicePathSize
) & (sizeof(UINT32
) - 1));
853 // Traverse the Driver Info List of this Override Item
855 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
856 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
857 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
858 DevicePathSize
= GetDevicePathSize (DriverImageInfo
->DriverImagePath
);
859 NeededSize
+= DevicePathSize
; //DriverDevicePath
861 // Align the driver image device path
863 NeededSize
+= ((sizeof(UINT32
) - DevicePathSize
) & (sizeof(UINT32
) - 1));
864 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
871 Deletes all environment variable(s) that contain the override mappings from Controller Device Path to
872 a set of Driver Device Paths.
874 @retval EFI_SUCCESS Delete all variable(s) successfully.
879 DeleteOverridesVariables (
884 VOID
*VariableBuffer
;
888 CHAR16 OverrideVariableName
[40];
891 // Get environment variable(s) number
894 VariableBuffer
= GetVariableAndSize (L
"PlatDriOver", &gEfiCallerIdGuid
, &BufferSize
);
896 if (VariableBuffer
== NULL
) {
897 return EFI_NOT_FOUND
;
900 // Check NotEnd to get all PlatDriOverX variable(s)
902 while ((VariableBuffer
!= NULL
) && ((*(UINT32
*)VariableBuffer
) != 0)) {
903 FreePool (VariableBuffer
);
904 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", VariableNum
);
905 VariableBuffer
= GetVariableAndSize (OverrideVariableName
, &gEfiCallerIdGuid
, &BufferSize
);
910 // Delete PlatDriOver and all additional variables, if exist.
912 Status
= gRT
->SetVariable (
915 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
919 ASSERT (!EFI_ERROR (Status
));
920 for (Index
= 1; Index
< VariableNum
; Index
++) {
921 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", Index
);
922 Status
= gRT
->SetVariable (
923 OverrideVariableName
,
925 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
929 ASSERT (!EFI_ERROR (Status
));
936 Save the memory mapping database into NV environment variable(s).
938 @param MappingDataBase Mapping database list entry pointer
940 @retval EFI_SUCCESS Save memory mapping database successfully
941 @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null
946 SaveOverridesMapping (
947 IN LIST_ENTRY
*MappingDataBase
951 VOID
*VariableBuffer
;
952 UINT8
*VariableIndex
;
954 CHAR16 OverrideVariableName
[40];
956 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
957 DRIVER_IMAGE_INFO
*DriverImageInfo
;
958 LIST_ENTRY
*OverrideItemListIndex
;
959 LIST_ENTRY
*ItemIndex
;
960 LIST_ENTRY
*ImageInfoListIndex
;
961 UINTN VariableNeededSize
;
962 UINT64 MaximumVariableStorageSize
;
963 UINT64 RemainingVariableStorageSize
;
964 UINT64 MaximumVariableSize
;
965 UINTN OneItemNeededSize
;
967 if (MappingDataBase
== NULL
) {
968 return EFI_INVALID_PARAMETER
;
971 if (IsListEmpty (MappingDataBase
)) {
972 Status
= DeleteOverridesVariables ();
977 // Get the the maximum size of an individual EFI variable in current system
979 gRT
->QueryVariableInfo (
980 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
981 &MaximumVariableStorageSize
,
982 &RemainingVariableStorageSize
,
987 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
988 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
990 // Try to find the most proper variable size which <= MaximumVariableSize,
991 // but can contain mapping info as much as possible
993 VariableNeededSize
= sizeof (UINT32
); // NotEnd;
994 ItemIndex
= OverrideItemListIndex
;
997 // Traverse all PLATFORM_OVERRIDE_ITEMs and get the total size.
999 while (!IsNull (MappingDataBase
, ItemIndex
)) {
1000 OneItemNeededSize
= GetOneItemNeededSize (ItemIndex
);
1002 // If the total size exceeds the MaximumVariableSize, then we must use
1003 // multiple variables.
1005 if ((VariableNeededSize
+
1007 StrSize (L
"PlatDriOver ")
1008 ) >= MaximumVariableSize
1014 VariableNeededSize
+= OneItemNeededSize
;
1015 ItemIndex
= GetNextNode (MappingDataBase
, ItemIndex
);
1019 if (VariableNeededSize
== sizeof (UINT32
)) {
1021 // If an individual EFI variable cannot contain a single Item, return error
1023 return EFI_OUT_OF_RESOURCES
;
1028 // VariableNeededSize is the most proper variable size, allocate variable buffer
1029 // ItemIndex now points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize
1031 VariableBuffer
= AllocateZeroPool (VariableNeededSize
);
1032 ASSERT (VariableBuffer
!= NULL
);
1033 ASSERT ((UINTN
) VariableBuffer
% sizeof(UINTN
) == 0);
1036 // Fill the variable buffer according to MappingDataBase
1038 VariableIndex
= VariableBuffer
;
1039 *(UINT32
*) VariableIndex
= NotEnd
;
1040 VariableIndex
+= sizeof (UINT32
); // pass NotEnd
1042 // ItemIndex points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize
1044 while (OverrideItemListIndex
!= ItemIndex
){
1045 *(UINT32
*) VariableIndex
= PLATFORM_OVERRIDE_ITEM_SIGNATURE
;
1046 VariableIndex
+= sizeof (UINT32
); // pass SIGNATURE
1048 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1049 *(UINT32
*) VariableIndex
= OverrideItem
->DriverInfoNum
;
1050 VariableIndex
+= sizeof (UINT32
); // pass DriverNum
1052 CopyMem (VariableIndex
, OverrideItem
->ControllerDevicePath
, GetDevicePathSize (OverrideItem
->ControllerDevicePath
));
1053 VariableIndex
+= GetDevicePathSize (OverrideItem
->ControllerDevicePath
); // pass ControllerDevicePath
1056 // Align the VariableIndex since the controller device path may not be aligned
1058 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
1060 // Save the Driver Info List of this PLATFORM_OVERRIDE_ITEM
1062 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1063 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1064 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1065 CopyMem (VariableIndex
, DriverImageInfo
->DriverImagePath
, GetDevicePathSize (DriverImageInfo
->DriverImagePath
));
1066 VariableIndex
+= GetDevicePathSize (DriverImageInfo
->DriverImagePath
); // pass DriverImageDevicePath
1068 // Align the VariableIndex since the driver image device path may not be aligned
1070 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
1071 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1074 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1077 ASSERT (((UINTN
)VariableIndex
- (UINTN
)VariableBuffer
) == VariableNeededSize
);
1079 if (NumIndex
== 0) {
1080 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver");
1082 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", NumIndex
);
1085 Status
= gRT
->SetVariable (
1086 OverrideVariableName
,
1088 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1092 FreePool (VariableBuffer
);
1094 if (EFI_ERROR (Status
)) {
1097 // Delete all PlatDriOver variables when full mapping can't be set.
1099 DeleteOverridesVariables ();
1111 Get the first Binding protocol which has the specific image handle.
1113 @param ImageHandle The Image handle
1114 @param BindingHandle The BindingHandle of the found Driver Binding protocol.
1115 If Binding protocol is not found, it is set to NULL.
1117 @return Pointer into the Binding Protocol interface
1118 @retval NULL The paramter is not valid or the binding protocol is not found.
1121 EFI_DRIVER_BINDING_PROTOCOL
*
1123 GetBindingProtocolFromImageHandle (
1124 IN EFI_HANDLE ImageHandle
,
1125 OUT EFI_HANDLE
*BindingHandle
1130 UINTN DriverBindingHandleCount
;
1131 EFI_HANDLE
*DriverBindingHandleBuffer
;
1132 EFI_DRIVER_BINDING_PROTOCOL
*DriverBindingInterface
;
1134 if (BindingHandle
== NULL
|| ImageHandle
== NULL
) {
1138 // Get all drivers which support driver binding protocol
1140 DriverBindingHandleCount
= 0;
1141 Status
= gBS
->LocateHandleBuffer (
1143 &gEfiDriverBindingProtocolGuid
,
1145 &DriverBindingHandleCount
,
1146 &DriverBindingHandleBuffer
1148 if (EFI_ERROR (Status
) || (DriverBindingHandleCount
== 0)) {
1152 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
1153 DriverBindingInterface
= NULL
;
1154 Status
= gBS
->OpenProtocol (
1155 DriverBindingHandleBuffer
[Index
],
1156 &gEfiDriverBindingProtocolGuid
,
1157 (VOID
**) &DriverBindingInterface
,
1160 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1162 if (EFI_ERROR (Status
)) {
1166 if (DriverBindingInterface
->ImageHandle
== ImageHandle
) {
1167 *BindingHandle
= DriverBindingHandleBuffer
[Index
];
1168 FreePool (DriverBindingHandleBuffer
);
1169 return DriverBindingInterface
;
1174 // If no Driver Binding Protocol instance is found
1176 FreePool (DriverBindingHandleBuffer
);
1177 *BindingHandle
= NULL
;
1182 Return the current TPL.
1194 Tpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
1195 gBS
->RestoreTPL (Tpl
);
1202 Retrieves the image handle of the platform override driver for a controller in
1203 the system from the memory mapping database.
1205 @param ControllerHandle The device handle of the controller to check if
1206 a driver override exists.
1207 @param DriverImageHandle On input, the previously returnd driver image handle.
1208 On output, a pointer to the next driver handle.
1209 Passing in a pointer to NULL, will return the
1210 first driver handle for ControllerHandle.
1211 @param MappingDataBase Mapping database list entry pointer
1212 @param CallerImageHandle The caller driver's image handle, for
1213 UpdateFvFileDevicePath use.
1215 @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not
1216 a valid handle. Or DriverImagePath is not a
1217 device path that was returned on a previous call
1219 @retval EFI_NOT_FOUND A driver override for ControllerHandle was not
1221 @retval EFI_UNSUPPORTED The operation is not supported.
1222 @retval EFI_SUCCESS The driver override for ControllerHandle was
1223 returned in DriverImagePath.
1228 GetDriverFromMapping (
1229 IN EFI_HANDLE ControllerHandle
,
1230 IN OUT EFI_HANDLE
*DriverImageHandle
,
1231 IN LIST_ENTRY
*MappingDataBase
,
1232 IN EFI_HANDLE CallerImageHandle
1236 EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
;
1237 BOOLEAN ControllerFound
;
1239 EFI_HANDLE
*ImageHandleBuffer
;
1240 UINTN ImageHandleCount
;
1242 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
1243 EFI_HANDLE DriverBindingHandle
;
1244 BOOLEAN FoundLastReturned
;
1245 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1246 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1247 LIST_ENTRY
*OverrideItemListIndex
;
1248 LIST_ENTRY
*ImageInfoListIndex
;
1249 EFI_DEVICE_PATH_PROTOCOL
*TempDriverImagePath
;
1250 EFI_HANDLE ImageHandle
;
1252 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
1253 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*BusSpecificDriverOverride
;
1254 UINTN DevicePathSize
;
1257 // Check that ControllerHandle is a valid handle
1259 if (ControllerHandle
== NULL
) {
1260 return EFI_INVALID_PARAMETER
;
1263 // Get the device path of ControllerHandle
1265 Status
= gBS
->HandleProtocol (
1267 &gEfiDevicePathProtocolGuid
,
1268 (VOID
**) &ControllerDevicePath
1270 if (EFI_ERROR (Status
) || ControllerDevicePath
== NULL
) {
1271 return EFI_INVALID_PARAMETER
;
1275 // Search ControllerDevicePath in MappingDataBase
1277 OverrideItem
= NULL
;
1278 ControllerFound
= FALSE
;
1279 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1281 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1282 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1283 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1284 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1286 ControllerDevicePath
,
1287 OverrideItem
->ControllerDevicePath
,
1291 ControllerFound
= TRUE
;
1295 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1298 if (!ControllerFound
) {
1299 return EFI_NOT_FOUND
;
1302 // Passing in a pointer to NULL, will return the first driver device path for ControllerHandle.
1303 // Check whether the driverImagePath is not a device path that was returned on a previous call to GetDriverPath().
1305 if (*DriverImageHandle
!= NULL
) {
1306 if (*DriverImageHandle
!= OverrideItem
->LastReturnedImageHandle
) {
1307 return EFI_INVALID_PARAMETER
;
1311 // The GetDriverPath() may be called recursively, because it use ConnectDevicePath() internally,
1312 // so should check whether there is a dead loop.
1313 // Here use a controller device path stack to record all processed controller device path during a GetDriverPath() call,
1314 // and check the controller device path whether appear again during the GetDriverPath() call.
1316 if (CheckExistInStack (OverrideItem
->ControllerDevicePath
)) {
1318 // There is a dependecy dead loop if the ControllerDevicePath appear in stack twice
1320 return EFI_UNSUPPORTED
;
1322 PushDevPathStack (OverrideItem
->ControllerDevicePath
);
1325 // Check every override driver, try to load and start them
1327 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1328 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1329 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1330 if (DriverImageInfo
->ImageHandle
== NULL
) {
1332 // Skip if the image is unloadable or unstartable
1334 if ((!DriverImageInfo
->UnLoadable
) && ((!DriverImageInfo
->UnStartable
))) {
1335 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
1337 // If the image device path contains an FV node, check the FV file device path is valid.
1338 // If it is invalid, try to return the valid device path.
1339 // FV address maybe changes for memory layout adjust from time to time,
1340 // use this funciton could promise the FV file device path is right.
1342 Status
= UpdateFvFileDevicePath (&TempDriverImagePath
, NULL
, CallerImageHandle
);
1343 if (!EFI_ERROR (Status
)) {
1344 FreePool (DriverImageInfo
->DriverImagePath
);
1345 DriverImageInfo
->DriverImagePath
= TempDriverImagePath
;
1348 // Get all Loaded Image protocol to check whether the driver image has been loaded and started
1351 ImageHandleCount
= 0;
1352 Status
= gBS
->LocateHandleBuffer (
1354 &gEfiLoadedImageProtocolGuid
,
1359 if (EFI_ERROR (Status
) || (ImageHandleCount
== 0)) {
1360 return EFI_NOT_FOUND
;
1363 for(Index
= 0; Index
< ImageHandleCount
; Index
++) {
1365 // Get the EFI Loaded Image Device Path Protocol
1367 LoadedImageDevicePath
= NULL
;
1368 Status
= gBS
->HandleProtocol (
1369 ImageHandleBuffer
[Index
],
1370 &gEfiLoadedImageDevicePathProtocolGuid
,
1371 (VOID
**) &LoadedImageDevicePath
1373 if (EFI_ERROR (Status
)) {
1375 // Maybe not all EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL existed.
1380 DevicePathSize
= GetDevicePathSize (DriverImageInfo
->DriverImagePath
);
1381 if (DevicePathSize
== GetDevicePathSize (LoadedImageDevicePath
)) {
1383 DriverImageInfo
->DriverImagePath
,
1384 LoadedImageDevicePath
,
1385 GetDevicePathSize (LoadedImageDevicePath
)
1396 // Find its related driver binding protocol
1397 // Driver binding handle may be different with its driver's Image Handle.
1399 DriverBindingHandle
= NULL
;
1400 DriverBinding
= GetBindingProtocolFromImageHandle (
1401 ImageHandleBuffer
[Index
],
1402 &DriverBindingHandle
1404 ASSERT (DriverBinding
!= NULL
);
1405 DriverImageInfo
->ImageHandle
= ImageHandleBuffer
[Index
];
1406 } else if (GetCurrentTpl() <= TPL_CALLBACK
){
1408 // The driver image has not been loaded and started. Try to load and start it now.
1409 // Try to connect all device in the driver image path.
1411 // Note: LoadImage() and StartImage() should be called under CALLBACK TPL in theory, but
1412 // since many device need to be connected in CALLBACK level environment( e.g. Usb devices )
1413 // and the Fat and Patition driver can endure executing in CALLBACK level in fact, so here permit
1414 // to use LoadImage() and StartImage() in CALLBACK TPL.
1416 Status
= ConnectDevicePath (DriverImageInfo
->DriverImagePath
);
1418 // check whether it points to a PCI Option Rom image,
1419 // and try to use bus override protocol to get its first option rom image driver
1421 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
1422 gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &TempDriverImagePath
, &Handle
);
1424 // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
1426 Status
= gBS
->HandleProtocol(
1428 &gEfiBusSpecificDriverOverrideProtocolGuid
,
1429 (VOID
**) &BusSpecificDriverOverride
1431 if (!EFI_ERROR (Status
) && (BusSpecificDriverOverride
!= NULL
)) {
1433 Status
= BusSpecificDriverOverride
->GetDriver (
1434 BusSpecificDriverOverride
,
1437 if (!EFI_ERROR (Status
)) {
1439 // Find its related driver binding protocol
1440 // Driver binding handle may be different with its driver's Image handle
1442 DriverBindingHandle
= NULL
;
1443 DriverBinding
= GetBindingProtocolFromImageHandle (
1445 &DriverBindingHandle
1447 ASSERT (DriverBinding
!= NULL
);
1448 DriverImageInfo
->ImageHandle
= ImageHandle
;
1452 // Skip if any device cannot be connected now, future passes through GetDriver() may be able to load that driver.
1453 // Only file path media or FwVol Device Path Node remain if all device is connected
1455 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
1456 gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &TempDriverImagePath
, &Handle
);
1457 if (((DevicePathType (TempDriverImagePath
) == MEDIA_DEVICE_PATH
) &&
1458 (DevicePathSubType (TempDriverImagePath
) == MEDIA_FILEPATH_DP
)) ||
1459 (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempDriverImagePath
) != NULL
)
1462 // Try to load the driver
1464 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
1465 Status
= gBS
->LoadImage (
1468 TempDriverImagePath
,
1473 if (!EFI_ERROR (Status
)) {
1475 // Try to start the driver
1477 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
1478 if (EFI_ERROR (Status
)){
1479 DriverImageInfo
->UnStartable
= TRUE
;
1480 DriverImageInfo
->ImageHandle
= NULL
;
1483 // Find its related driver binding protocol
1484 // Driver binding handle may be different with its driver's Image handle
1486 DriverBindingHandle
= NULL
;
1487 DriverBinding
= GetBindingProtocolFromImageHandle (
1489 &DriverBindingHandle
1491 ASSERT (DriverBinding
!= NULL
);
1492 DriverImageInfo
->ImageHandle
= ImageHandle
;
1495 DriverImageInfo
->UnLoadable
= TRUE
;
1496 DriverImageInfo
->ImageHandle
= NULL
;
1500 FreePool (ImageHandleBuffer
);
1503 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1506 // Finish try to load and start the override driver of a controller, popup the controller's device path
1508 PopDevPathStack (NULL
);
1511 // return the DriverImageHandle for ControllerHandle
1513 FoundLastReturned
= FALSE
;
1514 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1515 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1516 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1517 if (DriverImageInfo
->ImageHandle
!= NULL
) {
1518 if ((*DriverImageHandle
== NULL
) || FoundLastReturned
) {
1520 // If DriverImageHandle is NULL, then we just need to return the first driver.
1521 // If FoundLastReturned, this means we have just encountered the previously returned driver.
1522 // For both cases, we just return the image handle of this driver.
1524 OverrideItem
->LastReturnedImageHandle
= DriverImageInfo
->ImageHandle
;
1525 *DriverImageHandle
= DriverImageInfo
->ImageHandle
;
1527 } else if (*DriverImageHandle
== DriverImageInfo
->ImageHandle
){
1529 // We have found the previously returned driver.
1531 FoundLastReturned
= TRUE
;
1534 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1537 return EFI_NOT_FOUND
;
1542 Check mapping database whether already has the mapping info which
1543 records the input Controller to input DriverImage.
1545 @param ControllerDevicePath The controller device path is to be check.
1546 @param DriverImageDevicePath The driver image device path is to be check.
1547 @param MappingDataBase Mapping database list entry pointer
1548 @param DriverInfoNum the controller's total override driver number
1549 @param DriverImageNO The driver order number for the input DriverImage.
1550 If the DriverImageDevicePath is NULL, DriverImageNO is not set.
1552 @retval EFI_INVALID_PARAMETER ControllerDevicePath or MappingDataBase is NULL.
1553 @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or
1554 DriverImageDevicePath is not found in the found DriverImage Info list.
1555 @retval EFI_SUCCESS The controller's total override driver number and
1556 input DriverImage's order number is correctly return.
1561 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
1562 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath OPTIONAL
,
1563 IN LIST_ENTRY
*MappingDataBase
,
1564 OUT UINT32
*DriverInfoNum OPTIONAL
,
1565 OUT UINT32
*DriverImageNO OPTIONAL
1568 LIST_ENTRY
*OverrideItemListIndex
;
1569 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1570 LIST_ENTRY
*ImageInfoListIndex
;
1571 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1574 UINTN DevicePathSize
;
1576 if (ControllerDevicePath
== NULL
) {
1577 return EFI_INVALID_PARAMETER
;
1579 if (MappingDataBase
== NULL
) {
1580 return EFI_INVALID_PARAMETER
;
1584 // Search ControllerDevicePath in MappingDataBase
1587 OverrideItem
= NULL
;
1588 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1589 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1590 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1591 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1592 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1594 ControllerDevicePath
,
1595 OverrideItem
->ControllerDevicePath
,
1603 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1608 // ControllerDevicePath is not in MappingDataBase
1610 return EFI_NOT_FOUND
;
1613 ASSERT (OverrideItem
->DriverInfoNum
!= 0);
1614 if (DriverInfoNum
!= NULL
) {
1615 *DriverInfoNum
= OverrideItem
->DriverInfoNum
;
1619 // If DriverImageDevicePath is NULL, skip checking DriverImageDevicePath
1620 // in the controller's Driver Image Info List
1622 if (DriverImageDevicePath
== NULL
) {
1626 // return the DriverImageHandle for ControllerHandle
1630 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1631 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1632 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1634 DevicePathSize
= GetDevicePathSize (DriverImageDevicePath
);
1635 if (DevicePathSize
== GetDevicePathSize (DriverImageInfo
->DriverImagePath
)) {
1637 DriverImageDevicePath
,
1638 DriverImageInfo
->DriverImagePath
,
1639 GetDevicePathSize (DriverImageInfo
->DriverImagePath
)
1646 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1651 // DriverImageDevicePath is not found in the controller's Driver Image Info List
1653 return EFI_NOT_FOUND
;
1655 if (DriverImageNO
!= NULL
) {
1656 *DriverImageNO
= ImageNO
;
1664 Insert a driver image as a controller's override driver into the mapping database.
1665 The driver image's order number is indicated by DriverImageNO.
1667 @param ControllerDevicePath The controller device path need to add a
1668 override driver image item
1669 @param DriverImageDevicePath The driver image device path need to be insert
1670 @param MappingDataBase Mapping database list entry pointer
1671 @param DriverImageNO The inserted order number. If this number is taken,
1672 the larger available number will be used.
1674 @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or DriverImageDevicePath is NULL
1675 or MappingDataBase is NULL
1676 @retval EFI_ALREADY_STARTED The input Controller to input DriverImage has been
1677 recorded into the mapping database.
1678 @retval EFI_SUCCESS The Controller and DriverImage are inserted into
1679 the mapping database successfully.
1685 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
1686 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath
,
1687 IN LIST_ENTRY
*MappingDataBase
,
1688 IN UINT32 DriverImageNO
1692 LIST_ENTRY
*OverrideItemListIndex
;
1693 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1694 LIST_ENTRY
*ImageInfoListIndex
;
1695 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1698 UINTN DevicePathSize
;
1700 if (ControllerDevicePath
== NULL
) {
1701 return EFI_INVALID_PARAMETER
;
1703 if (DriverImageDevicePath
== NULL
) {
1704 return EFI_INVALID_PARAMETER
;
1706 if (MappingDataBase
== NULL
) {
1707 return EFI_INVALID_PARAMETER
;
1711 // If the driver is already in the controller's Driver Image Info List,
1712 // just return EFI_ALREADY_STARTED.
1714 Status
= CheckMapping (
1715 ControllerDevicePath
,
1716 DriverImageDevicePath
,
1721 if (Status
== EFI_SUCCESS
) {
1722 return EFI_ALREADY_STARTED
;
1726 // Search the input ControllerDevicePath in MappingDataBase
1729 OverrideItem
= NULL
;
1730 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1731 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1732 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1733 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1734 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1736 ControllerDevicePath
,
1737 OverrideItem
->ControllerDevicePath
,
1745 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1748 // If cannot find, this is a new controller item
1749 // Add the Controller related PLATFORM_OVERRIDE_ITEM structrue in mapping data base
1752 OverrideItem
= AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM
));
1753 ASSERT (OverrideItem
!= NULL
);
1754 OverrideItem
->Signature
= PLATFORM_OVERRIDE_ITEM_SIGNATURE
;
1755 OverrideItem
->ControllerDevicePath
= DuplicateDevicePath (ControllerDevicePath
);
1756 InitializeListHead (&OverrideItem
->DriverInfoList
);
1757 InsertTailList (MappingDataBase
, &OverrideItem
->Link
);
1761 // Prepare the driver image related DRIVER_IMAGE_INFO structure.
1763 DriverImageInfo
= AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO
));
1764 ASSERT (DriverImageInfo
!= NULL
);
1765 DriverImageInfo
->Signature
= DRIVER_IMAGE_INFO_SIGNATURE
;
1766 DriverImageInfo
->DriverImagePath
= DuplicateDevicePath (DriverImageDevicePath
);
1768 // Find the driver image wanted order location
1772 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1773 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1774 if (ImageNO
== (DriverImageNO
- 1)) {
1776 // find the wanted order location, insert it
1778 InsertTailList (ImageInfoListIndex
, &DriverImageInfo
->Link
);
1779 OverrideItem
->DriverInfoNum
++;
1784 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1789 // if not find the wanted order location, add it as last item of the controller mapping item
1791 InsertTailList (&OverrideItem
->DriverInfoList
, &DriverImageInfo
->Link
);
1792 OverrideItem
->DriverInfoNum
++;
1800 Delete a controller's override driver from the mapping database.
1802 @param ControllerDevicePath The controller device path will be deleted
1803 when all drivers images on it are removed.
1804 @param DriverImageDevicePath The driver image device path will be delete.
1805 If NULL, all driver image will be delete.
1806 @param MappingDataBase Mapping database list entry pointer
1808 @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or MappingDataBase is NULL
1809 @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or
1810 DriverImageDevicePath is not found in the found DriverImage Info list.
1811 @retval EFI_SUCCESS Delete the specified driver successfully.
1817 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
1818 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath
,
1819 IN LIST_ENTRY
*MappingDataBase
1823 LIST_ENTRY
*OverrideItemListIndex
;
1824 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1825 LIST_ENTRY
*ImageInfoListIndex
;
1826 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1828 UINTN DevicePathSize
;
1830 if (ControllerDevicePath
== NULL
) {
1831 return EFI_INVALID_PARAMETER
;
1834 if (MappingDataBase
== NULL
) {
1835 return EFI_INVALID_PARAMETER
;
1839 // If ControllerDevicePath is not found in mapping database, return EFI_NOT_FOUND.
1841 Status
= CheckMapping (
1842 ControllerDevicePath
,
1843 DriverImageDevicePath
,
1848 if (EFI_ERROR (Status
)) {
1849 return EFI_NOT_FOUND
;
1853 // Search ControllerDevicePath in MappingDataBase
1856 OverrideItem
= NULL
;
1857 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1858 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1859 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1860 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1861 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1863 ControllerDevicePath
,
1864 OverrideItem
->ControllerDevicePath
,
1872 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1876 ASSERT (OverrideItem
->DriverInfoNum
!= 0);
1879 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1880 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1881 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1882 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1883 if (DriverImageDevicePath
!= NULL
) {
1885 // Search for the specified DriverImageDevicePath and remove it, then break.
1887 DevicePathSize
= GetDevicePathSize (DriverImageDevicePath
);
1888 if (DevicePathSize
== GetDevicePathSize (DriverImageInfo
->DriverImagePath
)) {
1890 DriverImageDevicePath
,
1891 DriverImageInfo
->DriverImagePath
,
1892 GetDevicePathSize (DriverImageInfo
->DriverImagePath
)
1896 FreePool(DriverImageInfo
->DriverImagePath
);
1897 RemoveEntryList (&DriverImageInfo
->Link
);
1898 OverrideItem
->DriverInfoNum
--;
1904 // Remove all existing driver image info entries, so no break here.
1907 FreePool(DriverImageInfo
->DriverImagePath
);
1908 RemoveEntryList (&DriverImageInfo
->Link
);
1909 OverrideItem
->DriverInfoNum
--;
1914 // Confirm all driver image info entries have been removed,
1915 // if DriverImageDevicePath is NULL.
1917 if (DriverImageDevicePath
== NULL
) {
1918 ASSERT (OverrideItem
->DriverInfoNum
== 0);
1921 // If Override Item has no driver image info entry, then delete this item.
1923 if (OverrideItem
->DriverInfoNum
== 0) {
1924 FreePool(OverrideItem
->ControllerDevicePath
);
1925 RemoveEntryList (&OverrideItem
->Link
);
1926 FreePool (OverrideItem
);
1931 // DriverImageDevicePath is not NULL and cannot be found in the controller's
1932 // driver image info list.
1934 return EFI_NOT_FOUND
;