2 Implementation of Platform Driver Override Library.
4 Copyright (c) 2007 - 2008, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "PlatDriOver.h"
17 LIST_ENTRY mDevicePathStack
= INITIALIZE_LIST_HEAD_VARIABLE (mDevicePathStack
);
20 Free all the mapping database memory resource and initialize the mapping list entry.
22 @param MappingDataBase Mapping database list entry pointer
24 @retval EFI_SUCCESS Mapping database successfully freed
25 @retval EFI_INVALID_PARAMETER MappingDataBase is NULL
31 IN OUT LIST_ENTRY
*MappingDataBase
34 LIST_ENTRY
*OverrideItemListIndex
;
35 LIST_ENTRY
*ImageInfoListIndex
;
36 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
37 DRIVER_IMAGE_INFO
*DriverImageInfo
;
39 if (MappingDataBase
== NULL
) {
40 return EFI_INVALID_PARAMETER
;
43 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
44 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
45 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
47 // Free PLATFORM_OVERRIDE_ITEM.ControllerDevicePath[]
49 if (OverrideItem
->ControllerDevicePath
!= NULL
){
50 FreePool (OverrideItem
->ControllerDevicePath
);
53 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
54 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
56 // Free DRIVER_IMAGE_INFO.DriverImagePath[]
58 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
59 if (DriverImageInfo
->DriverImagePath
!= NULL
) {
60 FreePool(DriverImageInfo
->DriverImagePath
);
63 // Free DRIVER_IMAGE_INFO itself
65 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
66 RemoveEntryList (&DriverImageInfo
->Link
);
67 FreePool (DriverImageInfo
);
70 // Free PLATFORM_OVERRIDE_ITEM itself
72 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
73 RemoveEntryList (&OverrideItem
->Link
);
74 FreePool (OverrideItem
);
77 InitializeListHead (MappingDataBase
);
83 Create the mapping database according to variable.
85 Read the environment variable(s) that contain the override mappings from Controller Device Path to
86 a set of Driver Device Paths, and create the mapping database in memory with those variable info.
89 // NotEnd indicate whether the variable is the last one, and has no subsequent variable need to load.
90 // Each variable has MaximumVariableSize limitation, so we maybe need multiple variables to store
91 // large mapping infos.
92 // The variable(s) name rule is PlatDriOver, PlatDriOver1, PlatDriOver2, ....
94 UINT32 NotEnd; //Zero is the last one.
96 // The entry which contains the mapping that Controller Device Path to a set of Driver Device Paths
97 // There are often multi mapping entries in a variable.
99 UINT32 SIGNATURE; //SIGNATURE_32('p','d','o','i')
101 EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[];
102 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
103 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
104 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
106 UINT32 NotEnd; //Zero is the last one.
109 EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[];
110 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
111 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
112 EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
116 @param MappingDataBase Mapping database list entry pointer
118 @retval EFI_SUCCESS Create the mapping database in memory successfully
119 @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null
120 @retval EFI_NOT_FOUND Cannot find the 'PlatDriOver' NV variable
121 @retval EFI_VOLUME_CORRUPTED The found NV variable is corrupted
126 InitOverridesMapping (
127 OUT LIST_ENTRY
*MappingDataBase
131 VOID
*VariableBuffer
;
132 UINT8
*VariableIndex
;
134 CHAR16 OverrideVariableName
[40];
137 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
138 DRIVER_IMAGE_INFO
*DriverImageInfo
;
141 EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
;
142 EFI_DEVICE_PATH_PROTOCOL
*DriverDevicePath
;
145 if (MappingDataBase
== NULL
) {
146 return EFI_INVALID_PARAMETER
;
150 // Check the environment variable(s) that contain the override mappings .
152 VariableBuffer
= GetVariableAndSize (L
"PlatDriOver", &gEfiOverrideVariableGuid
, &BufferSize
);
153 ASSERT ((UINTN
) VariableBuffer
% sizeof(UINTN
) == 0);
154 if (VariableBuffer
== NULL
) {
155 return EFI_NOT_FOUND
;
159 // Traverse all variables.
164 VariableIndex
= VariableBuffer
;
168 NotEnd
= *(UINT32
*) VariableIndex
;
170 // Traverse the entries containing the mapping that Controller Device Path
171 // to a set of Driver Device Paths within this variable.
173 VariableIndex
= VariableIndex
+ sizeof (UINT32
);
174 while (VariableIndex
< ((UINT8
*)VariableBuffer
+ BufferSize
)) {
176 // Check signature of this entry
178 Signature
= *(UINT32
*) VariableIndex
;
179 if (Signature
!= PLATFORM_OVERRIDE_ITEM_SIGNATURE
) {
184 // Create PLATFORM_OVERRIDE_ITEM for this mapping
186 OverrideItem
= AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM
));
187 ASSERT (OverrideItem
!= NULL
);
188 OverrideItem
->Signature
= PLATFORM_OVERRIDE_ITEM_SIGNATURE
;
189 InitializeListHead (&OverrideItem
->DriverInfoList
);
190 VariableIndex
= VariableIndex
+ sizeof (UINT32
);
194 DriverNumber
= *(UINT32
*) VariableIndex
;
195 OverrideItem
->DriverInfoNum
= DriverNumber
;
196 VariableIndex
= VariableIndex
+ sizeof (UINT32
);
198 // Get ControllerDevicePath[]
200 ControllerDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) VariableIndex
;
201 OverrideItem
->ControllerDevicePath
= DuplicateDevicePath (ControllerDevicePath
);
202 VariableIndex
= VariableIndex
+ GetDevicePathSize (ControllerDevicePath
);
204 // Align the VariableIndex since the controller device path may not be aligned, refer to the SaveOverridesMapping()
206 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
209 // Get all DriverImageDevicePath[]
211 for (Index
= 0; Index
< DriverNumber
; Index
++) {
213 // Create DRIVER_IMAGE_INFO for this DriverDevicePath[]
215 DriverImageInfo
= AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO
));
216 ASSERT (DriverImageInfo
!= NULL
);
217 DriverImageInfo
->Signature
= DRIVER_IMAGE_INFO_SIGNATURE
;
219 DriverDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) VariableIndex
;
220 DriverImageInfo
->DriverImagePath
= DuplicateDevicePath (DriverDevicePath
);
221 VariableIndex
= VariableIndex
+ GetDevicePathSize (DriverDevicePath
);
223 // Align the VariableIndex since the driver image device path may not be aligned, refer to the SaveOverridesMapping()
225 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
227 InsertTailList (&OverrideItem
->DriverInfoList
, &DriverImageInfo
->Link
);
229 InsertTailList (MappingDataBase
, &OverrideItem
->Link
);
232 FreePool (VariableBuffer
);
234 FreeMappingDatabase (MappingDataBase
);
235 return EFI_VOLUME_CORRUPTED
;
239 // If there are additional variables (PlatDriOver1, PlatDriOver2, PlatDriOver3.....), get them.
240 // NotEnd indicates whether current variable is the end variable.
243 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", VariableNum
++);
244 VariableBuffer
= GetVariableAndSize (OverrideVariableName
, &gEfiOverrideVariableGuid
, &BufferSize
);
245 ASSERT ((UINTN
) VariableBuffer
% sizeof(UINTN
) == 0);
246 if (VariableBuffer
== NULL
) {
247 FreeMappingDatabase (MappingDataBase
);
248 return EFI_VOLUME_CORRUPTED
;
252 } while (NotEnd
!= 0);
259 Calculate the needed size in NV variable for recording a specific PLATFORM_OVERRIDE_ITEM info.
261 @param OverrideItemListIndex Pointer to the list of a specific PLATFORM_OVERRIDE_ITEM
263 @return The needed size number
268 GetOneItemNeededSize (
269 IN LIST_ENTRY
*OverrideItemListIndex
273 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
274 LIST_ENTRY
*ImageInfoListIndex
;
275 DRIVER_IMAGE_INFO
*DriverImageInfo
;
276 UINTN DevicePathSize
;
279 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
280 NeededSize
+= sizeof (UINT32
); //UINT32 SIGNATURE;
281 NeededSize
+= sizeof (UINT32
); //UINT32 DriverNum;
282 DevicePathSize
= GetDevicePathSize (OverrideItem
->ControllerDevicePath
);
283 NeededSize
+= DevicePathSize
; // ControllerDevicePath
285 // Align the controller device path
287 NeededSize
+= ((sizeof(UINT32
) - DevicePathSize
) & (sizeof(UINT32
) - 1));
289 // Traverse the Driver Info List of this Override Item
291 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
292 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
293 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
294 DevicePathSize
= GetDevicePathSize (DriverImageInfo
->DriverImagePath
);
295 NeededSize
+= DevicePathSize
; //DriverDevicePath
297 // Align the driver image device path
299 NeededSize
+= ((sizeof(UINT32
) - DevicePathSize
) & (sizeof(UINT32
) - 1));
300 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
307 Deletes all environment variable(s) that contain the override mappings from Controller Device Path to
308 a set of Driver Device Paths.
310 @retval EFI_SUCCESS Delete all variable(s) successfully.
315 DeleteOverridesVariables (
320 VOID
*VariableBuffer
;
324 CHAR16 OverrideVariableName
[40];
327 // Get environment variable(s) number
330 VariableBuffer
= GetVariableAndSize (L
"PlatDriOver", &gEfiOverrideVariableGuid
, &BufferSize
);
332 if (VariableBuffer
== NULL
) {
333 return EFI_NOT_FOUND
;
336 // Check NotEnd to get all PlatDriOverX variable(s)
338 while ((*(UINT32
*)VariableBuffer
) != 0) {
339 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", VariableNum
);
340 VariableBuffer
= GetVariableAndSize (OverrideVariableName
, &gEfiOverrideVariableGuid
, &BufferSize
);
342 ASSERT (VariableBuffer
!= NULL
);
346 // Delete PlatDriOver and all additional variables, if exist.
348 Status
= gRT
->SetVariable (
350 &gEfiOverrideVariableGuid
,
351 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
355 ASSERT (!EFI_ERROR (Status
));
356 for (Index
= 1; Index
< VariableNum
; Index
++) {
357 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", Index
);
358 Status
= gRT
->SetVariable (
359 OverrideVariableName
,
360 &gEfiOverrideVariableGuid
,
361 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
365 ASSERT (!EFI_ERROR (Status
));
372 Save the memory mapping database into NV environment variable(s).
374 @param MappingDataBase Mapping database list entry pointer
376 @retval EFI_SUCCESS Save memory mapping database successfully
377 @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null
382 SaveOverridesMapping (
383 IN LIST_ENTRY
*MappingDataBase
387 VOID
*VariableBuffer
;
388 UINT8
*VariableIndex
;
390 CHAR16 OverrideVariableName
[40];
392 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
393 DRIVER_IMAGE_INFO
*DriverImageInfo
;
394 LIST_ENTRY
*OverrideItemListIndex
;
395 LIST_ENTRY
*ItemIndex
;
396 LIST_ENTRY
*ImageInfoListIndex
;
397 UINTN VariableNeededSize
;
398 UINT64 MaximumVariableStorageSize
;
399 UINT64 RemainingVariableStorageSize
;
400 UINT64 MaximumVariableSize
;
401 UINTN OneItemNeededSize
;
403 if (MappingDataBase
== NULL
) {
404 return EFI_INVALID_PARAMETER
;
407 if (IsListEmpty (MappingDataBase
)) {
408 Status
= DeleteOverridesVariables ();
409 ASSERT_EFI_ERROR (Status
);
414 // Get the the maximum size of an individual EFI variable in current system
416 gRT
->QueryVariableInfo (
417 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
418 &MaximumVariableStorageSize
,
419 &RemainingVariableStorageSize
,
424 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
425 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
427 // Try to find the most proper variable size which <= MaximumVariableSize,
428 // but can contain mapping info as much as possible
430 VariableNeededSize
= sizeof (UINT32
); // NotEnd;
431 ItemIndex
= OverrideItemListIndex
;
434 // Traverse all PLATFORM_OVERRIDE_ITEMs and get the total size.
436 while (!IsNull (MappingDataBase
, ItemIndex
)) {
437 OneItemNeededSize
= GetOneItemNeededSize (ItemIndex
);
439 // If the total size exceeds the MaximumVariableSize, then we must use
440 // multiple variables.
442 if ((VariableNeededSize
+
444 sizeof (VARIABLE_HEADER
) +
445 StrSize (L
"PlatDriOver ")
446 ) >= MaximumVariableSize
452 VariableNeededSize
+= OneItemNeededSize
;
453 ItemIndex
= GetNextNode (MappingDataBase
, ItemIndex
);
457 if (VariableNeededSize
== sizeof (UINT32
)) {
459 // If an individual EFI variable cannot contain a single Item, return error
461 return EFI_OUT_OF_RESOURCES
;
466 // VariableNeededSize is the most proper variable size, allocate variable buffer
467 // ItemIndex now points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize
469 VariableBuffer
= AllocateZeroPool (VariableNeededSize
);
470 ASSERT (VariableBuffer
!= NULL
);
471 ASSERT ((UINTN
) VariableBuffer
% sizeof(UINTN
) == 0);
474 // Fill the variable buffer according to MappingDataBase
476 VariableIndex
= VariableBuffer
;
477 *(UINT32
*) VariableIndex
= NotEnd
;
478 VariableIndex
+= sizeof (UINT32
); // pass NotEnd
480 // ItemIndex points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize
482 while (OverrideItemListIndex
!= ItemIndex
){
483 *(UINT32
*) VariableIndex
= PLATFORM_OVERRIDE_ITEM_SIGNATURE
;
484 VariableIndex
+= sizeof (UINT32
); // pass SIGNATURE
486 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
487 *(UINT32
*) VariableIndex
= OverrideItem
->DriverInfoNum
;
488 VariableIndex
+= sizeof (UINT32
); // pass DriverNum
490 CopyMem (VariableIndex
, OverrideItem
->ControllerDevicePath
, GetDevicePathSize (OverrideItem
->ControllerDevicePath
));
491 VariableIndex
+= GetDevicePathSize (OverrideItem
->ControllerDevicePath
); // pass ControllerDevicePath
494 // Align the VariableIndex since the controller device path may not be aligned
496 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
498 // Save the Driver Info List of this PLATFORM_OVERRIDE_ITEM
500 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
501 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
502 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
503 CopyMem (VariableIndex
, DriverImageInfo
->DriverImagePath
, GetDevicePathSize (DriverImageInfo
->DriverImagePath
));
504 VariableIndex
+= GetDevicePathSize (DriverImageInfo
->DriverImagePath
); // pass DriverImageDevicePath
506 // Align the VariableIndex since the driver image device path may not be aligned
508 VariableIndex
+= ((sizeof(UINT32
) - ((UINTN
) (VariableIndex
))) & (sizeof(UINT32
) - 1));
509 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
512 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
515 ASSERT (((UINTN
)VariableIndex
- (UINTN
)VariableBuffer
) == VariableNeededSize
);
518 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver");
520 UnicodeSPrint (OverrideVariableName
, sizeof (OverrideVariableName
), L
"PlatDriOver%d", NumIndex
);
523 Status
= gRT
->SetVariable (
524 OverrideVariableName
,
525 &gEfiOverrideVariableGuid
,
526 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
530 ASSERT (!EFI_ERROR(Status
));
533 FreePool (VariableBuffer
);
540 Get the first Binding protocol which has the specific image handle.
542 @param ImageHandle The Image handle
543 @param BindingHandle The BindingHandle of the found Driver Binding protocol.
544 If Binding protocol is not found, it is set to NULL.
546 @return Pointer into the Binding Protocol interface
547 @retval NULL The paramter is not valid or the binding protocol is not found.
550 EFI_DRIVER_BINDING_PROTOCOL
*
552 GetBindingProtocolFromImageHandle (
553 IN EFI_HANDLE ImageHandle
,
554 OUT EFI_HANDLE
*BindingHandle
559 UINTN DriverBindingHandleCount
;
560 EFI_HANDLE
*DriverBindingHandleBuffer
;
561 EFI_DRIVER_BINDING_PROTOCOL
*DriverBindingInterface
;
563 if (BindingHandle
== NULL
|| ImageHandle
== NULL
) {
567 // Get all drivers which support driver binding protocol
569 DriverBindingHandleCount
= 0;
570 Status
= gBS
->LocateHandleBuffer (
572 &gEfiDriverBindingProtocolGuid
,
574 &DriverBindingHandleCount
,
575 &DriverBindingHandleBuffer
577 if (EFI_ERROR (Status
) || (DriverBindingHandleCount
== 0)) {
581 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
582 DriverBindingInterface
= NULL
;
583 Status
= gBS
->OpenProtocol (
584 DriverBindingHandleBuffer
[Index
],
585 &gEfiDriverBindingProtocolGuid
,
586 (VOID
**) &DriverBindingInterface
,
589 EFI_OPEN_PROTOCOL_GET_PROTOCOL
591 if (EFI_ERROR (Status
)) {
595 if (DriverBindingInterface
->ImageHandle
== ImageHandle
) {
596 *BindingHandle
= DriverBindingHandleBuffer
[Index
];
597 FreePool (DriverBindingHandleBuffer
);
598 return DriverBindingInterface
;
603 // If no Driver Binding Protocol instance is found
605 FreePool (DriverBindingHandleBuffer
);
606 *BindingHandle
= NULL
;
611 Return the current TPL.
623 Tpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
624 gBS
->RestoreTPL (Tpl
);
631 Retrieves the image handle of the platform override driver for a controller in
632 the system from the memory mapping database.
634 @param ControllerHandle The device handle of the controller to check if
635 a driver override exists.
636 @param DriverImageHandle On input, the previously returnd driver image handle.
637 On output, a pointer to the next driver handle.
638 Passing in a pointer to NULL, will return the
639 first driver handle for ControllerHandle.
640 @param MappingDataBase Mapping database list entry pointer
641 @param CallerImageHandle The caller driver's image handle, for
642 UpdateFvFileDevicePath use.
644 @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not
645 a valid handle. Or DriverImagePath is not a
646 device path that was returned on a previous call
648 @retval EFI_NOT_FOUND A driver override for ControllerHandle was not
650 @retval EFI_UNSUPPORTED The operation is not supported.
651 @retval EFI_SUCCESS The driver override for ControllerHandle was
652 returned in DriverImagePath.
657 GetDriverFromMapping (
658 IN EFI_HANDLE ControllerHandle
,
659 IN OUT EFI_HANDLE
*DriverImageHandle
,
660 IN LIST_ENTRY
*MappingDataBase
,
661 IN EFI_HANDLE CallerImageHandle
665 EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
;
666 BOOLEAN ControllerFound
;
668 EFI_HANDLE
*ImageHandleBuffer
;
669 UINTN ImageHandleCount
;
671 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
672 EFI_HANDLE DriverBindingHandle
;
673 BOOLEAN FoundLastReturned
;
674 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
675 DRIVER_IMAGE_INFO
*DriverImageInfo
;
676 LIST_ENTRY
*OverrideItemListIndex
;
677 LIST_ENTRY
*ImageInfoListIndex
;
678 EFI_DEVICE_PATH_PROTOCOL
*TempDriverImagePath
;
679 EFI_HANDLE ImageHandle
;
681 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
682 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*BusSpecificDriverOverride
;
683 UINTN DevicePathSize
;
686 // Check that ControllerHandle is a valid handle
688 if (ControllerHandle
== NULL
) {
689 return EFI_INVALID_PARAMETER
;
692 // Get the device path of ControllerHandle
694 Status
= gBS
->HandleProtocol (
696 &gEfiDevicePathProtocolGuid
,
697 (VOID
**) &ControllerDevicePath
699 if (EFI_ERROR (Status
) || ControllerDevicePath
== NULL
) {
700 return EFI_INVALID_PARAMETER
;
704 // Search ControllerDevicePath in MappingDataBase
707 ControllerFound
= FALSE
;
708 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
710 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
711 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
712 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
713 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
715 ControllerDevicePath
,
716 OverrideItem
->ControllerDevicePath
,
720 ControllerFound
= TRUE
;
724 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
727 if (!ControllerFound
) {
728 return EFI_NOT_FOUND
;
731 // Passing in a pointer to NULL, will return the first driver device path for ControllerHandle.
732 // Check whether the driverImagePath is not a device path that was returned on a previous call to GetDriverPath().
734 if (*DriverImageHandle
!= NULL
) {
735 if (*DriverImageHandle
!= OverrideItem
->LastReturnedImageHandle
) {
736 return EFI_INVALID_PARAMETER
;
740 // The GetDriverPath() may be called recursively, because it use ConnectDevicePath() internally,
741 // so should check whether there is a dead loop.
742 // Here use a controller device path stack to record all processed controller device path during a GetDriverPath() call,
743 // and check the controller device path whether appear again during the GetDriverPath() call.
745 if (CheckExistInStack (OverrideItem
->ControllerDevicePath
)) {
747 // There is a dependecy dead loop if the ControllerDevicePath appear in stack twice
749 return EFI_UNSUPPORTED
;
751 PushDevPathStack (OverrideItem
->ControllerDevicePath
);
754 // Check every override driver, try to load and start them
756 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
757 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
758 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
759 if (DriverImageInfo
->ImageHandle
== NULL
) {
761 // Skip if the image is unloadable or unstartable
763 if ((!DriverImageInfo
->UnLoadable
) && ((!DriverImageInfo
->UnStartable
))) {
764 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
766 // If the image device path contains an FV node, check the FV file device path is valid.
767 // If it is invalid, try to return the valid device path.
768 // FV address maybe changes for memory layout adjust from time to time,
769 // use this funciton could promise the FV file device path is right.
771 Status
= UpdateFvFileDevicePath (&TempDriverImagePath
, NULL
, CallerImageHandle
);
772 if (!EFI_ERROR (Status
)) {
773 FreePool (DriverImageInfo
->DriverImagePath
);
774 DriverImageInfo
->DriverImagePath
= TempDriverImagePath
;
777 // Get all Loaded Image protocol to check whether the driver image has been loaded and started
780 ImageHandleCount
= 0;
781 Status
= gBS
->LocateHandleBuffer (
783 &gEfiLoadedImageProtocolGuid
,
788 if (EFI_ERROR (Status
) || (ImageHandleCount
== 0)) {
789 return EFI_NOT_FOUND
;
792 for(Index
= 0; Index
< ImageHandleCount
; Index
++) {
794 // Get the EFI Loaded Image Device Path Protocol
796 LoadedImageDevicePath
= NULL
;
797 Status
= gBS
->HandleProtocol (
798 ImageHandleBuffer
[Index
],
799 &gEfiLoadedImageDevicePathProtocolGuid
,
800 (VOID
**) &LoadedImageDevicePath
802 if (EFI_ERROR (Status
)) {
804 // Maybe not all EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL existed.
809 DevicePathSize
= GetDevicePathSize (DriverImageInfo
->DriverImagePath
);
810 if (DevicePathSize
== GetDevicePathSize (LoadedImageDevicePath
)) {
812 DriverImageInfo
->DriverImagePath
,
813 LoadedImageDevicePath
,
814 GetDevicePathSize (LoadedImageDevicePath
)
825 // Find its related driver binding protocol
826 // Driver binding handle may be different with its driver's Image Handle.
828 DriverBindingHandle
= NULL
;
829 DriverBinding
= GetBindingProtocolFromImageHandle (
830 ImageHandleBuffer
[Index
],
833 ASSERT (DriverBinding
!= NULL
);
834 DriverImageInfo
->ImageHandle
= ImageHandleBuffer
[Index
];
835 } else if (GetCurrentTpl() <= TPL_CALLBACK
){
837 // The driver image has not been loaded and started. Try to load and start it now.
838 // Try to connect all device in the driver image path.
840 // Note: LoadImage() and StartImage() should be called under CALLBACK TPL in theory, but
841 // since many device need to be connected in CALLBACK level environment( e.g. Usb devices )
842 // and the Fat and Patition driver can endure executing in CALLBACK level in fact, so here permit
843 // to use LoadImage() and StartImage() in CALLBACK TPL.
845 Status
= ConnectDevicePath (DriverImageInfo
->DriverImagePath
);
847 // check whether it points to a PCI Option Rom image,
848 // and try to use bus override protocol to get its first option rom image driver
850 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
851 gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &TempDriverImagePath
, &Handle
);
853 // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
855 Status
= gBS
->HandleProtocol(
857 &gEfiBusSpecificDriverOverrideProtocolGuid
,
858 (VOID
**) &BusSpecificDriverOverride
860 if (!EFI_ERROR (Status
) && (BusSpecificDriverOverride
!= NULL
)) {
862 Status
= BusSpecificDriverOverride
->GetDriver (
863 BusSpecificDriverOverride
,
866 if (!EFI_ERROR (Status
)) {
868 // Find its related driver binding protocol
869 // Driver binding handle may be different with its driver's Image handle
871 DriverBindingHandle
= NULL
;
872 DriverBinding
= GetBindingProtocolFromImageHandle (
876 ASSERT (DriverBinding
!= NULL
);
877 DriverImageInfo
->ImageHandle
= ImageHandle
;
881 // Skip if any device cannot be connected now, future passes through GetDriver() may be able to load that driver.
882 // Only file path media or FwVol Device Path Node remain if all device is connected
884 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
885 gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &TempDriverImagePath
, &Handle
);
886 if (((DevicePathType (TempDriverImagePath
) == MEDIA_DEVICE_PATH
) &&
887 (DevicePathSubType (TempDriverImagePath
) == MEDIA_FILEPATH_DP
)) ||
888 (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) TempDriverImagePath
) != NULL
)
891 // Try to load the driver
893 TempDriverImagePath
= DriverImageInfo
->DriverImagePath
;
894 Status
= gBS
->LoadImage (
902 if (!EFI_ERROR (Status
)) {
904 // Try to start the driver
906 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
907 if (EFI_ERROR (Status
)){
908 DriverImageInfo
->UnStartable
= TRUE
;
909 DriverImageInfo
->ImageHandle
= NULL
;
912 // Find its related driver binding protocol
913 // Driver binding handle may be different with its driver's Image handle
915 DriverBindingHandle
= NULL
;
916 DriverBinding
= GetBindingProtocolFromImageHandle (
920 ASSERT (DriverBinding
!= NULL
);
921 DriverImageInfo
->ImageHandle
= ImageHandle
;
924 DriverImageInfo
->UnLoadable
= TRUE
;
925 DriverImageInfo
->ImageHandle
= NULL
;
929 FreePool (ImageHandleBuffer
);
932 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
935 // Finish try to load and start the override driver of a controller, popup the controller's device path
937 PopDevPathStack (NULL
);
940 // return the DriverImageHandle for ControllerHandle
942 FoundLastReturned
= FALSE
;
943 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
944 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
945 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
946 if (DriverImageInfo
->ImageHandle
!= NULL
) {
947 if ((*DriverImageHandle
== NULL
) || FoundLastReturned
) {
949 // If DriverImageHandle is NULL, then we just need to return the first driver.
950 // If FoundLastReturned, this means we have just encountered the previously returned driver.
951 // For both cases, we just return the image handle of this driver.
953 OverrideItem
->LastReturnedImageHandle
= DriverImageInfo
->ImageHandle
;
954 *DriverImageHandle
= DriverImageInfo
->ImageHandle
;
956 } else if (*DriverImageHandle
== DriverImageInfo
->ImageHandle
){
958 // We have found the previously returned driver.
960 FoundLastReturned
= TRUE
;
963 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
966 return EFI_NOT_FOUND
;
971 Check mapping database whether already has the mapping info which
972 records the input Controller to input DriverImage.
974 @param ControllerDevicePath The controller device path is to be check.
975 @param DriverImageDevicePath The driver image device path is to be check.
976 @param MappingDataBase Mapping database list entry pointer
977 @param DriverInfoNum the controller's total override driver number
978 @param DriverImageNO The driver order number for the input DriverImage.
979 If the DriverImageDevicePath is NULL, DriverImageNO is not set.
981 @retval EFI_INVALID_PARAMETER ControllerDevicePath or MappingDataBase is NULL.
982 @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or
983 DriverImageDevicePath is not found in the found DriverImage Info list.
984 @retval EFI_SUCCESS The controller's total override driver number and
985 input DriverImage's order number is correctly return.
990 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
991 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath OPTIONAL
,
992 IN LIST_ENTRY
*MappingDataBase
,
993 OUT UINT32
*DriverInfoNum OPTIONAL
,
994 OUT UINT32
*DriverImageNO OPTIONAL
997 LIST_ENTRY
*OverrideItemListIndex
;
998 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
999 LIST_ENTRY
*ImageInfoListIndex
;
1000 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1003 UINTN DevicePathSize
;
1005 if (ControllerDevicePath
== NULL
) {
1006 return EFI_INVALID_PARAMETER
;
1008 if (MappingDataBase
== NULL
) {
1009 return EFI_INVALID_PARAMETER
;
1013 // Search ControllerDevicePath in MappingDataBase
1016 OverrideItem
= NULL
;
1017 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1018 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1019 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1020 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1021 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1023 ControllerDevicePath
,
1024 OverrideItem
->ControllerDevicePath
,
1032 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1037 // ControllerDevicePath is not in MappingDataBase
1039 return EFI_NOT_FOUND
;
1042 ASSERT (OverrideItem
->DriverInfoNum
!= 0);
1043 if (DriverInfoNum
!= NULL
) {
1044 *DriverInfoNum
= OverrideItem
->DriverInfoNum
;
1048 // If DriverImageDevicePath is NULL, skip checking DriverImageDevicePath
1049 // in the controller's Driver Image Info List
1051 if (DriverImageDevicePath
== NULL
) {
1055 // return the DriverImageHandle for ControllerHandle
1059 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1060 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1061 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1063 DevicePathSize
= GetDevicePathSize (DriverImageDevicePath
);
1064 if (DevicePathSize
== GetDevicePathSize (DriverImageInfo
->DriverImagePath
)) {
1066 DriverImageDevicePath
,
1067 DriverImageInfo
->DriverImagePath
,
1068 GetDevicePathSize (DriverImageInfo
->DriverImagePath
)
1075 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1080 // DriverImageDevicePath is not found in the controller's Driver Image Info List
1082 return EFI_NOT_FOUND
;
1084 if (DriverImageNO
!= NULL
) {
1085 *DriverImageNO
= ImageNO
;
1093 Insert a driver image as a controller's override driver into the mapping database.
1094 The driver image's order number is indicated by DriverImageNO.
1096 @param ControllerDevicePath The controller device path need to add a
1097 override driver image item
1098 @param DriverImageDevicePath The driver image device path need to be insert
1099 @param MappingDataBase Mapping database list entry pointer
1100 @param DriverImageNO The inserted order number. If this number is taken,
1101 the larger available number will be used.
1103 @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or DriverImageDevicePath is NULL
1104 or MappingDataBase is NULL
1105 @retval EFI_ALREADY_STARTED The input Controller to input DriverImage has been
1106 recorded into the mapping database.
1107 @retval EFI_SUCCESS The Controller and DriverImage are inserted into
1108 the mapping database successfully.
1114 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
1115 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath
,
1116 IN LIST_ENTRY
*MappingDataBase
,
1117 IN UINT32 DriverImageNO
1121 LIST_ENTRY
*OverrideItemListIndex
;
1122 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1123 LIST_ENTRY
*ImageInfoListIndex
;
1124 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1127 UINTN DevicePathSize
;
1129 if (ControllerDevicePath
== NULL
) {
1130 return EFI_INVALID_PARAMETER
;
1132 if (DriverImageDevicePath
== NULL
) {
1133 return EFI_INVALID_PARAMETER
;
1135 if (MappingDataBase
== NULL
) {
1136 return EFI_INVALID_PARAMETER
;
1140 // If the driver is already in the controller's Driver Image Info List,
1141 // just return EFI_ALREADY_STARTED.
1143 Status
= CheckMapping (
1144 ControllerDevicePath
,
1145 DriverImageDevicePath
,
1150 if (Status
== EFI_SUCCESS
) {
1151 return EFI_ALREADY_STARTED
;
1155 // Search the input ControllerDevicePath in MappingDataBase
1158 OverrideItem
= NULL
;
1159 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1160 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1161 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1162 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1163 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1165 ControllerDevicePath
,
1166 OverrideItem
->ControllerDevicePath
,
1174 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1177 // If cannot find, this is a new controller item
1178 // Add the Controller related PLATFORM_OVERRIDE_ITEM structrue in mapping data base
1181 OverrideItem
= AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM
));
1182 ASSERT (OverrideItem
!= NULL
);
1183 OverrideItem
->Signature
= PLATFORM_OVERRIDE_ITEM_SIGNATURE
;
1184 OverrideItem
->ControllerDevicePath
= DuplicateDevicePath (ControllerDevicePath
);
1185 InitializeListHead (&OverrideItem
->DriverInfoList
);
1186 InsertTailList (MappingDataBase
, &OverrideItem
->Link
);
1190 // Prepare the driver image related DRIVER_IMAGE_INFO structure.
1192 DriverImageInfo
= AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO
));
1193 ASSERT (DriverImageInfo
!= NULL
);
1194 DriverImageInfo
->Signature
= DRIVER_IMAGE_INFO_SIGNATURE
;
1195 DriverImageInfo
->DriverImagePath
= DuplicateDevicePath (DriverImageDevicePath
);
1197 // Find the driver image wanted order location
1201 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1202 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1203 if (ImageNO
== (DriverImageNO
- 1)) {
1205 // find the wanted order location, insert it
1207 InsertTailList (ImageInfoListIndex
, &DriverImageInfo
->Link
);
1208 OverrideItem
->DriverInfoNum
++;
1213 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1218 // if not find the wantted order location, add it as last item of the controller mapping item
1220 InsertTailList (&OverrideItem
->DriverInfoList
, &DriverImageInfo
->Link
);
1221 OverrideItem
->DriverInfoNum
++;
1229 Delete a controller's override driver from the mapping database.
1231 @param ControllerDevicePath The controller device path will be deleted
1232 when all drivers images on it are removed.
1233 @param DriverImageDevicePath The driver image device path will be delete.
1234 If NULL, all driver image will be delete.
1235 @param MappingDataBase Mapping database list entry pointer
1237 @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or MappingDataBase is NULL
1238 @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or
1239 DriverImageDevicePath is not found in the found DriverImage Info list.
1240 @retval EFI_SUCCESS Delete the specified driver successfully.
1246 IN EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
,
1247 IN EFI_DEVICE_PATH_PROTOCOL
*DriverImageDevicePath
,
1248 IN LIST_ENTRY
*MappingDataBase
1252 LIST_ENTRY
*OverrideItemListIndex
;
1253 PLATFORM_OVERRIDE_ITEM
*OverrideItem
;
1254 LIST_ENTRY
*ImageInfoListIndex
;
1255 DRIVER_IMAGE_INFO
*DriverImageInfo
;
1257 UINTN DevicePathSize
;
1259 if (ControllerDevicePath
== NULL
) {
1260 return EFI_INVALID_PARAMETER
;
1263 if (MappingDataBase
== NULL
) {
1264 return EFI_INVALID_PARAMETER
;
1268 // If ControllerDevicePath is not found in mapping database, return EFI_NOT_FOUND.
1270 Status
= CheckMapping (
1271 ControllerDevicePath
,
1272 DriverImageDevicePath
,
1277 if (EFI_ERROR (Status
)) {
1278 return EFI_NOT_FOUND
;
1282 // Search ControllerDevicePath in MappingDataBase
1285 OverrideItem
= NULL
;
1286 OverrideItemListIndex
= GetFirstNode (MappingDataBase
);
1287 while (!IsNull (MappingDataBase
, OverrideItemListIndex
)) {
1288 OverrideItem
= CR(OverrideItemListIndex
, PLATFORM_OVERRIDE_ITEM
, Link
, PLATFORM_OVERRIDE_ITEM_SIGNATURE
);
1289 DevicePathSize
= GetDevicePathSize (ControllerDevicePath
);
1290 if (DevicePathSize
== GetDevicePathSize (OverrideItem
->ControllerDevicePath
)) {
1292 ControllerDevicePath
,
1293 OverrideItem
->ControllerDevicePath
,
1301 OverrideItemListIndex
= GetNextNode (MappingDataBase
, OverrideItemListIndex
);
1305 ASSERT (OverrideItem
->DriverInfoNum
!= 0);
1308 ImageInfoListIndex
= GetFirstNode (&OverrideItem
->DriverInfoList
);
1309 while (!IsNull (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
)) {
1310 DriverImageInfo
= CR(ImageInfoListIndex
, DRIVER_IMAGE_INFO
, Link
, DRIVER_IMAGE_INFO_SIGNATURE
);
1311 ImageInfoListIndex
= GetNextNode (&OverrideItem
->DriverInfoList
, ImageInfoListIndex
);
1312 if (DriverImageDevicePath
!= NULL
) {
1314 // Search for the specified DriverImageDevicePath and remove it, then break.
1316 DevicePathSize
= GetDevicePathSize (DriverImageDevicePath
);
1317 if (DevicePathSize
== GetDevicePathSize (DriverImageInfo
->DriverImagePath
)) {
1319 DriverImageDevicePath
,
1320 DriverImageInfo
->DriverImagePath
,
1321 GetDevicePathSize (DriverImageInfo
->DriverImagePath
)
1325 FreePool(DriverImageInfo
->DriverImagePath
);
1326 RemoveEntryList (&DriverImageInfo
->Link
);
1327 OverrideItem
->DriverInfoNum
--;
1333 // Remove all existing driver image info entries, so no break here.
1336 FreePool(DriverImageInfo
->DriverImagePath
);
1337 RemoveEntryList (&DriverImageInfo
->Link
);
1338 OverrideItem
->DriverInfoNum
--;
1343 // Confirm all driver image info entries have been removed,
1344 // if DriverImageDevicePath is NULL.
1346 if (DriverImageDevicePath
== NULL
) {
1347 ASSERT (OverrideItem
->DriverInfoNum
== 0);
1350 // If Override Item has no driver image info entry, then delete this item.
1352 if (OverrideItem
->DriverInfoNum
== 0) {
1353 FreePool(OverrideItem
->ControllerDevicePath
);
1354 RemoveEntryList (&OverrideItem
->Link
);
1355 FreePool (OverrideItem
);
1360 // DriverImageDevicePath is not NULL and cannot be found in the controller's
1361 // driver image info list.
1363 return EFI_NOT_FOUND
;
1370 Push a controller device path into a globle device path list.
1372 @param DevicePath The controller device path to push into stack
1374 @retval EFI_SUCCESS Device path successfully pushed into the stack.
1380 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
1383 DEVICE_PATH_STACK_ITEM
*DevicePathStackItem
;
1385 DevicePathStackItem
= AllocateZeroPool (sizeof (DEVICE_PATH_STACK_ITEM
));
1386 ASSERT (DevicePathStackItem
!= NULL
);
1387 DevicePathStackItem
->Signature
= DEVICE_PATH_STACK_ITEM_SIGNATURE
;
1388 DevicePathStackItem
->DevicePath
= DuplicateDevicePath (DevicePath
);
1389 InsertTailList (&mDevicePathStack
, &DevicePathStackItem
->Link
);
1395 Pop a controller device path from a globle device path list
1397 @param DevicePath The controller device path popped from stack
1399 @retval EFI_SUCCESS Controller device path successfully popped.
1400 @retval EFI_NOT_FOUND Stack is empty.
1406 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
1409 DEVICE_PATH_STACK_ITEM
*DevicePathStackItem
;
1410 LIST_ENTRY
*ItemListIndex
;
1412 ItemListIndex
= mDevicePathStack
.BackLink
;
1414 // Check if the stack is empty
1416 if (ItemListIndex
!= &mDevicePathStack
){
1417 DevicePathStackItem
= CR(ItemListIndex
, DEVICE_PATH_STACK_ITEM
, Link
, DEVICE_PATH_STACK_ITEM_SIGNATURE
);
1418 if (DevicePath
!= NULL
) {
1419 *DevicePath
= DuplicateDevicePath (DevicePathStackItem
->DevicePath
);
1421 FreePool (DevicePathStackItem
->DevicePath
);
1422 RemoveEntryList (&DevicePathStackItem
->Link
);
1423 FreePool (DevicePathStackItem
);
1426 return EFI_NOT_FOUND
;
1431 Check whether a controller device path is in a globle device path list
1433 @param DevicePath The controller device path to check
1435 @retval TRUE DevicePath exists in the stack.
1436 @retval FALSE DevicePath does not exist in the stack.
1442 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
1445 DEVICE_PATH_STACK_ITEM
*DevicePathStackItem
;
1446 LIST_ENTRY
*ItemListIndex
;
1447 UINTN DevicePathSize
;
1449 ItemListIndex
= mDevicePathStack
.BackLink
;
1450 while (ItemListIndex
!= &mDevicePathStack
){
1451 DevicePathStackItem
= CR(ItemListIndex
, DEVICE_PATH_STACK_ITEM
, Link
, DEVICE_PATH_STACK_ITEM_SIGNATURE
);
1452 DevicePathSize
= GetDevicePathSize (DevicePath
);
1453 if (DevicePathSize
== GetDevicePathSize (DevicePathStackItem
->DevicePath
)) {
1454 if (CompareMem (DevicePath
, DevicePathStackItem
->DevicePath
, DevicePathSize
) == 0) {
1458 ItemListIndex
= ItemListIndex
->BackLink
;
1466 Update the FV file device path if it is not valid.
1468 According to a file GUID, check a Fv file device path is valid. If it is invalid,
1469 try to return the valid device path.
1470 FV address maybe changes for memory layout adjust from time to time, use this funciton
1471 could promise the Fv file device path is right.
1473 @param DevicePath On input, the FV file device path to check
1474 On output, the updated valid FV file device path
1475 @param FileGuid The FV file GUID
1476 @param CallerImageHandle Image handle of the caller
1478 @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid
1480 @retval EFI_UNSUPPORTED the input DevicePath does not contain FV file
1482 @retval EFI_ALREADY_STARTED the input DevicePath has pointed to FV file, it
1484 @retval EFI_SUCCESS Successfully updated the invalid DevicePath,
1485 and return the updated device path in DevicePath
1490 UpdateFvFileDevicePath (
1491 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
1492 IN EFI_GUID
*FileGuid
,
1493 IN EFI_HANDLE CallerImageHandle
1496 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1497 EFI_DEVICE_PATH_PROTOCOL
*LastDeviceNode
;
1499 EFI_GUID
*GuidPoint
;
1501 UINTN FvHandleCount
;
1502 EFI_HANDLE
*FvHandleBuffer
;
1503 EFI_FV_FILETYPE Type
;
1505 EFI_FV_FILE_ATTRIBUTES Attributes
;
1506 UINT32 AuthenticationStatus
;
1508 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
1509 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
1510 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode
;
1511 EFI_HANDLE FoundFvHandle
;
1512 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
1515 if (DevicePath
== NULL
) {
1516 return EFI_INVALID_PARAMETER
;
1519 if (*DevicePath
== NULL
) {
1520 return EFI_INVALID_PARAMETER
;
1524 // Check whether the device path points to the default the input FV file
1526 TempDevicePath
= *DevicePath
;
1527 LastDeviceNode
= TempDevicePath
;
1528 while (!IsDevicePathEnd (TempDevicePath
)) {
1529 LastDeviceNode
= TempDevicePath
;
1530 TempDevicePath
= NextDevicePathNode (TempDevicePath
);
1532 GuidPoint
= EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) LastDeviceNode
);
1533 if (GuidPoint
== NULL
) {
1535 // If this option does not point to a FV file, just return EFI_UNSUPPORTED.
1537 return EFI_UNSUPPORTED
;
1540 if (FileGuid
!= NULL
) {
1541 if (!CompareGuid (GuidPoint
, FileGuid
)) {
1543 // If the FV file is not the input file GUID, just return EFI_UNSUPPORTED
1545 return EFI_UNSUPPORTED
;
1548 FileGuid
= GuidPoint
;
1552 // Check to see if the device path contains memory map node
1554 TempDevicePath
= *DevicePath
;
1556 while (!IsDevicePathEnd (TempDevicePath
)) {
1558 // Use old Device Path
1560 if (DevicePathType (TempDevicePath
) == HARDWARE_DEVICE_PATH
&&
1561 DevicePathSubType (TempDevicePath
) == HW_MEMMAP_DP
) {
1565 TempDevicePath
= NextDevicePathNode (TempDevicePath
);
1569 return EFI_UNSUPPORTED
;
1573 // Check whether the input Fv file device path is valid
1575 TempDevicePath
= *DevicePath
;
1576 FoundFvHandle
= NULL
;
1577 Status
= gBS
->LocateDevicePath (
1578 &gEfiFirmwareVolume2ProtocolGuid
,
1582 if (!EFI_ERROR (Status
)) {
1583 Status
= gBS
->HandleProtocol (
1585 &gEfiFirmwareVolume2ProtocolGuid
,
1588 if (!EFI_ERROR (Status
)) {
1590 // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there
1592 Status
= Fv
->ReadFile (
1599 &AuthenticationStatus
1601 if (!EFI_ERROR (Status
)) {
1602 return EFI_ALREADY_STARTED
;
1608 // Look for the input wanted FV file in current FV
1609 // First, try to look for in Caller own FV. Caller and input wanted FV file usually are in the same FV
1612 FoundFvHandle
= NULL
;
1613 Status
= gBS
->HandleProtocol (
1615 &gEfiLoadedImageProtocolGuid
,
1616 (VOID
**) &LoadedImage
1618 if (!EFI_ERROR (Status
)) {
1619 Status
= gBS
->HandleProtocol (
1620 LoadedImage
->DeviceHandle
,
1621 &gEfiFirmwareVolume2ProtocolGuid
,
1624 if (!EFI_ERROR (Status
)) {
1625 Status
= Fv
->ReadFile (
1632 &AuthenticationStatus
1634 if (!EFI_ERROR (Status
)) {
1636 FoundFvHandle
= LoadedImage
->DeviceHandle
;
1641 // Second, if fail to find, try to enumerate all FV
1644 gBS
->LocateHandleBuffer (
1646 &gEfiFirmwareVolume2ProtocolGuid
,
1651 for (Index
= 0; Index
< FvHandleCount
; Index
++) {
1652 gBS
->HandleProtocol (
1653 FvHandleBuffer
[Index
],
1654 &gEfiFirmwareVolume2ProtocolGuid
,
1658 Status
= Fv
->ReadFile (
1665 &AuthenticationStatus
1667 if (EFI_ERROR (Status
)) {
1669 // Skip if input Fv file not in the FV
1674 FoundFvHandle
= FvHandleBuffer
[Index
];
1681 // Build the shell device path
1683 NewDevicePath
= DevicePathFromHandle (FoundFvHandle
);
1684 EfiInitializeFwVolDevicepathNode (&FvFileNode
, FileGuid
);
1685 NewDevicePath
= AppendDevicePathNode (NewDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) &FvFileNode
);
1686 *DevicePath
= NewDevicePath
;
1689 return EFI_NOT_FOUND
;
1694 Gets the data and size of a variable.
1696 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1697 buffer, and the size of the buffer. If failure return NULL.
1699 @param Name String part of EFI variable name
1700 @param VendorGuid GUID part of EFI variable name
1701 @param VariableSize Returns the size of the EFI variable that was
1704 @return Dynamically allocated memory that contains a copy of the EFI variable.
1705 Caller is responsible freeing the buffer.
1706 @retval NULL Variable was not read
1711 GetVariableAndSize (
1713 IN EFI_GUID
*VendorGuid
,
1714 OUT UINTN
*VariableSize
1724 // Pass in a zero size buffer to find the required buffer size.
1727 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1728 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1730 // Allocate the buffer to return
1732 Buffer
= AllocateZeroPool (BufferSize
);
1733 if (Buffer
== NULL
) {
1737 // Read variable into the allocated buffer.
1739 Status
= gRT
->GetVariable (Name
, VendorGuid
, NULL
, &BufferSize
, Buffer
);
1740 if (EFI_ERROR (Status
)) {
1745 *VariableSize
= BufferSize
;
1751 Connect to the handle to a device on the device path.
1753 This function will create all handles associate with every device
1754 path node. If the handle associate with one device path node can not
1755 be created success, then still give one chance to do the dispatch,
1756 which load the missing drivers if possible.
1758 @param DevicePathToConnect The device path which will be connected, it can
1759 be a multi-instance device path
1761 @retval EFI_SUCCESS All handles associate with every device path
1762 node have been created
1763 @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles
1764 @retval EFI_NOT_FOUND Create the handle associate with one device
1771 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePathToConnect
1775 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1776 EFI_DEVICE_PATH_PROTOCOL
*CopyOfDevicePath
;
1777 EFI_DEVICE_PATH_PROTOCOL
*Instance
;
1778 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
1779 EFI_DEVICE_PATH_PROTOCOL
*Next
;
1781 EFI_HANDLE PreviousHandle
;
1784 if (DevicePathToConnect
== NULL
) {
1788 DevicePath
= DuplicateDevicePath (DevicePathToConnect
);
1789 CopyOfDevicePath
= DevicePath
;
1790 if (DevicePath
== NULL
) {
1791 return EFI_OUT_OF_RESOURCES
;
1796 // The outer loop handles multi instance device paths.
1797 // Only console variables contain multiple instance device paths.
1799 // After this call DevicePath points to the next Instance
1801 Instance
= GetNextDevicePathInstance (&DevicePath
, &Size
);
1802 ASSERT (Instance
!= NULL
);
1805 while (!IsDevicePathEndType (Next
)) {
1806 Next
= NextDevicePathNode (Next
);
1809 SetDevicePathEndNode (Next
);
1812 // Start the real work of connect with RemainingDevicePath
1814 PreviousHandle
= NULL
;
1817 // Find the handle that best matches the Device Path. If it is only a
1818 // partial match the remaining part of the device path is returned in
1819 // RemainingDevicePath.
1821 RemainingDevicePath
= Instance
;
1822 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingDevicePath
, &Handle
);
1824 if (!EFI_ERROR (Status
)) {
1825 if (Handle
== PreviousHandle
) {
1827 // If no forward progress is made try invoking the Dispatcher.
1828 // A new FV may have been added to the system an new drivers
1829 // may now be found.
1830 // Status == EFI_SUCCESS means a driver was dispatched
1831 // Status == EFI_NOT_FOUND means no new drivers were dispatched
1833 Status
= gDS
->Dispatch ();
1836 if (!EFI_ERROR (Status
)) {
1837 PreviousHandle
= Handle
;
1839 // Connect all drivers that apply to Handle and RemainingDevicePath,
1840 // the Recursive flag is FALSE so only one level will be expanded.
1842 // Do not check the connect status here, if the connect controller fail,
1843 // then still give the chance to do dispatch, because partial
1844 // RemainingDevicepath may be in the new FV
1846 // 1. If the connect fails, RemainingDevicepath and handle will not
1847 // change, so next time will do the dispatch, then dispatch's status
1849 // 2. If the connect succeeds, the RemainingDevicepath and handle will
1850 // change, then avoid the dispatch, we have chance to continue the
1853 gBS
->ConnectController (Handle
, NULL
, RemainingDevicePath
, FALSE
);
1857 // Loop until RemainingDevicePath is an empty device path
1859 } while (!EFI_ERROR (Status
) && !IsDevicePathEnd (RemainingDevicePath
));
1861 } while (DevicePath
!= NULL
);
1863 if (CopyOfDevicePath
!= NULL
) {
1864 FreePool (CopyOfDevicePath
);
1867 // All handle with DevicePath exists in the handle database