2 Implementation of the shared functions to do the platform driver vverride mapping.
4 Copyright (c) 2007 - 2018, 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
;
1489 DriverImageInfo
->UnLoadable
= TRUE
;
1490 DriverImageInfo
->ImageHandle
= NULL
;
1494 FreePool (ImageHandleBuffer
);
1497 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1500 // Finish try to load and start the override driver of a controller, popup the controller's device path
1502 PopDevPathStack (NULL
);
1505 // return the DriverImageHandle for ControllerHandle
1507 FoundLastReturned
= FALSE
;
1508 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1509 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1510 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1511 if (DriverImageInfo
->ImageHandle
!= NULL
) {
1512 if ((*DriverImageHandle
== NULL
) || FoundLastReturned
) {
1514 // If DriverImageHandle is NULL, then we just need to return the first driver.
1515 // If FoundLastReturned, this means we have just encountered the previously returned driver.
1516 // For both cases, we just return the image handle of this driver.
1518 OverrideItem
->LastReturnedImageHandle
= DriverImageInfo
->ImageHandle
;
1519 *DriverImageHandle
= DriverImageInfo
->ImageHandle
;
1521 } else if (*DriverImageHandle
== DriverImageInfo
->ImageHandle
){
1523 // We have found the previously returned driver.
1525 FoundLastReturned
= TRUE
;
1528 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1531 return EFI_NOT_FOUND
;
1536 Check mapping database whether already has the mapping info which
1537 records the input Controller to input DriverImage.
1539 @param ControllerDevicePath The controller device path is to be check.
1540 @param DriverImageDevicePath The driver image device path is to be check.
1541 @param MappingDataBase Mapping database list entry pointer
1542 @param DriverInfoNum the controller's total override driver number
1543 @param DriverImageNO The driver order number for the input DriverImage.
1544 If the DriverImageDevicePath is NULL, DriverImageNO is not set.
1546 @retval EFI_INVALID_PARAMETER ControllerDevicePath or MappingDataBase is NULL.
1547 @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or
1548 DriverImageDevicePath is not found in the found DriverImage Info list.
1549 @retval EFI_SUCCESS The controller's total override driver number and
1550 input DriverImage's order number is correctly return.
1555 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
1556 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath OPTIONAL
,
1557 IN LIST_ENTRY
*MappingDataBase
,
1558 OUT UINT32
*DriverInfoNum OPTIONAL
,
1559 OUT UINT32
*DriverImageNO OPTIONAL
1562 LIST_ENTRY
*OverrideItemListIndex
;
1563 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1564 LIST_ENTRY
*ImageInfoListIndex
;
1565 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1568 UINTN DevicePathSize
;
1570 if (ControllerDevicePath
== NULL
) {
1571 return EFI_INVALID_PARAMETER
;
1573 if (MappingDataBase
== NULL
) {
1574 return EFI_INVALID_PARAMETER
;
1578 // Search ControllerDevicePath in MappingDataBase
1581 OverrideItem
= NULL
;
1582 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1583 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1584 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1585 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1586 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1588 ControllerDevicePath
,
1589 OverrideItem
->ControllerDevicePath
,
1597 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1602 // ControllerDevicePath is not in MappingDataBase
1604 return EFI_NOT_FOUND
;
1607 ASSERT (OverrideItem
->DriverInfoNum
!= 0);
1608 if (DriverInfoNum
!= NULL
) {
1609 *DriverInfoNum
= OverrideItem
->DriverInfoNum
;
1613 // If DriverImageDevicePath is NULL, skip checking DriverImageDevicePath
1614 // in the controller's Driver Image Info List
1616 if (DriverImageDevicePath
== NULL
) {
1620 // return the DriverImageHandle for ControllerHandle
1624 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1625 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1626 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1628 DevicePathSize
= GetDevicePathSize (DriverImageDevicePath
);
1629 if (DevicePathSize
== GetDevicePathSize (DriverImageInfo
->DriverImagePath
)) {
1631 DriverImageDevicePath
,
1632 DriverImageInfo
->DriverImagePath
,
1633 GetDevicePathSize (DriverImageInfo
->DriverImagePath
)
1640 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1645 // DriverImageDevicePath is not found in the controller's Driver Image Info List
1647 return EFI_NOT_FOUND
;
1649 if (DriverImageNO
!= NULL
) {
1650 *DriverImageNO
= ImageNO
;
1658 Insert a driver image as a controller's override driver into the mapping database.
1659 The driver image's order number is indicated by DriverImageNO.
1661 @param ControllerDevicePath The controller device path need to add a
1662 override driver image item
1663 @param DriverImageDevicePath The driver image device path need to be insert
1664 @param MappingDataBase Mapping database list entry pointer
1665 @param DriverImageNO The inserted order number. If this number is taken,
1666 the larger available number will be used.
1668 @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or DriverImageDevicePath is NULL
1669 or MappingDataBase is NULL
1670 @retval EFI_ALREADY_STARTED The input Controller to input DriverImage has been
1671 recorded into the mapping database.
1672 @retval EFI_SUCCESS The Controller and DriverImage are inserted into
1673 the mapping database successfully.
1679 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
1680 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath
,
1681 IN LIST_ENTRY
*MappingDataBase
,
1682 IN UINT32 DriverImageNO
1686 LIST_ENTRY
*OverrideItemListIndex
;
1687 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1688 LIST_ENTRY
*ImageInfoListIndex
;
1689 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1692 UINTN DevicePathSize
;
1694 if (ControllerDevicePath
== NULL
) {
1695 return EFI_INVALID_PARAMETER
;
1697 if (DriverImageDevicePath
== NULL
) {
1698 return EFI_INVALID_PARAMETER
;
1700 if (MappingDataBase
== NULL
) {
1701 return EFI_INVALID_PARAMETER
;
1705 // If the driver is already in the controller's Driver Image Info List,
1706 // just return EFI_ALREADY_STARTED.
1708 Status
= CheckMapping (
1709 ControllerDevicePath
,
1710 DriverImageDevicePath
,
1715 if (Status
== EFI_SUCCESS
) {
1716 return EFI_ALREADY_STARTED
;
1720 // Search the input ControllerDevicePath in MappingDataBase
1723 OverrideItem
= NULL
;
1724 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1725 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1726 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1727 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1728 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1730 ControllerDevicePath
,
1731 OverrideItem
->ControllerDevicePath
,
1739 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1742 // If cannot find, this is a new controller item
1743 // Add the Controller related PLATFORM_OVERRIDE_ITEM structrue in mapping data base
1746 OverrideItem
= AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM
));
1747 ASSERT (OverrideItem
!= NULL
);
1748 OverrideItem
->Signature
= PLATFORM_OVERRIDE_ITEM_SIGNATURE
;
1749 OverrideItem
->ControllerDevicePath
= DuplicateDevicePath (ControllerDevicePath
);
1750 InitializeListHead (&OverrideItem
->DriverInfoList
);
1751 InsertTailList (MappingDataBase
, &OverrideItem
->Link
);
1755 // Prepare the driver image related DRIVER_IMAGE_INFO structure.
1757 DriverImageInfo
= AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO
));
1758 ASSERT (DriverImageInfo
!= NULL
);
1759 DriverImageInfo
->Signature
= DRIVER_IMAGE_INFO_SIGNATURE
;
1760 DriverImageInfo
->DriverImagePath
= DuplicateDevicePath (DriverImageDevicePath
);
1762 // Find the driver image wanted order location
1766 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1767 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1768 if (ImageNO
== (DriverImageNO
- 1)) {
1770 // find the wanted order location, insert it
1772 InsertTailList (ImageInfoListIndex
, &DriverImageInfo
->Link
);
1773 OverrideItem
->DriverInfoNum
++;
1778 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1783 // if not find the wanted order location, add it as last item of the controller mapping item
1785 InsertTailList (&OverrideItem
->DriverInfoList
, &DriverImageInfo
->Link
);
1786 OverrideItem
->DriverInfoNum
++;
1794 Delete a controller's override driver from the mapping database.
1796 @param ControllerDevicePath The controller device path will be deleted
1797 when all drivers images on it are removed.
1798 @param DriverImageDevicePath The driver image device path will be delete.
1799 If NULL, all driver image will be delete.
1800 @param MappingDataBase Mapping database list entry pointer
1802 @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or MappingDataBase is NULL
1803 @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or
1804 DriverImageDevicePath is not found in the found DriverImage Info list.
1805 @retval EFI_SUCCESS Delete the specified driver successfully.
1811 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
1812 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath
,
1813 IN LIST_ENTRY
*MappingDataBase
1817 LIST_ENTRY
*OverrideItemListIndex
;
1818 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1819 LIST_ENTRY
*ImageInfoListIndex
;
1820 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1822 UINTN DevicePathSize
;
1824 if (ControllerDevicePath
== NULL
) {
1825 return EFI_INVALID_PARAMETER
;
1828 if (MappingDataBase
== NULL
) {
1829 return EFI_INVALID_PARAMETER
;
1833 // If ControllerDevicePath is not found in mapping database, return EFI_NOT_FOUND.
1835 Status
= CheckMapping (
1836 ControllerDevicePath
,
1837 DriverImageDevicePath
,
1842 if (EFI_ERROR (Status
)) {
1843 return EFI_NOT_FOUND
;
1847 // Search ControllerDevicePath in MappingDataBase
1850 OverrideItem
= NULL
;
1851 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1852 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1853 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1854 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1855 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1857 ControllerDevicePath
,
1858 OverrideItem
->ControllerDevicePath
,
1866 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1870 ASSERT (OverrideItem
->DriverInfoNum
!= 0);
1873 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1874 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1875 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1876 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1877 if (DriverImageDevicePath
!= NULL
) {
1879 // Search for the specified DriverImageDevicePath and remove it, then break.
1881 DevicePathSize
= GetDevicePathSize (DriverImageDevicePath
);
1882 if (DevicePathSize
== GetDevicePathSize (DriverImageInfo
->DriverImagePath
)) {
1884 DriverImageDevicePath
,
1885 DriverImageInfo
->DriverImagePath
,
1886 GetDevicePathSize (DriverImageInfo
->DriverImagePath
)
1890 FreePool(DriverImageInfo
->DriverImagePath
);
1891 RemoveEntryList (&DriverImageInfo
->Link
);
1892 OverrideItem
->DriverInfoNum
--;
1898 // Remove all existing driver image info entries, so no break here.
1901 FreePool(DriverImageInfo
->DriverImagePath
);
1902 RemoveEntryList (&DriverImageInfo
->Link
);
1903 OverrideItem
->DriverInfoNum
--;
1908 // Confirm all driver image info entries have been removed,
1909 // if DriverImageDevicePath is NULL.
1911 if (DriverImageDevicePath
== NULL
) {
1912 ASSERT (OverrideItem
->DriverInfoNum
== 0);
1915 // If Override Item has no driver image info entry, then delete this item.
1917 if (OverrideItem
->DriverInfoNum
== 0) {
1918 FreePool(OverrideItem
->ControllerDevicePath
);
1919 RemoveEntryList (&OverrideItem
->Link
);
1920 FreePool (OverrideItem
);
1925 // DriverImageDevicePath is not NULL and cannot be found in the controller's
1926 // driver image info list.
1928 return EFI_NOT_FOUND
;