2 Implementation of the shared functions to do the platform driver vverride mapping.
4 Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "InternalPlatDriOverrideDxe.h"
11 #define PLATFORM_OVERRIDE_ITEM_SIGNATURE SIGNATURE_32('p','d','o','i')
12 typedef struct _PLATFORM_OVERRIDE_ITEM
{
16 EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
;
18 /// List of DRIVER_IMAGE_INFO
20 LIST_ENTRY DriverInfoList
;
21 EFI_HANDLE LastReturnedImageHandle
;
22 } PLATFORM_OVERRIDE_ITEM
;
24 #define DRIVER_IMAGE_INFO_SIGNATURE SIGNATURE_32('p','d','i','i')
25 typedef struct _DRIVER_IMAGE_INFO
{
28 EFI_HANDLE ImageHandle
;
29 EFI_DEVICE_PATH_PROTOCOL
*DriverImagePath
;
34 #define DEVICE_PATH_STACK_ITEM_SIGNATURE SIGNATURE_32('d','p','s','i')
35 typedef struct _DEVICE_PATH_STACK_ITEM
{
38 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
39 } DEVICE_PATH_STACK_ITEM
;
42 LIST_ENTRY mDevicePathStack
= INITIALIZE_LIST_HEAD_VARIABLE (mDevicePathStack
);
45 Push a controller device path into a globle device path list.
47 @param DevicePath The controller device path to push into stack
49 @retval EFI_SUCCESS Device path successfully pushed into the stack.
55 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
58 DEVICE_PATH_STACK_ITEM
*DevicePathStackItem
;
60 DevicePathStackItem
= AllocateZeroPool (sizeof (DEVICE_PATH_STACK_ITEM
));
61 ASSERT (DevicePathStackItem
!= NULL
);
62 DevicePathStackItem
->Signature
= DEVICE_PATH_STACK_ITEM_SIGNATURE
;
63 DevicePathStackItem
->DevicePath
= DuplicateDevicePath (DevicePath
);
64 InsertTailList (&mDevicePathStack
, &DevicePathStackItem
->Link
);
70 Pop a controller device path from a globle device path list
72 @param DevicePath The controller device path popped from stack
74 @retval EFI_SUCCESS Controller device path successfully popped.
75 @retval EFI_NOT_FOUND Stack is empty.
81 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
84 DEVICE_PATH_STACK_ITEM
*DevicePathStackItem
;
85 LIST_ENTRY
*ItemListIndex
;
87 ItemListIndex
= mDevicePathStack
.BackLink
;
89 // Check if the stack is empty
91 if (ItemListIndex
!= &mDevicePathStack
){
92 DevicePathStackItem
= CR(ItemListIndex
, DEVICE_PATH_STACK_ITEM
, Link
, DEVICE_PATH_STACK_ITEM_SIGNATURE
);
93 if (DevicePath
!= NULL
) {
94 *DevicePath
= DuplicateDevicePath (DevicePathStackItem
->DevicePath
);
96 FreePool (DevicePathStackItem
->DevicePath
);
97 RemoveEntryList (&DevicePathStackItem
->Link
);
98 FreePool (DevicePathStackItem
);
101 return EFI_NOT_FOUND
;
106 Check whether a controller device path is in a globle device path list
108 @param DevicePath The controller device path to check
110 @retval TRUE DevicePath exists in the stack.
111 @retval FALSE DevicePath does not exist in the stack.
117 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
120 DEVICE_PATH_STACK_ITEM
*DevicePathStackItem
;
121 LIST_ENTRY
*ItemListIndex
;
122 UINTN DevicePathSize
;
124 ItemListIndex
= mDevicePathStack
.BackLink
;
125 while (ItemListIndex
!= &mDevicePathStack
){
126 DevicePathStackItem
= CR(ItemListIndex
, DEVICE_PATH_STACK_ITEM
, Link
, DEVICE_PATH_STACK_ITEM_SIGNATURE
);
127 DevicePathSize
= GetDevicePathSize (DevicePath
);
128 if (DevicePathSize
== GetDevicePathSize (DevicePathStackItem
->DevicePath
)) {
129 if (CompareMem (DevicePath
, DevicePathStackItem
->DevicePath
, DevicePathSize
) == 0) {
133 ItemListIndex
= ItemListIndex
->BackLink
;
140 Update the FV file device path if it is not valid.
142 According to a file GUID, check a Fv file device path is valid. If it is invalid,
143 try to return the valid device path.
144 FV address maybe changes for memory layout adjust from time to time, use this function
145 could promise the Fv file device path is right.
147 @param DevicePath On input, the FV file device path to check
148 On output, the updated valid FV file device path
149 @param FileGuid The FV file GUID
150 @param CallerImageHandle Image handle of the caller
152 @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid
154 @retval EFI_UNSUPPORTED the input DevicePath does not contain FV file
156 @retval EFI_ALREADY_STARTED the input DevicePath has pointed to FV file, it
158 @retval EFI_SUCCESS Successfully updated the invalid DevicePath,
159 and return the updated device path in DevicePath
164 UpdateFvFileDevicePath (
165 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
166 IN EFI_GUID
*FileGuid
,
167 IN EFI_HANDLE CallerImageHandle
170 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
171 EFI_DEVICE_PATH_PROTOCOL
*LastDeviceNode
;
176 EFI_HANDLE
*FvHandleBuffer
;
177 EFI_FV_FILETYPE Type
;
179 EFI_FV_FILE_ATTRIBUTES Attributes
;
180 UINT32 AuthenticationStatus
;
182 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
183 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
184 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode
;
185 EFI_HANDLE FoundFvHandle
;
186 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
189 if (DevicePath
== NULL
) {
190 return EFI_INVALID_PARAMETER
;
193 if (*DevicePath
== NULL
) {
194 return EFI_INVALID_PARAMETER
;
198 // Check whether the device path points to the default the input FV file
200 TempDevicePath
= *DevicePath
;
201 LastDeviceNode
= TempDevicePath
;
202 while (!IsDevicePathEnd (TempDevicePath
)) {
203 LastDeviceNode
= TempDevicePath
;
204 TempDevicePath
= NextDevicePathNode (TempDevicePath
);
206 GuidPoint
= EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) LastDeviceNode
);
207 if (GuidPoint
== NULL
) {
209 // If this option does not point to a FV file, just return EFI_UNSUPPORTED.
211 return EFI_UNSUPPORTED
;
214 if (FileGuid
!= NULL
) {
215 if (!CompareGuid (GuidPoint
, FileGuid
)) {
217 // If the FV file is not the input file GUID, just return EFI_UNSUPPORTED
219 return EFI_UNSUPPORTED
;
222 FileGuid
= GuidPoint
;
226 // Check to see if the device path contains memory map node
228 TempDevicePath
= *DevicePath
;
230 while (!IsDevicePathEnd (TempDevicePath
)) {
232 // Use old Device Path
234 if (DevicePathType (TempDevicePath
) == HARDWARE_DEVICE_PATH
&&
235 DevicePathSubType (TempDevicePath
) == HW_MEMMAP_DP
) {
239 TempDevicePath
= NextDevicePathNode (TempDevicePath
);
243 return EFI_UNSUPPORTED
;
247 // Check whether the input Fv file device path is valid
249 TempDevicePath
= *DevicePath
;
250 FoundFvHandle
= NULL
;
251 Status
= gBS
->LocateDevicePath (
252 &gEfiFirmwareVolume2ProtocolGuid
,
256 if (!EFI_ERROR (Status
)) {
257 Status
= gBS
->HandleProtocol (
259 &gEfiFirmwareVolume2ProtocolGuid
,
262 if (!EFI_ERROR (Status
)) {
264 // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there
266 Status
= Fv
->ReadFile (
273 &AuthenticationStatus
275 if (!EFI_ERROR (Status
)) {
276 return EFI_ALREADY_STARTED
;
282 // Look for the input wanted FV file in current FV
283 // First, try to look for in Caller own FV. Caller and input wanted FV file usually are in the same FV
286 FoundFvHandle
= NULL
;
287 Status
= gBS
->HandleProtocol (
289 &gEfiLoadedImageProtocolGuid
,
290 (VOID
**) &LoadedImage
292 if (!EFI_ERROR (Status
)) {
293 Status
= gBS
->HandleProtocol (
294 LoadedImage
->DeviceHandle
,
295 &gEfiFirmwareVolume2ProtocolGuid
,
298 if (!EFI_ERROR (Status
)) {
299 Status
= Fv
->ReadFile (
306 &AuthenticationStatus
308 if (!EFI_ERROR (Status
)) {
310 FoundFvHandle
= LoadedImage
->DeviceHandle
;
315 // Second, if fail to find, try to enumerate all FV
318 gBS
->LocateHandleBuffer (
320 &gEfiFirmwareVolume2ProtocolGuid
,
325 for (Index
= 0; Index
< FvHandleCount
; Index
++) {
326 gBS
->HandleProtocol (
327 FvHandleBuffer
[Index
],
328 &gEfiFirmwareVolume2ProtocolGuid
,
332 Status
= Fv
->ReadFile (
339 &AuthenticationStatus
341 if (EFI_ERROR (Status
)) {
343 // Skip if input Fv file not in the FV
348 FoundFvHandle
= FvHandleBuffer
[Index
];
355 // Build the shell device path
357 NewDevicePath
= DevicePathFromHandle (FoundFvHandle
);
358 EfiInitializeFwVolDevicepathNode (&FvFileNode
, FileGuid
);
359 NewDevicePath
= AppendDevicePathNode (NewDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) &FvFileNode
);
360 *DevicePath
= NewDevicePath
;
363 return EFI_NOT_FOUND
;
367 Gets the data and size of a variable.
369 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
370 buffer, and the size of the buffer. If failure return NULL.
372 @param Name String part of EFI variable name
373 @param VendorGuid GUID part of EFI variable name
374 @param VariableSize Returns the size of the EFI variable that was
377 @return Dynamically allocated memory that contains a copy of the EFI variable.
378 Caller is responsible freeing the buffer.
379 @retval NULL Variable was not read
386 IN EFI_GUID
*VendorGuid
,
387 OUT UINTN
*VariableSize
397 // Pass in a zero size buffer to find the required buffer size.
400 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
401 if (Status
== EFI_BUFFER_TOO_SMALL
) {
403 // Allocate the buffer to return
405 Buffer
= AllocateZeroPool (BufferSize
);
406 if (Buffer
== NULL
) {
410 // Read variable into the allocated buffer.
412 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
413 if (EFI_ERROR (Status
)) {
418 *VariableSize
= BufferSize
;
423 Connect to the handle to a device on the device path.
425 This function will create all handles associate with every device
426 path node. If the handle associate with one device path node can not
427 be created success, then still give one chance to do the dispatch,
428 which load the missing drivers if possible.
430 @param DevicePathToConnect The device path which will be connected, it can
431 be a multi-instance device path
433 @retval EFI_SUCCESS All handles associate with every device path
434 node have been created
435 @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles
436 @retval EFI_NOT_FOUND Create the handle associate with one device
443 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePathToConnect
447 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
448 EFI_DEVICE_PATH_PROTOCOL
*CopyOfDevicePath
;
449 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
450 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
451 EFI_DEVICE_PATH_PROTOCOL
*Next
;
453 EFI_HANDLE PreviousHandle
;
456 if (DevicePathToConnect
== NULL
) {
460 DevicePath
= DuplicateDevicePath (DevicePathToConnect
);
461 CopyOfDevicePath
= DevicePath
;
462 if (DevicePath
== NULL
) {
463 return EFI_OUT_OF_RESOURCES
;
468 // The outer loop handles multi instance device paths.
469 // Only console variables contain multiple instance device paths.
471 // After this call DevicePath points to the next Instance
473 Instance
= GetNextDevicePathInstance (&DevicePath
, &Size
);
474 ASSERT (Instance
!= NULL
);
477 while (!IsDevicePathEndType (Next
)) {
478 Next
= NextDevicePathNode (Next
);
481 SetDevicePathEndNode (Next
);
484 // Start the real work of connect with RemainingDevicePath
486 PreviousHandle
= NULL
;
489 // Find the handle that best matches the Device Path. If it is only a
490 // partial match the remaining part of the device path is returned in
491 // RemainingDevicePath.
493 RemainingDevicePath
= Instance
;
494 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingDevicePath
, &Handle
);
496 if (!EFI_ERROR (Status
)) {
497 if (Handle
== PreviousHandle
) {
499 // If no forward progress is made try invoking the Dispatcher.
500 // A new FV may have been added to the system an new drivers
502 // Status == EFI_SUCCESS means a driver was dispatched
503 // Status == EFI_NOT_FOUND means no new drivers were dispatched
505 Status
= gDS
->Dispatch ();
508 if (!EFI_ERROR (Status
)) {
509 PreviousHandle
= Handle
;
511 // Connect all drivers that apply to Handle and RemainingDevicePath,
512 // the Recursive flag is FALSE so only one level will be expanded.
514 // Do not check the connect status here, if the connect controller fail,
515 // then still give the chance to do dispatch, because partial
516 // RemainingDevicepath may be in the new FV
518 // 1. If the connect fails, RemainingDevicepath and handle will not
519 // change, so next time will do the dispatch, then dispatch's status
521 // 2. If the connect succeeds, the RemainingDevicepath and handle will
522 // change, then avoid the dispatch, we have chance to continue the
525 gBS
->ConnectController (Handle
, NULL
, RemainingDevicePath
, FALSE
);
529 // Loop until RemainingDevicePath is an empty device path
531 } while (!EFI_ERROR (Status
) && !IsDevicePathEnd (RemainingDevicePath
));
533 } while (DevicePath
!= NULL
);
535 if (CopyOfDevicePath
!= NULL
) {
536 FreePool (CopyOfDevicePath
);
539 // All handle with DevicePath exists in the handle database
545 Free all the mapping database memory resource and initialize the mapping list entry.
547 @param MappingDataBase Mapping database list entry pointer
549 @retval EFI_SUCCESS Mapping database successfully freed
550 @retval EFI_INVALID_PARAMETER MappingDataBase is NULL
555 FreeMappingDatabase (
556 IN OUT LIST_ENTRY
*MappingDataBase
559 LIST_ENTRY
*OverrideItemListIndex
;
560 LIST_ENTRY
*ImageInfoListIndex
;
561 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
562 DRIVER_IMAGE_INFO
*DriverImageInfo
;
564 if (MappingDataBase
== NULL
) {
565 return EFI_INVALID_PARAMETER
;
568 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
569 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
570 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
572 // Free PLATFORM_OVERRIDE_ITEM.ControllerDevicePath[]
574 if (OverrideItem
->ControllerDevicePath
!= NULL
){
575 FreePool (OverrideItem
->ControllerDevicePath
);
578 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
579 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
581 // Free DRIVER_IMAGE_INFO.DriverImagePath[]
583 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
584 if (DriverImageInfo
->DriverImagePath
!= NULL
) {
585 FreePool(DriverImageInfo
->DriverImagePath
);
588 // Free DRIVER_IMAGE_INFO itself
590 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
591 RemoveEntryList (&DriverImageInfo
->Link
);
592 FreePool (DriverImageInfo
);
595 // Free PLATFORM_OVERRIDE_ITEM itself
597 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
598 RemoveEntryList (&OverrideItem
->Link
);
599 FreePool (OverrideItem
);
602 InitializeListHead (MappingDataBase
);
608 Create the mapping database according to variable.
610 Read the environment variable(s) that contain the override mappings from Controller Device Path to
611 a set of Driver Device Paths, and create the mapping database in memory with those variable info.
614 // NotEnd indicate whether the variable is the last one, and has no subsequent variable need to load.
615 // Each variable has MaximumVariableSize limitation, so we maybe need multiple variables to store
616 // large mapping infos.
617 // The variable(s) name rule is PlatDriOver, PlatDriOver1, PlatDriOver2, ....
619 UINT32 NotEnd; //Zero is the last one.
621 // The entry which contains the mapping that Controller Device Path to a set of Driver Device Paths
622 // There are often multi mapping entries in a variable.
624 UINT32 SIGNATURE; //SIGNATURE_32('p','d','o','i')
626 EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[];
627 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
628 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
629 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
631 UINT32 NotEnd; //Zero is the last one.
634 EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[];
635 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
636 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
637 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
641 @param MappingDataBase Mapping database list entry pointer
643 @retval EFI_SUCCESS Create the mapping database in memory successfully
644 @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null
645 @retval EFI_NOT_FOUND Cannot find the 'PlatDriOver' NV variable
646 @retval EFI_VOLUME_CORRUPTED The found NV variable is corrupted
651 InitOverridesMapping (
652 OUT LIST_ENTRY
*MappingDataBase
656 VOID
*VariableBuffer
;
657 UINT8
*VariableIndex
;
659 CHAR16 OverrideVariableName
[40];
662 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
663 DRIVER_IMAGE_INFO
*DriverImageInfo
;
666 EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
;
667 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
670 if (MappingDataBase
== NULL
) {
671 return EFI_INVALID_PARAMETER
;
675 // Check the environment variable(s) that contain the override mappings .
677 VariableBuffer
= GetVariableAndSize (L
"PlatDriOver", &gEfiCallerIdGuid
, &BufferSize
);
678 ASSERT ((UINTN
) VariableBuffer
% sizeof(UINTN
) == 0);
679 if (VariableBuffer
== NULL
) {
680 return EFI_NOT_FOUND
;
684 // Traverse all variables.
690 VariableIndex
= VariableBuffer
;
691 if (VariableIndex
+ sizeof (UINT32
) > (UINT8
*) VariableBuffer
+ BufferSize
) {
697 NotEnd
= *(UINT32
*) VariableIndex
;
700 // Traverse the entries containing the mapping that Controller Device Path
701 // to a set of Driver Device Paths within this variable.
703 VariableIndex
= VariableIndex
+ sizeof (UINT32
);
704 while (VariableIndex
< ((UINT8
*)VariableBuffer
+ BufferSize
)) {
706 // Check signature of this entry
708 if (VariableIndex
+ sizeof (UINT32
) > (UINT8
*) VariableBuffer
+ BufferSize
) {
712 Signature
= *(UINT32
*) VariableIndex
;
713 if (Signature
!= PLATFORM_OVERRIDE_ITEM_SIGNATURE
) {
718 // Create PLATFORM_OVERRIDE_ITEM for this mapping
720 OverrideItem
= AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM
));
721 ASSERT (OverrideItem
!= NULL
);
722 OverrideItem
->Signature
= PLATFORM_OVERRIDE_ITEM_SIGNATURE
;
723 InitializeListHead (&OverrideItem
->DriverInfoList
);
724 VariableIndex
= VariableIndex
+ sizeof (UINT32
);
728 if (VariableIndex
+ sizeof (UINT32
) >= (UINT8
*) VariableBuffer
+ BufferSize
) {
732 DriverNumber
= *(UINT32
*) VariableIndex
;
733 OverrideItem
->DriverInfoNum
= DriverNumber
;
734 VariableIndex
= VariableIndex
+ sizeof (UINT32
);
736 // Get ControllerDevicePath[]
738 ControllerDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) VariableIndex
;
739 OverrideItem
->ControllerDevicePath
= DuplicateDevicePath (ControllerDevicePath
);
740 VariableIndex
= VariableIndex
+ GetDevicePathSize (ControllerDevicePath
);
742 // Align the VariableIndex since the controller device path may not be aligned, refer to the SaveOverridesMapping()
744 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
746 // Check buffer overflow.
748 if ((OverrideItem
->ControllerDevicePath
== NULL
) || (VariableIndex
< (UINT8
*) ControllerDevicePath
) ||
749 (VariableIndex
> (UINT8
*) VariableBuffer
+ BufferSize
)) {
755 // Get all DriverImageDevicePath[]
757 for (Index
= 0; Index
< DriverNumber
; Index
++) {
759 // Create DRIVER_IMAGE_INFO for this DriverDevicePath[]
761 DriverImageInfo
= AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO
));
762 ASSERT (DriverImageInfo
!= NULL
);
763 DriverImageInfo
->Signature
= DRIVER_IMAGE_INFO_SIGNATURE
;
765 DriverDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) VariableIndex
;
766 DriverImageInfo
->DriverImagePath
= DuplicateDevicePath (DriverDevicePath
);
767 VariableIndex
= VariableIndex
+ GetDevicePathSize (DriverDevicePath
);
769 // Align the VariableIndex since the driver image device path may not be aligned, refer to the SaveOverridesMapping()
771 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
773 InsertTailList (&OverrideItem
->DriverInfoList
, &DriverImageInfo
->Link
);
776 // Check buffer overflow
778 if ((DriverImageInfo
->DriverImagePath
== NULL
) || (VariableIndex
< (UINT8
*) DriverDevicePath
) ||
779 (VariableIndex
< (UINT8
*) VariableBuffer
+ BufferSize
)) {
784 InsertTailList (MappingDataBase
, &OverrideItem
->Link
);
790 FreePool (VariableBuffer
);
792 FreeMappingDatabase (MappingDataBase
);
793 return EFI_VOLUME_CORRUPTED
;
797 // If there are additional variables (PlatDriOver1, PlatDriOver2, PlatDriOver3.....), get them.
798 // NotEnd indicates whether current variable is the end variable.
801 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", VariableNum
++);
802 VariableBuffer
= GetVariableAndSize (OverrideVariableName
, &gEfiCallerIdGuid
, &BufferSize
);
803 ASSERT ((UINTN
) VariableBuffer
% sizeof(UINTN
) == 0);
804 if (VariableBuffer
== NULL
) {
805 FreeMappingDatabase (MappingDataBase
);
806 return EFI_VOLUME_CORRUPTED
;
810 } while (NotEnd
!= 0);
817 Calculate the needed size in NV variable for recording a specific PLATFORM_OVERRIDE_ITEM info.
819 @param OverrideItemListIndex Pointer to the list of a specific PLATFORM_OVERRIDE_ITEM
821 @return The needed size number
826 GetOneItemNeededSize (
827 IN LIST_ENTRY
*OverrideItemListIndex
831 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
832 LIST_ENTRY
*ImageInfoListIndex
;
833 DRIVER_IMAGE_INFO
*DriverImageInfo
;
834 UINTN DevicePathSize
;
837 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
838 NeededSize
+= sizeof (UINT32
); //UINT32 SIGNATURE;
839 NeededSize
+= sizeof (UINT32
); //UINT32 DriverNum;
840 DevicePathSize
= GetDevicePathSize (OverrideItem
->ControllerDevicePath
);
841 NeededSize
+= DevicePathSize
; // ControllerDevicePath
843 // Align the controller device path
845 NeededSize
+= ((sizeof(UINT32
) - DevicePathSize
) & (sizeof(UINT32
) - 1));
847 // Traverse the Driver Info List of this Override Item
849 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
850 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
851 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
852 DevicePathSize
= GetDevicePathSize (DriverImageInfo
->DriverImagePath
);
853 NeededSize
+= DevicePathSize
; //DriverDevicePath
855 // Align the driver image device path
857 NeededSize
+= ((sizeof(UINT32
) - DevicePathSize
) & (sizeof(UINT32
) - 1));
858 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
865 Deletes all environment variable(s) that contain the override mappings from Controller Device Path to
866 a set of Driver Device Paths.
868 @retval EFI_SUCCESS Delete all variable(s) successfully.
873 DeleteOverridesVariables (
878 VOID
*VariableBuffer
;
882 CHAR16 OverrideVariableName
[40];
885 // Get environment variable(s) number
888 VariableBuffer
= GetVariableAndSize (L
"PlatDriOver", &gEfiCallerIdGuid
, &BufferSize
);
890 if (VariableBuffer
== NULL
) {
891 return EFI_NOT_FOUND
;
894 // Check NotEnd to get all PlatDriOverX variable(s)
896 while ((VariableBuffer
!= NULL
) && ((*(UINT32
*)VariableBuffer
) != 0)) {
897 FreePool (VariableBuffer
);
898 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", VariableNum
);
899 VariableBuffer
= GetVariableAndSize (OverrideVariableName
, &gEfiCallerIdGuid
, &BufferSize
);
904 // Delete PlatDriOver and all additional variables, if exist.
906 Status
= gRT
->SetVariable (
909 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
913 ASSERT (!EFI_ERROR (Status
));
914 for (Index
= 1; Index
< VariableNum
; Index
++) {
915 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", Index
);
916 Status
= gRT
->SetVariable (
917 OverrideVariableName
,
919 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
923 ASSERT (!EFI_ERROR (Status
));
930 Save the memory mapping database into NV environment variable(s).
932 @param MappingDataBase Mapping database list entry pointer
934 @retval EFI_SUCCESS Save memory mapping database successfully
935 @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null
940 SaveOverridesMapping (
941 IN LIST_ENTRY
*MappingDataBase
945 VOID
*VariableBuffer
;
946 UINT8
*VariableIndex
;
948 CHAR16 OverrideVariableName
[40];
950 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
951 DRIVER_IMAGE_INFO
*DriverImageInfo
;
952 LIST_ENTRY
*OverrideItemListIndex
;
953 LIST_ENTRY
*ItemIndex
;
954 LIST_ENTRY
*ImageInfoListIndex
;
955 UINTN VariableNeededSize
;
956 UINT64 MaximumVariableStorageSize
;
957 UINT64 RemainingVariableStorageSize
;
958 UINT64 MaximumVariableSize
;
959 UINTN OneItemNeededSize
;
961 if (MappingDataBase
== NULL
) {
962 return EFI_INVALID_PARAMETER
;
965 if (IsListEmpty (MappingDataBase
)) {
966 Status
= DeleteOverridesVariables ();
971 // Get the the maximum size of an individual EFI variable in current system
973 gRT
->QueryVariableInfo (
974 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
975 &MaximumVariableStorageSize
,
976 &RemainingVariableStorageSize
,
981 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
982 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
984 // Try to find the most proper variable size which <= MaximumVariableSize,
985 // but can contain mapping info as much as possible
987 VariableNeededSize
= sizeof (UINT32
); // NotEnd;
988 ItemIndex
= OverrideItemListIndex
;
991 // Traverse all PLATFORM_OVERRIDE_ITEMs and get the total size.
993 while (!IsNull (MappingDataBase
, ItemIndex
)) {
994 OneItemNeededSize
= GetOneItemNeededSize (ItemIndex
);
996 // If the total size exceeds the MaximumVariableSize, then we must use
997 // multiple variables.
999 if ((VariableNeededSize
+
1001 StrSize (L
"PlatDriOver ")
1002 ) >= MaximumVariableSize
1008 VariableNeededSize
+= OneItemNeededSize
;
1009 ItemIndex
= GetNextNode (MappingDataBase
, ItemIndex
);
1013 if (VariableNeededSize
== sizeof (UINT32
)) {
1015 // If an individual EFI variable cannot contain a single Item, return error
1017 return EFI_OUT_OF_RESOURCES
;
1022 // VariableNeededSize is the most proper variable size, allocate variable buffer
1023 // ItemIndex now points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize
1025 VariableBuffer
= AllocateZeroPool (VariableNeededSize
);
1026 ASSERT (VariableBuffer
!= NULL
);
1027 ASSERT ((UINTN
) VariableBuffer
% sizeof(UINTN
) == 0);
1030 // Fill the variable buffer according to MappingDataBase
1032 VariableIndex
= VariableBuffer
;
1033 *(UINT32
*) VariableIndex
= NotEnd
;
1034 VariableIndex
+= sizeof (UINT32
); // pass NotEnd
1036 // ItemIndex points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize
1038 while (OverrideItemListIndex
!= ItemIndex
){
1039 *(UINT32
*) VariableIndex
= PLATFORM_OVERRIDE_ITEM_SIGNATURE
;
1040 VariableIndex
+= sizeof (UINT32
); // pass SIGNATURE
1042 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1043 *(UINT32
*) VariableIndex
= OverrideItem
->DriverInfoNum
;
1044 VariableIndex
+= sizeof (UINT32
); // pass DriverNum
1046 CopyMem (VariableIndex
, OverrideItem
->ControllerDevicePath
, GetDevicePathSize (OverrideItem
->ControllerDevicePath
));
1047 VariableIndex
+= GetDevicePathSize (OverrideItem
->ControllerDevicePath
); // pass ControllerDevicePath
1050 // Align the VariableIndex since the controller device path may not be aligned
1052 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
1054 // Save the Driver Info List of this PLATFORM_OVERRIDE_ITEM
1056 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1057 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1058 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1059 CopyMem (VariableIndex
, DriverImageInfo
->DriverImagePath
, GetDevicePathSize (DriverImageInfo
->DriverImagePath
));
1060 VariableIndex
+= GetDevicePathSize (DriverImageInfo
->DriverImagePath
); // pass DriverImageDevicePath
1062 // Align the VariableIndex since the driver image device path may not be aligned
1064 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
1065 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1068 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1071 ASSERT (((UINTN
)VariableIndex
- (UINTN
)VariableBuffer
) == VariableNeededSize
);
1073 if (NumIndex
== 0) {
1074 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver");
1076 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", NumIndex
);
1079 Status
= gRT
->SetVariable (
1080 OverrideVariableName
,
1082 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1086 FreePool (VariableBuffer
);
1088 if (EFI_ERROR (Status
)) {
1091 // Delete all PlatDriOver variables when full mapping can't be set.
1093 DeleteOverridesVariables ();
1105 Get the first Binding protocol which has the specific image handle.
1107 @param ImageHandle The Image handle
1108 @param BindingHandle The BindingHandle of the found Driver Binding protocol.
1109 If Binding protocol is not found, it is set to NULL.
1111 @return Pointer into the Binding Protocol interface
1112 @retval NULL The parameter is not valid or the binding protocol is not found.
1115 EFI_DRIVER_BINDING_PROTOCOL
*
1117 GetBindingProtocolFromImageHandle (
1118 IN EFI_HANDLE ImageHandle
,
1119 OUT EFI_HANDLE
*BindingHandle
1124 UINTN DriverBindingHandleCount
;
1125 EFI_HANDLE
*DriverBindingHandleBuffer
;
1126 EFI_DRIVER_BINDING_PROTOCOL
*DriverBindingInterface
;
1128 if (BindingHandle
== NULL
|| ImageHandle
== NULL
) {
1132 // Get all drivers which support driver binding protocol
1134 DriverBindingHandleCount
= 0;
1135 Status
= gBS
->LocateHandleBuffer (
1137 &gEfiDriverBindingProtocolGuid
,
1139 &DriverBindingHandleCount
,
1140 &DriverBindingHandleBuffer
1142 if (EFI_ERROR (Status
) || (DriverBindingHandleCount
== 0)) {
1146 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
1147 DriverBindingInterface
= NULL
;
1148 Status
= gBS
->OpenProtocol (
1149 DriverBindingHandleBuffer
[Index
],
1150 &gEfiDriverBindingProtocolGuid
,
1151 (VOID
**) &DriverBindingInterface
,
1154 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1156 if (EFI_ERROR (Status
)) {
1160 if (DriverBindingInterface
->ImageHandle
== ImageHandle
) {
1161 *BindingHandle
= DriverBindingHandleBuffer
[Index
];
1162 FreePool (DriverBindingHandleBuffer
);
1163 return DriverBindingInterface
;
1168 // If no Driver Binding Protocol instance is found
1170 FreePool (DriverBindingHandleBuffer
);
1171 *BindingHandle
= NULL
;
1176 Return the current TPL.
1188 Tpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
1189 gBS
->RestoreTPL (Tpl
);
1196 Retrieves the image handle of the platform override driver for a controller in
1197 the system from the memory mapping database.
1199 @param ControllerHandle The device handle of the controller to check if
1200 a driver override exists.
1201 @param DriverImageHandle On input, the previously returnd driver image handle.
1202 On output, a pointer to the next driver handle.
1203 Passing in a pointer to NULL, will return the
1204 first driver handle for ControllerHandle.
1205 @param MappingDataBase Mapping database list entry pointer
1206 @param CallerImageHandle The caller driver's image handle, for
1207 UpdateFvFileDevicePath use.
1209 @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not
1210 a valid handle. Or DriverImagePath is not a
1211 device path that was returned on a previous call
1213 @retval EFI_NOT_FOUND A driver override for ControllerHandle was not
1215 @retval EFI_UNSUPPORTED The operation is not supported.
1216 @retval EFI_SUCCESS The driver override for ControllerHandle was
1217 returned in DriverImagePath.
1222 GetDriverFromMapping (
1223 IN EFI_HANDLE ControllerHandle
,
1224 IN OUT EFI_HANDLE
*DriverImageHandle
,
1225 IN LIST_ENTRY
*MappingDataBase
,
1226 IN EFI_HANDLE CallerImageHandle
1230 EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
;
1231 BOOLEAN ControllerFound
;
1233 EFI_HANDLE
*ImageHandleBuffer
;
1234 UINTN ImageHandleCount
;
1236 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
1237 EFI_HANDLE DriverBindingHandle
;
1238 BOOLEAN FoundLastReturned
;
1239 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1240 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1241 LIST_ENTRY
*OverrideItemListIndex
;
1242 LIST_ENTRY
*ImageInfoListIndex
;
1243 EFI_DEVICE_PATH_PROTOCOL
*TempDriverImagePath
;
1244 EFI_HANDLE ImageHandle
;
1246 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
1247 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*BusSpecificDriverOverride
;
1248 UINTN DevicePathSize
;
1251 // Check that ControllerHandle is a valid handle
1253 if (ControllerHandle
== NULL
) {
1254 return EFI_INVALID_PARAMETER
;
1257 // Get the device path of ControllerHandle
1259 Status
= gBS
->HandleProtocol (
1261 &gEfiDevicePathProtocolGuid
,
1262 (VOID
**) &ControllerDevicePath
1264 if (EFI_ERROR (Status
) || ControllerDevicePath
== NULL
) {
1265 return EFI_INVALID_PARAMETER
;
1269 // Search ControllerDevicePath in MappingDataBase
1271 OverrideItem
= NULL
;
1272 ControllerFound
= FALSE
;
1273 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1275 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1276 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1277 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1278 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1280 ControllerDevicePath
,
1281 OverrideItem
->ControllerDevicePath
,
1285 ControllerFound
= TRUE
;
1289 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1292 if (!ControllerFound
) {
1293 return EFI_NOT_FOUND
;
1296 // Passing in a pointer to NULL, will return the first driver device path for ControllerHandle.
1297 // Check whether the driverImagePath is not a device path that was returned on a previous call to GetDriverPath().
1299 if (*DriverImageHandle
!= NULL
) {
1300 if (*DriverImageHandle
!= OverrideItem
->LastReturnedImageHandle
) {
1301 return EFI_INVALID_PARAMETER
;
1305 // The GetDriverPath() may be called recursively, because it use ConnectDevicePath() internally,
1306 // so should check whether there is a dead loop.
1307 // Here use a controller device path stack to record all processed controller device path during a GetDriverPath() call,
1308 // and check the controller device path whether appear again during the GetDriverPath() call.
1310 if (CheckExistInStack (OverrideItem
->ControllerDevicePath
)) {
1312 // There is a dependency dead loop if the ControllerDevicePath appear in stack twice
1314 return EFI_UNSUPPORTED
;
1316 PushDevPathStack (OverrideItem
->ControllerDevicePath
);
1319 // Check every override driver, try to load and start them
1321 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1322 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1323 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1324 if (DriverImageInfo
->ImageHandle
== NULL
) {
1326 // Skip if the image is unloadable or unstartable
1328 if ((!DriverImageInfo
->UnLoadable
) && ((!DriverImageInfo
->UnStartable
))) {
1329 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
1331 // If the image device path contains an FV node, check the FV file device path is valid.
1332 // If it is invalid, try to return the valid device path.
1333 // FV address maybe changes for memory layout adjust from time to time,
1334 // use this function could promise the FV file device path is right.
1336 Status
= UpdateFvFileDevicePath (&TempDriverImagePath
, NULL
, CallerImageHandle
);
1337 if (!EFI_ERROR (Status
)) {
1338 FreePool (DriverImageInfo
->DriverImagePath
);
1339 DriverImageInfo
->DriverImagePath
= TempDriverImagePath
;
1342 // Get all Loaded Image protocol to check whether the driver image has been loaded and started
1345 ImageHandleCount
= 0;
1346 Status
= gBS
->LocateHandleBuffer (
1348 &gEfiLoadedImageProtocolGuid
,
1353 if (EFI_ERROR (Status
) || (ImageHandleCount
== 0)) {
1354 return EFI_NOT_FOUND
;
1357 for(Index
= 0; Index
< ImageHandleCount
; Index
++) {
1359 // Get the EFI Loaded Image Device Path Protocol
1361 LoadedImageDevicePath
= NULL
;
1362 Status
= gBS
->HandleProtocol (
1363 ImageHandleBuffer
[Index
],
1364 &gEfiLoadedImageDevicePathProtocolGuid
,
1365 (VOID
**) &LoadedImageDevicePath
1367 if (EFI_ERROR (Status
)) {
1369 // Maybe not all EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL existed.
1374 DevicePathSize
= GetDevicePathSize (DriverImageInfo
->DriverImagePath
);
1375 if (DevicePathSize
== GetDevicePathSize (LoadedImageDevicePath
)) {
1377 DriverImageInfo
->DriverImagePath
,
1378 LoadedImageDevicePath
,
1379 GetDevicePathSize (LoadedImageDevicePath
)
1390 // Find its related driver binding protocol
1391 // Driver binding handle may be different with its driver's Image Handle.
1393 DriverBindingHandle
= NULL
;
1394 DriverBinding
= GetBindingProtocolFromImageHandle (
1395 ImageHandleBuffer
[Index
],
1396 &DriverBindingHandle
1398 ASSERT (DriverBinding
!= NULL
);
1399 DriverImageInfo
->ImageHandle
= ImageHandleBuffer
[Index
];
1400 } else if (GetCurrentTpl() <= TPL_CALLBACK
){
1402 // The driver image has not been loaded and started. Try to load and start it now.
1403 // Try to connect all device in the driver image path.
1405 // Note: LoadImage() and StartImage() should be called under CALLBACK TPL in theory, but
1406 // since many device need to be connected in CALLBACK level environment( e.g. Usb devices )
1407 // and the Fat and Patition driver can endure executing in CALLBACK level in fact, so here permit
1408 // to use LoadImage() and StartImage() in CALLBACK TPL.
1410 Status
= ConnectDevicePath (DriverImageInfo
->DriverImagePath
);
1412 // check whether it points to a PCI Option Rom image,
1413 // and try to use bus override protocol to get its first option rom image driver
1415 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
1416 gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &TempDriverImagePath
, &Handle
);
1418 // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
1420 Status
= gBS
->HandleProtocol(
1422 &gEfiBusSpecificDriverOverrideProtocolGuid
,
1423 (VOID
**) &BusSpecificDriverOverride
1425 if (!EFI_ERROR (Status
) && (BusSpecificDriverOverride
!= NULL
)) {
1427 Status
= BusSpecificDriverOverride
->GetDriver (
1428 BusSpecificDriverOverride
,
1431 if (!EFI_ERROR (Status
)) {
1433 // Find its related driver binding protocol
1434 // Driver binding handle may be different with its driver's Image handle
1436 DriverBindingHandle
= NULL
;
1437 DriverBinding
= GetBindingProtocolFromImageHandle (
1439 &DriverBindingHandle
1441 ASSERT (DriverBinding
!= NULL
);
1442 DriverImageInfo
->ImageHandle
= ImageHandle
;
1446 // Skip if any device cannot be connected now, future passes through GetDriver() may be able to load that driver.
1447 // Only file path media or FwVol Device Path Node remain if all device is connected
1449 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
1450 gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &TempDriverImagePath
, &Handle
);
1451 if (((DevicePathType (TempDriverImagePath
) == MEDIA_DEVICE_PATH
) &&
1452 (DevicePathSubType (TempDriverImagePath
) == MEDIA_FILEPATH_DP
)) ||
1453 (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempDriverImagePath
) != NULL
)
1456 // Try to load the driver
1458 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
1459 Status
= gBS
->LoadImage (
1462 TempDriverImagePath
,
1467 if (!EFI_ERROR (Status
)) {
1469 // Try to start the driver
1471 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
1472 if (EFI_ERROR (Status
)){
1473 DriverImageInfo
->UnStartable
= TRUE
;
1474 DriverImageInfo
->ImageHandle
= NULL
;
1477 // Find its related driver binding protocol
1478 // Driver binding handle may be different with its driver's Image handle
1480 DriverBindingHandle
= NULL
;
1481 DriverBinding
= GetBindingProtocolFromImageHandle (
1483 &DriverBindingHandle
1485 ASSERT (DriverBinding
!= NULL
);
1486 DriverImageInfo
->ImageHandle
= ImageHandle
;
1490 // With EFI_SECURITY_VIOLATION retval, the Image was loaded and an ImageHandle was created
1491 // with a valid EFI_LOADED_IMAGE_PROTOCOL, but the image can not be started right now.
1492 // If the caller doesn't have the option to defer the execution of an image, we should
1493 // unload image for the EFI_SECURITY_VIOLATION to avoid resource leak.
1495 if (Status
== EFI_SECURITY_VIOLATION
) {
1496 gBS
->UnloadImage (ImageHandle
);
1498 DriverImageInfo
->UnLoadable
= TRUE
;
1499 DriverImageInfo
->ImageHandle
= NULL
;
1503 FreePool (ImageHandleBuffer
);
1506 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1509 // Finish try to load and start the override driver of a controller, popup the controller's device path
1511 PopDevPathStack (NULL
);
1514 // return the DriverImageHandle for ControllerHandle
1516 FoundLastReturned
= FALSE
;
1517 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1518 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1519 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1520 if (DriverImageInfo
->ImageHandle
!= NULL
) {
1521 if ((*DriverImageHandle
== NULL
) || FoundLastReturned
) {
1523 // If DriverImageHandle is NULL, then we just need to return the first driver.
1524 // If FoundLastReturned, this means we have just encountered the previously returned driver.
1525 // For both cases, we just return the image handle of this driver.
1527 OverrideItem
->LastReturnedImageHandle
= DriverImageInfo
->ImageHandle
;
1528 *DriverImageHandle
= DriverImageInfo
->ImageHandle
;
1530 } else if (*DriverImageHandle
== DriverImageInfo
->ImageHandle
){
1532 // We have found the previously returned driver.
1534 FoundLastReturned
= TRUE
;
1537 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1540 return EFI_NOT_FOUND
;
1545 Check mapping database whether already has the mapping info which
1546 records the input Controller to input DriverImage.
1548 @param ControllerDevicePath The controller device path is to be check.
1549 @param DriverImageDevicePath The driver image device path is to be check.
1550 @param MappingDataBase Mapping database list entry pointer
1551 @param DriverInfoNum the controller's total override driver number
1552 @param DriverImageNO The driver order number for the input DriverImage.
1553 If the DriverImageDevicePath is NULL, DriverImageNO is not set.
1555 @retval EFI_INVALID_PARAMETER ControllerDevicePath or MappingDataBase is NULL.
1556 @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or
1557 DriverImageDevicePath is not found in the found DriverImage Info list.
1558 @retval EFI_SUCCESS The controller's total override driver number and
1559 input DriverImage's order number is correctly return.
1564 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
1565 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath OPTIONAL
,
1566 IN LIST_ENTRY
*MappingDataBase
,
1567 OUT UINT32
*DriverInfoNum OPTIONAL
,
1568 OUT UINT32
*DriverImageNO OPTIONAL
1571 LIST_ENTRY
*OverrideItemListIndex
;
1572 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1573 LIST_ENTRY
*ImageInfoListIndex
;
1574 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1577 UINTN DevicePathSize
;
1579 if (ControllerDevicePath
== NULL
) {
1580 return EFI_INVALID_PARAMETER
;
1582 if (MappingDataBase
== NULL
) {
1583 return EFI_INVALID_PARAMETER
;
1587 // Search ControllerDevicePath in MappingDataBase
1590 OverrideItem
= NULL
;
1591 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1592 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1593 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1594 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1595 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1597 ControllerDevicePath
,
1598 OverrideItem
->ControllerDevicePath
,
1606 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1611 // ControllerDevicePath is not in MappingDataBase
1613 return EFI_NOT_FOUND
;
1616 ASSERT (OverrideItem
->DriverInfoNum
!= 0);
1617 if (DriverInfoNum
!= NULL
) {
1618 *DriverInfoNum
= OverrideItem
->DriverInfoNum
;
1622 // If DriverImageDevicePath is NULL, skip checking DriverImageDevicePath
1623 // in the controller's Driver Image Info List
1625 if (DriverImageDevicePath
== NULL
) {
1629 // return the DriverImageHandle for ControllerHandle
1633 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1634 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1635 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1637 DevicePathSize
= GetDevicePathSize (DriverImageDevicePath
);
1638 if (DevicePathSize
== GetDevicePathSize (DriverImageInfo
->DriverImagePath
)) {
1640 DriverImageDevicePath
,
1641 DriverImageInfo
->DriverImagePath
,
1642 GetDevicePathSize (DriverImageInfo
->DriverImagePath
)
1649 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1654 // DriverImageDevicePath is not found in the controller's Driver Image Info List
1656 return EFI_NOT_FOUND
;
1658 if (DriverImageNO
!= NULL
) {
1659 *DriverImageNO
= ImageNO
;
1667 Insert a driver image as a controller's override driver into the mapping database.
1668 The driver image's order number is indicated by DriverImageNO.
1670 @param ControllerDevicePath The controller device path need to add a
1671 override driver image item
1672 @param DriverImageDevicePath The driver image device path need to be insert
1673 @param MappingDataBase Mapping database list entry pointer
1674 @param DriverImageNO The inserted order number. If this number is taken,
1675 the larger available number will be used.
1677 @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or DriverImageDevicePath is NULL
1678 or MappingDataBase is NULL
1679 @retval EFI_ALREADY_STARTED The input Controller to input DriverImage has been
1680 recorded into the mapping database.
1681 @retval EFI_SUCCESS The Controller and DriverImage are inserted into
1682 the mapping database successfully.
1688 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
1689 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath
,
1690 IN LIST_ENTRY
*MappingDataBase
,
1691 IN UINT32 DriverImageNO
1695 LIST_ENTRY
*OverrideItemListIndex
;
1696 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1697 LIST_ENTRY
*ImageInfoListIndex
;
1698 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1701 UINTN DevicePathSize
;
1703 if (ControllerDevicePath
== NULL
) {
1704 return EFI_INVALID_PARAMETER
;
1706 if (DriverImageDevicePath
== NULL
) {
1707 return EFI_INVALID_PARAMETER
;
1709 if (MappingDataBase
== NULL
) {
1710 return EFI_INVALID_PARAMETER
;
1714 // If the driver is already in the controller's Driver Image Info List,
1715 // just return EFI_ALREADY_STARTED.
1717 Status
= CheckMapping (
1718 ControllerDevicePath
,
1719 DriverImageDevicePath
,
1724 if (Status
== EFI_SUCCESS
) {
1725 return EFI_ALREADY_STARTED
;
1729 // Search the input ControllerDevicePath in MappingDataBase
1732 OverrideItem
= NULL
;
1733 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1734 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1735 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1736 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1737 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1739 ControllerDevicePath
,
1740 OverrideItem
->ControllerDevicePath
,
1748 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1751 // If cannot find, this is a new controller item
1752 // Add the Controller related PLATFORM_OVERRIDE_ITEM structrue in mapping data base
1755 OverrideItem
= AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM
));
1756 ASSERT (OverrideItem
!= NULL
);
1757 OverrideItem
->Signature
= PLATFORM_OVERRIDE_ITEM_SIGNATURE
;
1758 OverrideItem
->ControllerDevicePath
= DuplicateDevicePath (ControllerDevicePath
);
1759 InitializeListHead (&OverrideItem
->DriverInfoList
);
1760 InsertTailList (MappingDataBase
, &OverrideItem
->Link
);
1764 // Prepare the driver image related DRIVER_IMAGE_INFO structure.
1766 DriverImageInfo
= AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO
));
1767 ASSERT (DriverImageInfo
!= NULL
);
1768 DriverImageInfo
->Signature
= DRIVER_IMAGE_INFO_SIGNATURE
;
1769 DriverImageInfo
->DriverImagePath
= DuplicateDevicePath (DriverImageDevicePath
);
1771 // Find the driver image wanted order location
1775 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1776 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1777 if (ImageNO
== (DriverImageNO
- 1)) {
1779 // find the wanted order location, insert it
1781 InsertTailList (ImageInfoListIndex
, &DriverImageInfo
->Link
);
1782 OverrideItem
->DriverInfoNum
++;
1787 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1792 // if not find the wanted order location, add it as last item of the controller mapping item
1794 InsertTailList (&OverrideItem
->DriverInfoList
, &DriverImageInfo
->Link
);
1795 OverrideItem
->DriverInfoNum
++;
1803 Delete a controller's override driver from the mapping database.
1805 @param ControllerDevicePath The controller device path will be deleted
1806 when all drivers images on it are removed.
1807 @param DriverImageDevicePath The driver image device path will be delete.
1808 If NULL, all driver image will be delete.
1809 @param MappingDataBase Mapping database list entry pointer
1811 @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or MappingDataBase is NULL
1812 @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or
1813 DriverImageDevicePath is not found in the found DriverImage Info list.
1814 @retval EFI_SUCCESS Delete the specified driver successfully.
1820 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
1821 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath
,
1822 IN LIST_ENTRY
*MappingDataBase
1826 LIST_ENTRY
*OverrideItemListIndex
;
1827 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1828 LIST_ENTRY
*ImageInfoListIndex
;
1829 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1831 UINTN DevicePathSize
;
1833 if (ControllerDevicePath
== NULL
) {
1834 return EFI_INVALID_PARAMETER
;
1837 if (MappingDataBase
== NULL
) {
1838 return EFI_INVALID_PARAMETER
;
1842 // If ControllerDevicePath is not found in mapping database, return EFI_NOT_FOUND.
1844 Status
= CheckMapping (
1845 ControllerDevicePath
,
1846 DriverImageDevicePath
,
1851 if (EFI_ERROR (Status
)) {
1852 return EFI_NOT_FOUND
;
1856 // Search ControllerDevicePath in MappingDataBase
1859 OverrideItem
= NULL
;
1860 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1861 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1862 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1863 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1864 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1866 ControllerDevicePath
,
1867 OverrideItem
->ControllerDevicePath
,
1875 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1879 ASSERT (OverrideItem
->DriverInfoNum
!= 0);
1882 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1883 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1884 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1885 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1886 if (DriverImageDevicePath
!= NULL
) {
1888 // Search for the specified DriverImageDevicePath and remove it, then break.
1890 DevicePathSize
= GetDevicePathSize (DriverImageDevicePath
);
1891 if (DevicePathSize
== GetDevicePathSize (DriverImageInfo
->DriverImagePath
)) {
1893 DriverImageDevicePath
,
1894 DriverImageInfo
->DriverImagePath
,
1895 GetDevicePathSize (DriverImageInfo
->DriverImagePath
)
1899 FreePool(DriverImageInfo
->DriverImagePath
);
1900 RemoveEntryList (&DriverImageInfo
->Link
);
1901 OverrideItem
->DriverInfoNum
--;
1907 // Remove all existing driver image info entries, so no break here.
1910 FreePool(DriverImageInfo
->DriverImagePath
);
1911 RemoveEntryList (&DriverImageInfo
->Link
);
1912 OverrideItem
->DriverInfoNum
--;
1917 // Confirm all driver image info entries have been removed,
1918 // if DriverImageDevicePath is NULL.
1920 if (DriverImageDevicePath
== NULL
) {
1921 ASSERT (OverrideItem
->DriverInfoNum
== 0);
1924 // If Override Item has no driver image info entry, then delete this item.
1926 if (OverrideItem
->DriverInfoNum
== 0) {
1927 FreePool(OverrideItem
->ControllerDevicePath
);
1928 RemoveEntryList (&OverrideItem
->Link
);
1929 FreePool (OverrideItem
);
1934 // DriverImageDevicePath is not NULL and cannot be found in the controller's
1935 // driver image info list.
1937 return EFI_NOT_FOUND
;