summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg/Universal/PlatformDriOverrideDxe
diff options
context:
space:
mode:
authorlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>2009-04-24 07:02:52 +0000
committerlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>2009-04-24 07:02:52 +0000
commit6d8ced29b1486afd2e96a31c96474545cba30c7f (patch)
treec02b296eecba16a952f862dfa7a3789aa290b483 /MdeModulePkg/Universal/PlatformDriOverrideDxe
parent59f1d89250eceead2c0e33babe670a938a6a115c (diff)
downloadedk2-6d8ced29b1486afd2e96a31c96474545cba30c7f.tar.gz
edk2-6d8ced29b1486afd2e96a31c96474545cba30c7f.tar.bz2
edk2-6d8ced29b1486afd2e96a31c96474545cba30c7f.zip
Merge application PlatOverMngr and library DxePlatDriOverLib into driver PlatDriOverrideDxe.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8169 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Universal/PlatformDriOverrideDxe')
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/InternalPlatDriOverrideDxe.h218
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c1667
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideLib.c1898
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatOverMngr.h73
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverride.c212
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf74
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/Vfr.vfr109
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/VfrStrings.unibin0 -> 10032 bytes
8 files changed, 4027 insertions, 224 deletions
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/InternalPlatDriOverrideDxe.h b/MdeModulePkg/Universal/PlatformDriOverrideDxe/InternalPlatDriOverrideDxe.h
new file mode 100644
index 0000000000..efd87e91e7
--- /dev/null
+++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/InternalPlatDriOverrideDxe.h
@@ -0,0 +1,218 @@
+/** @file
+ Ihe internal heder file includes the required Protocol/Guid/Library
+ and the shared function APIs.
+
+Copyright (c) 2007 - 2009, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _INTERNAL_PLATFORM_DRIVER_OVERRIDE_H_
+#define _INTERNAL_PLATFORM_DRIVER_OVERRIDE_H_
+
+#include <PiDxe.h>
+
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/FormBrowser2.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/BusSpecificDriverOverride.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/ComponentName.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PlatformDriverOverride.h>
+#include <Guid/MdeModuleHii.h>
+#include <Guid/VariableFormat.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/HiiLib.h>
+
+/**
+ Free all the mapping database memory resource and initialize the mapping list entry.
+
+ @param MappingDataBase Mapping database list entry pointer
+
+ @retval EFI_INVALID_PARAMETER mapping database list entry is NULL
+ @retval EFI_SUCCESS Free success
+
+**/
+EFI_STATUS
+EFIAPI
+FreeMappingDatabase (
+ IN OUT LIST_ENTRY *MappingDataBase
+ )
+;
+
+/**
+ Read the NV environment variable(s) that contain the override mappings from Controller Device Path to
+ a set of Driver Device Paths, and create the mapping database in memory to contain these variable info.
+
+ @param MappingDataBase Mapping database list entry pointer
+
+ @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null
+ @retval EFI_NOT_FOUND Cannot find the 'PlatDriOver' NV variable
+ @retval EFI_VOLUME_CORRUPTED The found NV variable is corrupted
+ @retval EFI_SUCCESS Create the mapping database in memory successfully
+
+**/
+EFI_STATUS
+EFIAPI
+InitOverridesMapping (
+ OUT LIST_ENTRY *MappingDataBase
+ )
+;
+
+/**
+ Save the memory mapping database into NV environment variable(s).
+ If MappingDataBase list is empty, then delete all platform override NV variables.
+
+ @param MappingDataBase Mapping database list entry pointer
+
+ @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null
+ @retval EFI_SUCCESS Save memory mapping database successfully
+
+**/
+EFI_STATUS
+EFIAPI
+SaveOverridesMapping (
+ IN LIST_ENTRY *MappingDataBase
+ )
+;
+
+/**
+ Retrieves the image handle of the platform override driver for a controller in the system from the memory mapping database.
+
+ @param ControllerHandle The device handle of the controller to check if
+ a driver override exists.
+ @param DriverImageHandle On output, a pointer to the next driver handle.
+ Passing in a pointer to NULL, will return the
+ first driver handle for ControllerHandle.
+ @param MappingDataBase MappingDataBase - Mapping database list entry
+ pointer
+ @param CallerImageHandle The caller driver's image handle, for
+ UpdateFvFileDevicePath use.
+
+ @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not
+ a valid handle. Or DriverImagePath is not a
+ device path that was returned on a previous call
+ to GetDriverPath().
+ @retval EFI_NOT_FOUND A driver override for ControllerHandle was not
+ found.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SUCCESS The driver override for ControllerHandle was
+ returned in DriverImagePath.
+
+**/
+EFI_STATUS
+EFIAPI
+GetDriverFromMapping (
+ IN EFI_HANDLE ControllerHandle,
+ IN OUT EFI_HANDLE *DriverImageHandle,
+ IN LIST_ENTRY *MappingDataBase,
+ IN EFI_HANDLE CallerImageHandle
+ )
+;
+
+/**
+ Check mapping database whether already has the mapping info which
+ records the input Controller to input DriverImage.
+
+ @param ControllerDevicePath The controller device path is to be check.
+ @param DriverImageDevicePath The driver image device path is to be check.
+ @param MappingDataBase Mapping database list entry pointer
+ @param DriverInfoNum the controller's total override driver number
+ @param DriverImageNO The driver order number for the input DriverImage.
+ If the DriverImageDevicePath is NULL, DriverImageNO is not set.
+
+ @retval EFI_INVALID_PARAMETER ControllerDevicePath or MappingDataBase is NULL.
+ @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or
+ DriverImageDevicePath is not found in the found DriverImage Info list.
+ @retval EFI_SUCCESS The controller's total override driver number and
+ input DriverImage's order number is correctly return.
+**/
+EFI_STATUS
+EFIAPI
+CheckMapping (
+ IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath OPTIONAL,
+ IN LIST_ENTRY *MappingDataBase,
+ OUT UINT32 *DriverInfoNum OPTIONAL,
+ OUT UINT32 *DriverImageNO OPTIONAL
+ )
+;
+
+/**
+ Insert a driver image as a controller's override driver into the mapping database.
+ The driver image's order number is indicated by DriverImageNO.
+
+ @param ControllerDevicePath The controller device path need to add a
+ override driver image item
+ @param DriverImageDevicePath The driver image device path need to be insert
+ @param MappingDataBase Mapping database list entry pointer
+ @param DriverImageNO The inserted order number. If this number is taken,
+ the larger available number will be used.
+
+ @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or DriverImageDevicePath is NULL
+ or MappingDataBase is NULL
+ @retval EFI_ALREADY_STARTED The input Controller to input DriverImage has been
+ recorded into the mapping database.
+ @retval EFI_SUCCESS The Controller and DriverImage are inserted into
+ the mapping database successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+InsertDriverImage (
+ IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath,
+ IN LIST_ENTRY *MappingDataBase,
+ IN UINT32 DriverImageNO
+ )
+;
+
+/**
+ Delete a controller's override driver from the mapping database.
+
+ @param ControllerDevicePath The controller device path will be deleted
+ when all drivers images on it are removed.
+ @param DriverImageDevicePath The driver image device path will be delete.
+ If NULL, all driver image will be delete.
+ @param MappingDataBase Mapping database list entry pointer
+
+ @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or MappingDataBase is NULL
+ @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or
+ DriverImageDevicePath is not found in the found DriverImage Info list.
+ @retval EFI_SUCCESS Delete the specified driver successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+DeleteDriverImage (
+ IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath,
+ IN LIST_ENTRY *MappingDataBase
+ )
+;
+
+#endif
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c
new file mode 100644
index 0000000000..47921cd43b
--- /dev/null
+++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c
@@ -0,0 +1,1667 @@
+/** @file
+ This file also installs UEFI PLATFORM_DRIVER_OVERRIDE_PROTOCOL.
+
+ The main code offers a UI interface in device manager to let user configure
+ platform override protocol to override the default algorithm for matching
+ drivers to controllers.
+
+ The main flow:
+ 1. It dynamicly locate all controller device path.
+ 2. It dynamicly locate all drivers which support binding protocol.
+ 3. It export and dynamicly update two menu to let user select the
+ mapping between drivers to controllers.
+ 4. It save all the mapping info in NV variables which will be consumed
+ by platform override protocol driver to publish the platform override protocol.
+
+Copyright (c) 2007 - 2009, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "InternalPlatDriOverrideDxe.h"
+#include "PlatOverMngr.h"
+
+#define EFI_CALLBACK_INFO_SIGNATURE SIGNATURE_32 ('C', 'l', 'b', 'k')
+#define EFI_CALLBACK_INFO_FROM_THIS(a) CR (a, EFI_CALLBACK_INFO, ConfigAccess, EFI_CALLBACK_INFO_SIGNATURE)
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE RegisteredHandle;
+ PLAT_OVER_MNGR_DATA FakeNvData;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
+ EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL PlatformDriverOverride;
+} EFI_CALLBACK_INFO;
+
+#pragma pack(1)
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} HII_VENDOR_DEVICE_PATH;
+
+#pragma pack()
+
+//
+// uni string and Vfr Binary data.
+//
+extern UINT8 VfrBin[];
+extern UINT8 PlatDriOverrideDxeStrings[];
+
+//
+// module global data
+//
+EFI_GUID mPlatformOverridesManagerGuid = PLAT_OVER_MNGR_GUID;
+CHAR16 mVariableName[] = L"Data";
+LIST_ENTRY mMappingDataBase = INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase);
+BOOLEAN mEnvironmentVariableRead = FALSE;
+EFI_HANDLE mCallerImageHandle = NULL;
+
+EFI_HANDLE *mDevicePathHandleBuffer;
+EFI_HANDLE *mDriverImageHandleBuffer;
+
+INTN mSelectedCtrIndex;
+EFI_STRING_ID mControllerToken[MAX_CHOICE_NUM];
+UINTN mDriverImageHandleCount;
+EFI_STRING_ID mDriverImageToken[MAX_CHOICE_NUM];
+EFI_STRING_ID mDriverImageFilePathToken[MAX_CHOICE_NUM];
+EFI_LOADED_IMAGE_PROTOCOL *mDriverImageProtocol[MAX_CHOICE_NUM];
+EFI_DEVICE_PATH_PROTOCOL *mControllerDevicePathProtocol[MAX_CHOICE_NUM];
+UINTN mSelectedDriverImageNum;
+UINTN mLastSavedDriverImageNum;
+UINT16 mCurrentPage;
+EFI_CALLBACK_INFO *mCallbackInfo;
+
+HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ EFI_CALLER_ID_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8) (END_DEVICE_PATH_LENGTH),
+ (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+/**
+ Converting a given device to an unicode string.
+
+ This function will dependent on gEfiDevicePathToTextProtocolGuid, if protocol
+ does not installed, then return unknown device path L"?" directly.
+
+ @param DevPath Given device path instance
+
+ @return Converted string from given device path.
+ @retval L"?" Can not locate gEfiDevicePathToTextProtocolGuid protocol for converting.
+**/
+CHAR16 *
+DevicePathToStr (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
+ CHAR16 *ToText;
+
+ if (DevPath == NULL) {
+ return L"";
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiDevicePathToTextProtocolGuid,
+ NULL,
+ (VOID **) &DevPathToText
+ );
+ if (!EFI_ERROR (Status)) {
+ ToText = DevPathToText->ConvertDevicePathToText (
+ DevPath,
+ FALSE,
+ TRUE
+ );
+ ASSERT (ToText != NULL);
+ return ToText;
+ }
+
+ return L"?";
+}
+
+/**
+ Worker function to get the driver name by ComponentName or ComponentName2 protocol
+ according to the driver binding handle.
+
+ @param DriverBindingHandle The Handle of DriverBinding.
+ @param ProtocolGuid The pointer to Component Name (2) protocol GUID.
+ @param VariableName The name of the RFC 4646 or ISO 639-2 language variable.
+
+ @retval !NULL Pointer into the image name if the image name is found,
+ @retval NULL Pointer to NULL if the image name is not found.
+
+**/
+CHAR16 *
+GetComponentNameWorker (
+ IN EFI_HANDLE DriverBindingHandle,
+ IN EFI_GUID *ProtocolGuid,
+ IN CONST CHAR16 *VariableName
+ )
+{
+ EFI_STATUS Status;
+ EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
+ CHAR16 *DriverName;
+ CHAR8 *Language;
+ CHAR8 *BestLanguage;
+
+ Status = gBS->OpenProtocol (
+ DriverBindingHandle,
+ ProtocolGuid,
+ (VOID *) &ComponentName,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ //
+ // Find the best matching language.
+ //
+ Language = GetEfiGlobalVariable (VariableName);
+ BestLanguage = GetBestLanguage (
+ ComponentName->SupportedLanguages,
+ (BOOLEAN) (ProtocolGuid == &gEfiComponentNameProtocolGuid),
+ Language,
+ NULL
+ );
+
+ DriverName = NULL;
+ if (BestLanguage != NULL) {
+ ComponentName->GetDriverName (
+ ComponentName,
+ BestLanguage,
+ &DriverName
+ );
+ FreePool (BestLanguage);
+ }
+
+ if (Language != NULL) {
+ FreePool (Language);
+ }
+
+ return DriverName;
+}
+
+
+/**
+ Get the driver name by ComponentName or ComponentName2 protocol
+ according to the driver binding handle
+
+ @param DriverBindingHandle The Handle of DriverBinding.
+
+ @retval !NULL Pointer into the image name if the image name is found,
+ @retval NULL Pointer to NULL if the image name is not found.
+
+**/
+CHAR16 *
+GetComponentName (
+ IN EFI_HANDLE DriverBindingHandle
+ )
+{
+ CHAR16 *DriverName;
+
+ //
+ // Try RFC 4646 Component Name 2 protocol first.
+ //
+ DriverName = GetComponentNameWorker (DriverBindingHandle, &gEfiComponentName2ProtocolGuid, L"PlatformLang");
+ if (DriverName == NULL) {
+ //
+ // If we can not get driver name from Component Name 2 protocol, we can try ISO 639-2 Component Name protocol.
+ //
+ DriverName = GetComponentNameWorker (DriverBindingHandle, &gEfiComponentNameProtocolGuid, L"Lang");
+ }
+
+ return DriverName;
+}
+
+/**
+ Get the image name from EFI UI section.
+ Get FV protocol by its loaded image protocol to abstract EFI UI section.
+
+ @param Image Pointer to the loaded image protocol
+
+ @retval !NULL Pointer to the image name if the image name is found,
+ @retval NULL NULL if the image name is not found.
+
+**/
+CHAR16 *
+GetImageName (
+ IN EFI_LOADED_IMAGE_PROTOCOL *Image
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
+ EFI_DEVICE_PATH_PROTOCOL *AlignedDevPathNode;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;
+ VOID *Buffer;
+ UINTN BufferSize;
+ UINT32 AuthenticationStatus;
+ EFI_GUID *NameGuid;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2;
+
+ Fv2 = NULL;
+ Buffer = NULL;
+ BufferSize = 0;
+
+ if (Image->FilePath == NULL) {
+ return NULL;
+ }
+ DevPathNode = Image->FilePath;
+
+ while (!IsDevicePathEnd (DevPathNode)) {
+ //
+ // Make sure device path node is aligned when accessing it's FV Name Guid field.
+ //
+ AlignedDevPathNode = AllocateCopyPool (DevicePathNodeLength(DevPathNode), DevPathNode);
+
+ //
+ // Find the Fv File path
+ //
+ NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)AlignedDevPathNode);
+ if (NameGuid != NULL) {
+ FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) AlignedDevPathNode;
+ Status = gBS->HandleProtocol (
+ Image->DeviceHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &Fv2
+ );
+ //
+ // Locate Image EFI UI section to get the image name.
+ //
+ if (!EFI_ERROR (Status)) {
+ Status = Fv2->ReadSection (
+ Fv2,
+ &FvFilePath->FvFileName,
+ EFI_SECTION_USER_INTERFACE,
+ 0,
+ &Buffer,
+ &BufferSize,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ FreePool (AlignedDevPathNode);
+ break;
+ }
+ Buffer = NULL;
+ }
+ }
+
+ FreePool (AlignedDevPathNode);
+
+ //
+ // Next device path node
+ //
+ DevPathNode = NextDevicePathNode (DevPathNode);
+ }
+
+ return Buffer;
+}
+
+/**
+ Prepare the first page to let user select the device controller which need to
+ add mapping drivers if user select 'Refresh' in first page.
+ During first page, user will see all currnet controller device path in system,
+ select any device path will go to second page to select its overrides drivers.
+
+ @param Private Pointer to EFI_CALLBACK_INFO.
+ @param KeyValue The callback key value of device controller item in first page.
+ @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
+
+ @retval EFI_SUCCESS Always returned.
+
+**/
+EFI_STATUS
+UpdateDeviceSelectPage (
+ IN EFI_CALLBACK_INFO *Private,
+ IN UINT16 KeyValue,
+ IN PLAT_OVER_MNGR_DATA *FakeNvData
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN DevicePathHandleCount;
+ CHAR16 *NewString;
+ EFI_STRING_ID NewStringToken;
+ CHAR16 *ControllerName;
+ EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;
+ UINTN Len;
+ VOID *StartOpCodeHandle;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ EFI_IFR_GUID_LABEL *EndLabel;
+
+ //
+ // Set current page form ID.
+ //
+ mCurrentPage = FORM_ID_DEVICE;
+
+ //
+ // Initial the mapping database in memory
+ //
+ FreeMappingDatabase (&mMappingDataBase);
+ InitOverridesMapping (&mMappingDataBase);
+
+ //
+ // Init OpCode Handle
+ //
+ StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (StartOpCodeHandle != NULL);
+
+ EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (EndOpCodeHandle != NULL);
+
+ //
+ // Create Hii Extend Label OpCode as the start opcode
+ //
+ StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ StartLabel->Number = FORM_ID_DEVICE;
+
+ //
+ // Create Hii Extend Label OpCode as the end opcode
+ //
+ EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ EndLabel->Number = LABEL_END;
+
+ //
+ // Clear first page form
+ //
+ HiiUpdateForm (
+ Private->RegisteredHandle,
+ &mPlatformOverridesManagerGuid,
+ FORM_ID_DEVICE,
+ StartOpCodeHandle, // Label FORM_ID_DEVICE
+ EndOpCodeHandle // LABEL_END
+ );
+
+ //
+ // When user enter the page at first time, the 'first refresh' string is given to notify user to refresh all the drivers,
+ // then the 'first refresh' string will be replaced by the 'refresh' string, and the two strings content are same after the replacement
+ //
+ NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH);
+ NewString = HiiGetString (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH), NULL);
+ ASSERT (NewString != NULL);
+ if (HiiSetString (Private->RegisteredHandle, NewStringToken, NewString, NULL) == 0) {
+ ASSERT (FALSE);
+ }
+ FreePool (NewString);
+
+ NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH_HELP);
+ NewString = HiiGetString (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH_HELP), NULL);
+ ASSERT (NewString != NULL);
+ if (HiiSetString (Private->RegisteredHandle, NewStringToken, NewString, NULL) == 0) {
+ ASSERT (FALSE);
+ }
+ FreePool (NewString);
+
+ //
+ // created needed controller device item in first page
+ //
+ DevicePathHandleCount = 0;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ &DevicePathHandleCount,
+ &mDevicePathHandleBuffer
+ );
+ if (EFI_ERROR (Status) || (DevicePathHandleCount == 0)) {
+ return EFI_SUCCESS;
+ }
+
+ for (Index = 0; Index < DevicePathHandleCount; Index++) {
+ if (FakeNvData->PciDeviceFilter == 0x01) {
+ //
+ // Only care PCI device which contain efi driver in its option rom.
+ //
+
+ //
+ // Check whether it is a pci device
+ //
+ ControllerDevicePath = NULL;
+ Status = gBS->OpenProtocol (
+ mDevicePathHandleBuffer[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ //
+ // Check whether it contain efi driver in its option rom
+ //
+ Status = gBS->HandleProtocol(
+ mDevicePathHandleBuffer[Index],
+ &gEfiBusSpecificDriverOverrideProtocolGuid,
+ (VOID **) &BusSpecificDriverOverride
+ );
+ if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) {
+ continue;
+ }
+ }
+
+ ControllerDevicePath = NULL;
+ Status = gBS->OpenProtocol (
+ mDevicePathHandleBuffer[Index],
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ControllerDevicePath,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Save the device path protocol interface
+ //
+ mControllerDevicePathProtocol[Index] = ControllerDevicePath;
+
+ //
+ // Get the driver name
+ //
+ ControllerName = DevicePathToStr (ControllerDevicePath);
+
+ //
+ // Export the driver name string and create item in set options page
+ //
+ Len = StrSize (ControllerName);
+ NewString = AllocateZeroPool (Len + StrSize (L"--"));
+ ASSERT (NewString != NULL);
+ if (EFI_ERROR (CheckMapping (ControllerDevicePath,NULL, &mMappingDataBase, NULL, NULL))) {
+ StrCat (NewString, L"--");
+ } else {
+ StrCat (NewString, L"**");
+ }
+ StrCat (NewString, ControllerName);
+
+ NewStringToken = HiiSetString (Private->RegisteredHandle, mControllerToken[Index], NewString, NULL);
+ ASSERT (NewStringToken != 0);
+ FreePool (NewString);
+ //
+ // Save the device path string toke for next access use
+ //
+ mControllerToken[Index] = NewStringToken;
+
+ HiiCreateGotoOpCode (
+ StartOpCodeHandle,
+ FORM_ID_DRIVER,
+ NewStringToken,
+ STRING_TOKEN (STR_GOTO_HELP_DRIVER),
+ EFI_IFR_FLAG_CALLBACK,
+ (UINT16) (Index + KEY_VALUE_DEVICE_OFFSET)
+ );
+ }
+
+ //
+ // Update first page form
+ //
+ HiiUpdateForm (
+ Private->RegisteredHandle,
+ &mPlatformOverridesManagerGuid,
+ FORM_ID_DEVICE,
+ StartOpCodeHandle, // Label FORM_ID_DEVICE
+ EndOpCodeHandle // LABEL_END
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the first Driver Binding handle which has the specific image handle.
+
+ @param ImageHandle The Image handle
+
+ @return Handle to Driver binding
+ @retval NULL The paramter is not valid or the driver binding handle is not found.
+
+**/
+EFI_HANDLE
+GetDriverBindingHandleFromImageHandle (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN DriverBindingHandleCount;
+ EFI_HANDLE *DriverBindingHandleBuffer;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBindingInterface;
+ EFI_HANDLE DriverBindingHandle;
+
+ DriverBindingHandle = NULL;
+
+ if (ImageHandle == NULL) {
+ return NULL;
+ }
+ //
+ // Get all drivers which support driver binding protocol
+ //
+ DriverBindingHandleCount = 0;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiDriverBindingProtocolGuid,
+ NULL,
+ &DriverBindingHandleCount,
+ &DriverBindingHandleBuffer
+ );
+ if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
+ return NULL;
+ }
+
+ //
+ // Get the first Driver Binding handle which has the specific image handle.
+ //
+ for (Index = 0; Index < DriverBindingHandleCount; Index++) {
+ DriverBindingInterface = NULL;
+ Status = gBS->OpenProtocol (
+ DriverBindingHandleBuffer[Index],
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **) &DriverBindingInterface,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (DriverBindingInterface->ImageHandle == ImageHandle) {
+ DriverBindingHandle = DriverBindingHandleBuffer[Index];
+ break;
+ }
+ }
+
+ FreePool (DriverBindingHandleBuffer);
+ return DriverBindingHandle;
+}
+
+/**
+ Prepare to let user select the drivers which need mapping with the device controller
+ selected in first page.
+
+ @param Private Pointer to EFI_CALLBACK_INFO.
+ @param KeyValue The callback key value of device controller item in first page.
+ KeyValue is larger than or equal to KEY_VALUE_DEVICE_OFFSET.
+ @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
+
+ @retval EFI_SUCCESS Always returned.
+
+**/
+EFI_STATUS
+UpdateBindingDriverSelectPage (
+ IN EFI_CALLBACK_INFO *Private,
+ IN UINT16 KeyValue,
+ IN PLAT_OVER_MNGR_DATA *FakeNvData
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ CHAR16 *NewString;
+ EFI_STRING_ID NewStringToken;
+ EFI_STRING_ID NewStringHelpToken;
+ UINTN DriverImageHandleCount;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ CHAR16 *DriverName;
+ BOOLEAN FreeDriverName;
+ EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;
+ EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;
+ EFI_HANDLE DriverBindingHandle;
+ VOID *StartOpCodeHandle;
+ VOID *EndOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ EFI_IFR_GUID_LABEL *EndLabel;
+
+ //
+ // If user select a controller item in the first page the following code will be run.
+ // During second page, user will see all currnet driver bind protocol driver, the driver name and its device path will be shown
+ //
+ //First acquire the list of Loaded Image Protocols, and then when want the name of the driver, look up all the Driver Binding Protocols
+ // and find the first one whose ImageHandle field matches the image handle of the Loaded Image Protocol.
+ // then use the Component Name Protocol on the same handle as the first matching Driver Binding Protocol to look up the name of the driver.
+ //
+
+ mCurrentPage = FORM_ID_DRIVER;
+ //
+ // Switch the item callback key value to its NO. in mDevicePathHandleBuffer
+ //
+ mSelectedCtrIndex = KeyValue - KEY_VALUE_DEVICE_OFFSET;
+ ASSERT (mSelectedCtrIndex < MAX_CHOICE_NUM);
+
+ mLastSavedDriverImageNum = 0;
+
+ //
+ // Init OpCode Handle
+ //
+ StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (StartOpCodeHandle != NULL);
+
+ EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (EndOpCodeHandle != NULL);
+
+ //
+ // Create Hii Extend Label OpCode as the start opcode
+ //
+ StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ StartLabel->Number = FORM_ID_DRIVER;
+
+ //
+ // Create Hii Extend Label OpCode as the end opcode
+ //
+ EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ EndLabel->Number = LABEL_END;
+
+ //
+ // Clear second page form
+ //
+ HiiUpdateForm (
+ Private->RegisteredHandle,
+ &mPlatformOverridesManagerGuid,
+ FORM_ID_DRIVER,
+ StartOpCodeHandle,
+ EndOpCodeHandle
+ );
+
+ //
+ // Show all driver which support loaded image protocol in second page
+ //
+ DriverImageHandleCount = 0;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiLoadedImageProtocolGuid,
+ NULL,
+ &DriverImageHandleCount,
+ &mDriverImageHandleBuffer
+ );
+ if (EFI_ERROR (Status) || (DriverImageHandleCount == 0)) {
+ return EFI_NOT_FOUND;
+ }
+
+ mDriverImageHandleCount = DriverImageHandleCount;
+ for (Index = 0; Index < DriverImageHandleCount; Index++) {
+ //
+ // Step1: Get the driver image total file path for help string and the driver name.
+ //
+
+ //
+ // Find driver's Loaded Image protocol
+ //
+ LoadedImage =NULL;
+
+ Status = gBS->OpenProtocol (
+ mDriverImageHandleBuffer[Index],
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ FakeNvData->DriSelection[Index] = 0x00;
+ continue;
+ }
+ mDriverImageProtocol[Index] = LoadedImage;
+ //
+ // Find its related driver binding protocol
+ //
+ DriverBindingHandle = GetDriverBindingHandleFromImageHandle (mDriverImageHandleBuffer[Index]);
+ if (DriverBindingHandle == NULL) {
+ FakeNvData->DriSelection[Index] = 0x00;
+ continue;
+ }
+
+ //
+ // Get the EFI Loaded Image Device Path Protocol
+ //
+ LoadedImageDevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ mDriverImageHandleBuffer[Index],
+ &gEfiLoadedImageDevicePathProtocolGuid,
+ (VOID **) &LoadedImageDevicePath
+ );
+ if (LoadedImageDevicePath == NULL) {
+ FakeNvData->DriSelection[Index] = 0x00;
+ continue;
+ }
+
+ if (FakeNvData->PciDeviceFilter == 0x01) {
+ //
+ // only care the driver which is in a Pci device option rom,
+ // and the driver's LoadedImage->DeviceHandle must point to a pci device which has efi option rom
+ //
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->HandleProtocol(
+ LoadedImage->DeviceHandle,
+ &gEfiBusSpecificDriverOverrideProtocolGuid,
+ (VOID **) &BusSpecificDriverOverride
+ );
+ if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) {
+ FakeNvData->DriSelection[Index] = 0x00;
+ continue;
+ }
+ } else {
+ FakeNvData->DriSelection[Index] = 0x00;
+ continue;
+ }
+ }
+
+ //
+ // For driver name, try to get its component name, if fail, get its image name,
+ // if also fail, give a default name.
+ //
+ FreeDriverName = FALSE;
+ DriverName = GetComponentName (DriverBindingHandle);
+ if (DriverName == NULL) {
+ //
+ // get its image name
+ //
+ DriverName = GetImageName (LoadedImage);
+ }
+ if (DriverName == NULL) {
+ //
+ // give a default name
+ //
+ DriverName = HiiGetString (Private->RegisteredHandle, STRING_TOKEN (STR_DRIVER_DEFAULT_NAME), NULL);
+ ASSERT (DriverName != NULL);
+ FreeDriverName = TRUE; // the DriverName string need to free pool
+ }
+
+
+ //
+ // Step2 Export the driver name string and create check box item in second page
+ //
+
+ //
+ // First create the driver image name
+ //
+ NewString = AllocateZeroPool (StrSize (DriverName));
+ ASSERT (NewString != NULL);
+ if (EFI_ERROR (CheckMapping (mControllerDevicePathProtocol[mSelectedCtrIndex], LoadedImageDevicePath, &mMappingDataBase, NULL, NULL))) {
+ FakeNvData->DriSelection[Index] = 0x00;
+ } else {
+ FakeNvData->DriSelection[Index] = 0x01;
+ mLastSavedDriverImageNum++;
+ }
+ StrCat (NewString, DriverName);
+ NewStringToken = HiiSetString (Private->RegisteredHandle, mDriverImageToken[Index], NewString, NULL);
+ ASSERT (NewStringToken != 0);
+ mDriverImageToken[Index] = NewStringToken;
+ FreePool (NewString);
+ if (FreeDriverName) {
+ FreePool (DriverName);
+ }
+
+ //
+ // Second create the driver image device path as item help string
+ //
+ DriverName = DevicePathToStr (LoadedImageDevicePath);
+
+ NewString = AllocateZeroPool (StrSize (DriverName));
+ ASSERT (NewString != NULL);
+ StrCat (NewString, DriverName);
+ NewStringHelpToken = HiiSetString (Private->RegisteredHandle, mDriverImageFilePathToken[Index], NewString, NULL);
+ ASSERT (NewStringHelpToken != 0);
+ mDriverImageFilePathToken[Index] = NewStringHelpToken;
+ FreePool (NewString);
+ FreePool (DriverName);
+
+ HiiCreateCheckBoxOpCode (
+ StartOpCodeHandle,
+ (UINT16) (DRIVER_SELECTION_QUESTION_ID + Index),
+ VARSTORE_ID_PLAT_OVER_MNGR,
+ (UINT16) (DRIVER_SELECTION_VAR_OFFSET + Index),
+ NewStringToken,
+ NewStringHelpToken,
+ 0,
+ 0,
+ NULL
+ );
+ }
+
+ //
+ // Update second page form
+ //
+ HiiUpdateForm (
+ Private->RegisteredHandle,
+ &mPlatformOverridesManagerGuid,
+ FORM_ID_DRIVER,
+ StartOpCodeHandle, // Label FORM_ID_DRIVER
+ EndOpCodeHandle // LABEL_END
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare to let user select the priority order of the drivers which are
+ selected in second page.
+
+ @param Private Pointer to EFI_CALLBACK_INFO.
+ @param KeyValue The callback key value of device controller item in first page.
+ @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
+
+ @retval EFI_SUCCESS Always returned.
+
+**/
+EFI_STATUS
+UpdatePrioritySelectPage (
+ IN EFI_CALLBACK_INFO *Private,
+ IN UINT16 KeyValue,
+ IN PLAT_OVER_MNGR_DATA *FakeNvData
+ )
+{
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;
+ UINTN SelectedDriverImageNum;
+ UINT32 DriverImageNO;
+ UINTN MinNO;
+ UINTN Index1;
+ UINTN TempNO[100];
+ UINTN OrderNO[100];
+ VOID *StartOpCodeHandle;
+ VOID *EndOpCodeHandle;
+ VOID *OptionsOpCodeHandle;
+ EFI_IFR_GUID_LABEL *StartLabel;
+ EFI_IFR_GUID_LABEL *EndLabel;
+
+ //
+ // Following code will be run if user select 'order ... priority' item in second page
+ // Prepare third page. In third page, user will order the drivers priority which are selected in second page
+ //
+ mCurrentPage = FORM_ID_ORDER;
+
+ //
+ // Init OpCode Handle
+ //
+ StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (StartOpCodeHandle != NULL);
+
+ EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (EndOpCodeHandle != NULL);
+
+ //
+ // Create Hii Extend Label OpCode as the start opcode
+ //
+ StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ StartLabel->Number = FORM_ID_ORDER;
+
+ //
+ // Create Hii Extend Label OpCode as the end opcode
+ //
+ EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
+ EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+ EndLabel->Number = LABEL_END;
+
+ //
+ // Clear third page form
+ //
+ HiiUpdateForm (
+ Private->RegisteredHandle,
+ &mPlatformOverridesManagerGuid,
+ FORM_ID_ORDER,
+ StartOpCodeHandle,
+ EndOpCodeHandle
+ );
+
+ //
+ // Check how many drivers have been selected
+ //
+ SelectedDriverImageNum = 0;
+ for (Index = 0; Index < mDriverImageHandleCount; Index++) {
+ if (FakeNvData->DriSelection[Index] != 0) {
+ SelectedDriverImageNum ++;
+ }
+ }
+
+ mSelectedDriverImageNum = SelectedDriverImageNum;
+ if (SelectedDriverImageNum == 0) {
+ return EFI_SUCCESS;
+ }
+
+ OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
+ ASSERT (OptionsOpCodeHandle != NULL);
+
+ //
+ // Create order list for those selected drivers
+ //
+ SelectedDriverImageNum = 0;
+ for (Index = 0; Index < mDriverImageHandleCount; Index++) {
+ if (FakeNvData->DriSelection[Index] != 0) {
+ //
+ // Use the NO. in driver binding buffer as value, will use it later
+ //
+ HiiCreateOneOfOptionOpCode (
+ OptionsOpCodeHandle,
+ mDriverImageToken[Index],
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ Index + 1
+ );
+
+ //
+ // Get the EFI Loaded Image Device Path Protocol
+ //
+ LoadedImageDevicePath = NULL;
+ gBS->HandleProtocol (
+ mDriverImageHandleBuffer[Index],
+ &gEfiLoadedImageDevicePathProtocolGuid,
+ (VOID **) &LoadedImageDevicePath
+ );
+ ASSERT (LoadedImageDevicePath != NULL);
+
+ //
+ // Check the driver DriverImage's order number in mapping database
+ //
+ DriverImageNO = 0;
+ CheckMapping (
+ mControllerDevicePathProtocol[mSelectedCtrIndex],
+ LoadedImageDevicePath,
+ &mMappingDataBase,
+ NULL,
+ &DriverImageNO
+ );
+ if (DriverImageNO == 0) {
+ DriverImageNO = (UINT32) mLastSavedDriverImageNum + 1;
+ mLastSavedDriverImageNum++;
+ }
+ TempNO[SelectedDriverImageNum] = DriverImageNO;
+ OrderNO[SelectedDriverImageNum] = Index + 1;
+ SelectedDriverImageNum ++;
+ }
+ }
+
+ ASSERT (SelectedDriverImageNum == mSelectedDriverImageNum);
+ //
+ // NvRamMap Must be clear firstly
+ //
+ ZeroMem (FakeNvData->DriOrder, sizeof (FakeNvData->DriOrder));
+
+ //
+ // Order the selected drivers according to the info already in mapping database
+ // the less order number in mapping database the less order number in NvRamMap
+ //
+ for (Index=0; Index < SelectedDriverImageNum; Index++) {
+ //
+ // Find the minimal order number in TempNO array, its index in TempNO is same as IfrOptionList array
+ //
+ MinNO = 0;
+ for (Index1=0; Index1 < SelectedDriverImageNum; Index1++) {
+ if (TempNO[Index1] < TempNO[MinNO]) {
+ MinNO = Index1;
+ }
+ }
+ //
+ // the IfrOptionList[MinNO].Value = the driver NO. in driver binding buffer
+ //
+ FakeNvData->DriOrder[Index] = (UINT8) OrderNO[MinNO];
+ TempNO[MinNO] = MAX_CHOICE_NUM + 1;
+ }
+
+ //
+ // Create Order List OpCode
+ //
+ HiiCreateOrderedListOpCode (
+ StartOpCodeHandle,
+ (UINT16) DRIVER_ORDER_QUESTION_ID,
+ VARSTORE_ID_PLAT_OVER_MNGR,
+ (UINT16) DRIVER_ORDER_VAR_OFFSET,
+ mControllerToken[mSelectedCtrIndex],
+ mControllerToken[mSelectedCtrIndex],
+ EFI_IFR_FLAG_RESET_REQUIRED,
+ 0,
+ EFI_IFR_NUMERIC_SIZE_1,
+ (UINT8) MAX_CHOICE_NUM,
+ OptionsOpCodeHandle,
+ NULL
+ );
+
+ //
+ // Update third page form
+ //
+ HiiUpdateForm (
+ Private->RegisteredHandle,
+ &mPlatformOverridesManagerGuid,
+ FORM_ID_ORDER,
+ StartOpCodeHandle, // Label FORM_ID_ORDER
+ EndOpCodeHandle // LABEL_END
+ );
+
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Save the save the mapping database to NV variable.
+
+ @param Private Pointer to EFI_CALLBACK_INFO.
+ @param KeyValue The callback key value of device controller item in first page.
+ @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
+
+ @retval EFI_SUCCESS Always returned.
+
+**/
+EFI_STATUS
+CommintChanges (
+ IN EFI_CALLBACK_INFO *Private,
+ IN UINT16 KeyValue,
+ IN PLAT_OVER_MNGR_DATA *FakeNvData
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN SelectedDriverImageNum;
+ EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;
+ //
+ // Following code will be run if user select 'commint changes' in third page
+ // user enter 'Commit Changes' to save the mapping database
+ //
+ DeleteDriverImage (mControllerDevicePathProtocol[mSelectedCtrIndex], NULL, &mMappingDataBase);
+ for (SelectedDriverImageNum = 0; SelectedDriverImageNum < mSelectedDriverImageNum; SelectedDriverImageNum++) {
+ //
+ // DriOrder[SelectedDriverImageNum] = the driver NO. in driver binding buffer
+ //
+ Index = FakeNvData->DriOrder[SelectedDriverImageNum] - 1;
+
+ //
+ // Get the EFI Loaded Image Device Path Protocol
+ //
+ LoadedImageDevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ mDriverImageHandleBuffer[Index],
+ &gEfiLoadedImageDevicePathProtocolGuid,
+ (VOID **) &LoadedImageDevicePath
+ );
+ ASSERT (LoadedImageDevicePath != NULL);
+
+ InsertDriverImage (
+ mControllerDevicePathProtocol[mSelectedCtrIndex],
+ LoadedImageDevicePath,
+ &mMappingDataBase,
+ (UINT32)SelectedDriverImageNum + 1
+ );
+ }
+ Status = SaveOverridesMapping (&mMappingDataBase);
+
+ return Status;
+}
+
+/**
+ This function allows a caller to extract the current configuration for one
+ or more named elements from the target driver.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Request A null-terminated Unicode string in <ConfigRequest> format.
+ @param Progress On return, points to a character in the Request string.
+ Points to the string's null terminator if request was successful.
+ Points to the most recent '&' before the first failing name/value
+ pair (or the beginning of the string if the failure is in the
+ first name/value pair) if the request was not successful.
+ @param Results A null-terminated Unicode string in <ConfigAltResp> format which
+ has all values filled in for the names in the Request string.
+ String to be allocated by the called function.
+
+ @retval EFI_SUCCESS The Results is filled with the requested values.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
+ @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatOverMngrExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+{
+ EFI_STATUS Status;
+ EFI_CALLBACK_INFO *Private;
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
+
+ if (Request == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Private = EFI_CALLBACK_INFO_FROM_THIS (This);
+ HiiConfigRouting = Private->HiiConfigRouting;
+
+ //
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+ //
+ Status = HiiConfigRouting->BlockToConfig (
+ HiiConfigRouting,
+ Request,
+ (UINT8 *) &Private->FakeNvData,
+ sizeof (PLAT_OVER_MNGR_DATA),
+ Results,
+ Progress
+ );
+ return Status;
+}
+
+/**
+ This function processes the results of changes in configuration.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Configuration A null-terminated Unicode string in <ConfigRequest> format.
+ @param Progress A pointer to a string filled in with the offset of the most
+ recent '&' before the first failing name/value pair (or the
+ beginning of the string if the failure is in the first
+ name/value pair) or the terminating NULL if all was successful.
+
+ @retval EFI_SUCCESS The Results is processed successfully.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatOverMngrRouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_CALLBACK_INFO *Private;
+ UINT16 KeyValue;
+ PLAT_OVER_MNGR_DATA *FakeNvData;
+
+ Private = EFI_CALLBACK_INFO_FROM_THIS (This);
+ FakeNvData = (PLAT_OVER_MNGR_DATA *) HiiGetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA));
+ if (FakeNvData == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (mCurrentPage == FORM_ID_DRIVER) {
+ KeyValue = KEY_VALUE_DRIVER_GOTO_ORDER;
+ UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);
+ KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;
+ CommintChanges (Private, KeyValue, FakeNvData);
+ //
+ // Since UpdatePrioritySelectPage will change mCurrentPage,
+ // should ensure the mCurrentPage still indicate the second page here
+ //
+ mCurrentPage = FORM_ID_DRIVER;
+ }
+
+ if (mCurrentPage == FORM_ID_ORDER) {
+ KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;
+ CommintChanges (Private, KeyValue, FakeNvData);
+ }
+
+ if (FakeNvData != NULL) {
+ FreePool (FakeNvData);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This is the function that is called to provide results data to the driver. This data
+ consists of a unique key which is used to identify what data is either being passed back
+ or being asked for.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Action A null-terminated Unicode string in <ConfigRequest> format.
+ @param KeyValue A unique Goto OpCode callback value which record user's selection.
+ 0x100 <= KeyValue <0x500 : user select a controller item in the first page;
+ KeyValue == 0x1234 : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page
+ KeyValue == 0x1235 : user select 'Pci device filter' in first page
+ KeyValue == 0x1500 : user select 'order ... priority' item in second page
+ KeyValue == 0x1800 : user select 'commint changes' in third page
+ KeyValue == 0x2000 : user select 'Go to Previous Menu' in third page
+ @param Type The type of value for the question.
+ @param Value A pointer to the data being sent to the original exporting driver.
+ @param ActionRequest On return, points to the action requested by the callback function.
+
+ @retval EFI_SUCCESS Always returned.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatOverMngrCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID KeyValue,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+{
+ EFI_CALLBACK_INFO *Private;
+ EFI_STATUS Status;
+ EFI_STRING_ID NewStringToken;
+ EFI_INPUT_KEY Key;
+ PLAT_OVER_MNGR_DATA *FakeNvData;
+
+ Private = EFI_CALLBACK_INFO_FROM_THIS (This);
+ FakeNvData = (PLAT_OVER_MNGR_DATA *) HiiGetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA));
+ if (FakeNvData == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (KeyValue == KEY_VALUE_DEVICE_REFRESH ||
+ KeyValue == KEY_VALUE_DEVICE_FILTER ||
+ KeyValue == KEY_VALUE_DRIVER_GOTO_PREVIOUS
+ ) {
+ UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);
+ //
+ // Update page title string
+ //
+ NewStringToken = STRING_TOKEN (STR_TITLE);
+ if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"First, Select the controller by device path", NULL) == 0) {
+ ASSERT (FALSE);
+ }
+ }
+
+ if (((KeyValue >= KEY_VALUE_DEVICE_OFFSET) && (KeyValue < KEY_VALUE_DEVICE_MAX)) || (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS)) {
+ if (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS) {
+ KeyValue = (EFI_QUESTION_ID) (mSelectedCtrIndex + KEY_VALUE_DEVICE_OFFSET);
+ }
+ UpdateBindingDriverSelectPage (Private, KeyValue, FakeNvData);
+ //
+ // Update page title string
+ //
+ NewStringToken = STRING_TOKEN (STR_TITLE);
+ if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"Second, Select drivers for the previous selected controller", NULL) == 0) {
+ ASSERT (FALSE);
+ }
+ }
+
+ if (KeyValue == KEY_VALUE_DRIVER_GOTO_ORDER) {
+ UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);
+ //
+ // Update page title string
+ //
+ NewStringToken = STRING_TOKEN (STR_TITLE);
+ if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"Finally, Set the priority order for the drivers and save them", NULL) == 0) {
+ ASSERT (FALSE);
+ }
+ }
+
+ if (KeyValue == KEY_VALUE_ORDER_SAVE_AND_EXIT) {
+ Status = CommintChanges (Private, KeyValue, FakeNvData);
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
+ if (EFI_ERROR (Status)) {
+ CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Single Override Info too large, Saving Error!", NULL);
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ if (KeyValue == KEY_VALUE_DEVICE_CLEAR) {
+ //
+ // Deletes all environment variable(s) that contain the override mappings info
+ //
+ FreeMappingDatabase (&mMappingDataBase);
+ Status = SaveOverridesMapping (&mMappingDataBase);
+ UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);
+ }
+ //
+ // Pass changed uncommitted data back to Form Browser
+ //
+ HiiSetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA), (UINT8 *) FakeNvData, NULL);
+
+ //
+ // Update local configuration buffer.
+ //
+ CopyMem (&Private->FakeNvData, FakeNvData, sizeof (PLAT_OVER_MNGR_DATA));
+ if (FakeNvData != NULL) {
+ FreePool (FakeNvData);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Retrieves the image handle of the platform override driver for a controller in the system.
+
+ @param This A pointer to the
+ EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL instance.
+ @param ControllerHandle The device handle of the controller to check if a
+ driver override exists.
+ @param DriverImageHandle On input, a pointer to the previous driver image
+ handle returned by GetDriver(). On output, a
+ pointer to the next driver image handle. Passing
+ in a NULL, will return the first driver image
+ handle for ControllerHandle.
+
+ @retval EFI_SUCCESS The driver override for ControllerHandle was
+ returned in DriverImageHandle.
+ @retval EFI_NOT_FOUND A driver override for ControllerHandle was not
+ found.
+ @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not a
+ valid handle. DriverImageHandle is not a handle
+ that was returned on a previous call to
+ GetDriver().
+
+**/
+EFI_STATUS
+EFIAPI
+GetDriver (
+ IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN OUT EFI_HANDLE *DriverImageHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Check that ControllerHandle is a valid handle
+ //
+ if (ControllerHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Read the environment variable(s) that contain the override mappings from Controller Device Path to
+ // a set of Driver Device Paths, and initialize in memory database of the overrides that map Controller
+ // Device Paths to an ordered set of Driver Device Paths and Driver Handles. This action is only performed
+ // once and finished in first call.
+ //
+ if (!mEnvironmentVariableRead) {
+ mEnvironmentVariableRead = TRUE;
+
+ Status = InitOverridesMapping (&mMappingDataBase);
+ if (EFI_ERROR (Status)){
+ DEBUG ((DEBUG_ERROR, "The status to Get Platform Driver Override Variable is %r\n", Status));
+ InitializeListHead (&mMappingDataBase);
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ //
+ // if the environment variable does not exist, just return not found
+ //
+ if (IsListEmpty (&mMappingDataBase)) {
+ return EFI_NOT_FOUND;
+ }
+
+ return GetDriverFromMapping (
+ ControllerHandle,
+ DriverImageHandle,
+ &mMappingDataBase,
+ mCallerImageHandle
+ );
+}
+
+/**
+ Retrieves the device path of the platform override driver for a controller in the system.
+ This driver doesn't support this API.
+
+ @param This A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_
+ PROTOCOL instance.
+ @param ControllerHandle The device handle of the controller to check if a driver override
+ exists.
+ @param DriverImagePath On input, a pointer to the previous driver device path returned by
+ GetDriverPath(). On output, a pointer to the next driver
+ device path. Passing in a pointer to NULL, will return the first
+ driver device path for ControllerHandle.
+
+ @retval EFI_UNSUPPORTED
+**/
+EFI_STATUS
+EFIAPI
+GetDriverPath (
+ IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DriverImagePath
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Used to associate a driver image handle with a device path that was returned on a prior call to the
+ GetDriverPath() service. This driver image handle will then be available through the
+ GetDriver() service. This driver doesn't support this API.
+
+ @param This A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_
+ PROTOCOL instance.
+ @param ControllerHandle The device handle of the controller.
+ @param DriverImagePath A pointer to the driver device path that was returned in a prior
+ call to GetDriverPath().
+ @param DriverImageHandle The driver image handle that was returned by LoadImage()
+ when the driver specified by DriverImagePath was loaded
+ into memory.
+
+ @retval EFI_UNSUPPORTED
+**/
+EFI_STATUS
+EFIAPI
+DriverLoaded (
+ IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *DriverImagePath,
+ IN EFI_HANDLE DriverImageHandle
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ The driver Entry Point. The funciton will export a disk device class formset and
+ its callback function to hii database.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatDriOverrideDxeInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
+ VOID *Instance;
+
+ //
+ // There should only be one Form Configuration protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiFormBrowser2ProtocolGuid,
+ NULL,
+ (VOID **) &FormBrowser2
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // According to UEFI spec, there can be at most a single instance
+ // in the system of the EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL.
+ // So here we check the existence.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiPlatformDriverOverrideProtocolGuid,
+ NULL,
+ &Instance
+ );
+ //
+ // If there was no error, assume there is an installation and return error
+ //
+ if (!EFI_ERROR (Status)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ mCallerImageHandle = ImageHandle;
+ mCallbackInfo = AllocateZeroPool (sizeof (EFI_CALLBACK_INFO));
+ if (mCallbackInfo == NULL) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ mCallbackInfo->Signature = EFI_CALLBACK_INFO_SIGNATURE;
+ mCallbackInfo->ConfigAccess.ExtractConfig = PlatOverMngrExtractConfig;
+ mCallbackInfo->ConfigAccess.RouteConfig = PlatOverMngrRouteConfig;
+ mCallbackInfo->ConfigAccess.Callback = PlatOverMngrCallback;
+ mCallbackInfo->PlatformDriverOverride.GetDriver = GetDriver;
+ mCallbackInfo->PlatformDriverOverride.GetDriverPath = GetDriverPath;
+ mCallbackInfo->PlatformDriverOverride.DriverLoaded = DriverLoaded;
+ //
+ // Install Device Path Protocol and Config Access protocol to driver handle
+ // Install Platform Driver Override Protocol to driver handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mCallbackInfo->DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mCallbackInfo->ConfigAccess,
+ &gEfiPlatformDriverOverrideProtocolGuid,
+ &mCallbackInfo->PlatformDriverOverride,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Finish;
+ }
+
+ //
+ // Publish our HII data
+ //
+ mCallbackInfo->RegisteredHandle = HiiAddPackages (
+ &mPlatformOverridesManagerGuid,
+ mCallbackInfo->DriverHandle,
+ VfrBin,
+ PlatDriOverrideDxeStrings,
+ NULL
+ );
+ if (mCallbackInfo->RegisteredHandle == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Finish;
+ }
+
+ //
+ // Locate ConfigRouting protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiConfigRoutingProtocolGuid,
+ NULL,
+ (VOID **) &mCallbackInfo->HiiConfigRouting
+ );
+ if (EFI_ERROR (Status)) {
+ goto Finish;
+ }
+
+ //
+ // Clear all the globle variable
+ //
+ mDriverImageHandleCount = 0;
+ mCurrentPage = 0;
+ ZeroMem (mDriverImageToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));
+ ZeroMem (mDriverImageFilePathToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));
+ ZeroMem (mControllerToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));
+ ZeroMem (mDriverImageProtocol, MAX_CHOICE_NUM * sizeof (EFI_LOADED_IMAGE_PROTOCOL *));
+
+ return EFI_SUCCESS;
+
+Finish:
+ if (mCallbackInfo->DriverHandle != NULL) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ mCallbackInfo->DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mCallbackInfo->ConfigAccess,
+ &gEfiPlatformDriverOverrideProtocolGuid,
+ &mCallbackInfo->PlatformDriverOverride,
+ NULL
+ );
+ }
+
+ if (mCallbackInfo->RegisteredHandle != NULL) {
+ HiiRemovePackages (mCallbackInfo->RegisteredHandle);
+ }
+
+ if (mCallbackInfo != NULL) {
+ FreePool (mCallbackInfo);
+ }
+
+ return Status;
+}
+
+/**
+ Unload its installed protocol.
+
+ @param[in] ImageHandle Handle that identifies the image to be unloaded.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+**/
+EFI_STATUS
+EFIAPI
+PlatDriOverrideDxeUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ if (mCallbackInfo->DriverHandle != NULL) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ mCallbackInfo->DriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mHiiVendorDevicePath,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &mCallbackInfo->ConfigAccess,
+ &gEfiPlatformDriverOverrideProtocolGuid,
+ &mCallbackInfo->PlatformDriverOverride,
+ NULL
+ );
+ }
+
+ if (mCallbackInfo->RegisteredHandle != NULL) {
+ HiiRemovePackages (mCallbackInfo->RegisteredHandle);
+ }
+
+ if (mCallbackInfo != NULL) {
+ FreePool (mCallbackInfo);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideLib.c b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideLib.c
new file mode 100644
index 0000000000..48beba06e8
--- /dev/null
+++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideLib.c
@@ -0,0 +1,1898 @@
+/** @file
+ Implementation of the shared functions to do the platform driver vverride mapping.
+
+ Copyright (c) 2007 - 2009, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "InternalPlatDriOverrideDxe.h"
+
+#define PLATFORM_OVERRIDE_ITEM_SIGNATURE SIGNATURE_32('p','d','o','i')
+ typedef struct _PLATFORM_OVERRIDE_ITEM {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ UINT32 DriverInfoNum;
+ EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath;
+ ///
+ /// List of DRIVER_IMAGE_INFO
+ ///
+ LIST_ENTRY DriverInfoList;
+ EFI_HANDLE LastReturnedImageHandle;
+} PLATFORM_OVERRIDE_ITEM;
+
+#define DRIVER_IMAGE_INFO_SIGNATURE SIGNATURE_32('p','d','i','i')
+typedef struct _DRIVER_IMAGE_INFO {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ EFI_HANDLE ImageHandle;
+ EFI_DEVICE_PATH_PROTOCOL *DriverImagePath;
+ BOOLEAN UnLoadable;
+ BOOLEAN UnStartable;
+} DRIVER_IMAGE_INFO;
+
+#define DEVICE_PATH_STACK_ITEM_SIGNATURE SIGNATURE_32('d','p','s','i')
+typedef struct _DEVICE_PATH_STACK_ITEM{
+ UINTN Signature;
+ LIST_ENTRY Link;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+} DEVICE_PATH_STACK_ITEM;
+
+
+LIST_ENTRY mDevicePathStack = INITIALIZE_LIST_HEAD_VARIABLE (mDevicePathStack);
+
+/**
+ Push a controller device path into a globle device path list.
+
+ @param DevicePath The controller device path to push into stack
+
+ @retval EFI_SUCCESS Device path successfully pushed into the stack.
+
+**/
+EFI_STATUS
+EFIAPI
+PushDevPathStack (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ DEVICE_PATH_STACK_ITEM *DevicePathStackItem;
+
+ DevicePathStackItem = AllocateZeroPool (sizeof (DEVICE_PATH_STACK_ITEM));
+ ASSERT (DevicePathStackItem != NULL);
+ DevicePathStackItem->Signature = DEVICE_PATH_STACK_ITEM_SIGNATURE;
+ DevicePathStackItem->DevicePath = DuplicateDevicePath (DevicePath);
+ InsertTailList (&mDevicePathStack, &DevicePathStackItem->Link);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Pop a controller device path from a globle device path list
+
+ @param DevicePath The controller device path popped from stack
+
+ @retval EFI_SUCCESS Controller device path successfully popped.
+ @retval EFI_NOT_FOUND Stack is empty.
+
+**/
+EFI_STATUS
+EFIAPI
+PopDevPathStack (
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ DEVICE_PATH_STACK_ITEM *DevicePathStackItem;
+ LIST_ENTRY *ItemListIndex;
+
+ ItemListIndex = mDevicePathStack.BackLink;
+ //
+ // Check if the stack is empty
+ //
+ if (ItemListIndex != &mDevicePathStack){
+ DevicePathStackItem = CR(ItemListIndex, DEVICE_PATH_STACK_ITEM, Link, DEVICE_PATH_STACK_ITEM_SIGNATURE);
+ if (DevicePath != NULL) {
+ *DevicePath = DuplicateDevicePath (DevicePathStackItem->DevicePath);
+ }
+ FreePool (DevicePathStackItem->DevicePath);
+ RemoveEntryList (&DevicePathStackItem->Link);
+ FreePool (DevicePathStackItem);
+ return EFI_SUCCESS;
+ }
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Check whether a controller device path is in a globle device path list
+
+ @param DevicePath The controller device path to check
+
+ @retval TRUE DevicePath exists in the stack.
+ @retval FALSE DevicePath does not exist in the stack.
+
+**/
+BOOLEAN
+EFIAPI
+CheckExistInStack (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ DEVICE_PATH_STACK_ITEM *DevicePathStackItem;
+ LIST_ENTRY *ItemListIndex;
+ UINTN DevicePathSize;
+
+ ItemListIndex = mDevicePathStack.BackLink;
+ while (ItemListIndex != &mDevicePathStack){
+ DevicePathStackItem = CR(ItemListIndex, DEVICE_PATH_STACK_ITEM, Link, DEVICE_PATH_STACK_ITEM_SIGNATURE);
+ DevicePathSize = GetDevicePathSize (DevicePath);
+ if (DevicePathSize == GetDevicePathSize (DevicePathStackItem->DevicePath)) {
+ if (CompareMem (DevicePath, DevicePathStackItem->DevicePath, DevicePathSize) == 0) {
+ return TRUE;
+ }
+ }
+ ItemListIndex = ItemListIndex->BackLink;
+ }
+
+ return FALSE;
+}
+
+/**
+ Update the FV file device path if it is not valid.
+
+ According to a file GUID, check a Fv file device path is valid. If it is invalid,
+ try to return the valid device path.
+ FV address maybe changes for memory layout adjust from time to time, use this funciton
+ could promise the Fv file device path is right.
+
+ @param DevicePath On input, the FV file device path to check
+ On output, the updated valid FV file device path
+ @param FileGuid The FV file GUID
+ @param CallerImageHandle Image handle of the caller
+
+ @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid
+ parameter
+ @retval EFI_UNSUPPORTED the input DevicePath does not contain FV file
+ GUID at all
+ @retval EFI_ALREADY_STARTED the input DevicePath has pointed to FV file, it
+ is valid
+ @retval EFI_SUCCESS Successfully updated the invalid DevicePath,
+ and return the updated device path in DevicePath
+
+**/
+EFI_STATUS
+EFIAPI
+UpdateFvFileDevicePath (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
+ IN EFI_GUID *FileGuid,
+ IN EFI_HANDLE CallerImageHandle
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;
+ EFI_STATUS Status;
+ EFI_GUID *GuidPoint;
+ UINTN Index;
+ UINTN FvHandleCount;
+ EFI_HANDLE *FvHandleBuffer;
+ EFI_FV_FILETYPE Type;
+ UINTN Size;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINT32 AuthenticationStatus;
+ BOOLEAN FindFvFile;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode;
+ EFI_HANDLE FoundFvHandle;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+ BOOLEAN HasFvNode;
+
+ if (DevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*DevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check whether the device path points to the default the input FV file
+ //
+ TempDevicePath = *DevicePath;
+ LastDeviceNode = TempDevicePath;
+ while (!IsDevicePathEnd (TempDevicePath)) {
+ LastDeviceNode = TempDevicePath;
+ TempDevicePath = NextDevicePathNode (TempDevicePath);
+ }
+ GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode);
+ if (GuidPoint == NULL) {
+ //
+ // If this option does not point to a FV file, just return EFI_UNSUPPORTED.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ if (FileGuid != NULL) {
+ if (!CompareGuid (GuidPoint, FileGuid)) {
+ //
+ // If the FV file is not the input file GUID, just return EFI_UNSUPPORTED
+ //
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ FileGuid = GuidPoint;
+ }
+
+ //
+ // Check to see if the device path contains memory map node
+ //
+ TempDevicePath = *DevicePath;
+ HasFvNode = FALSE;
+ while (!IsDevicePathEnd (TempDevicePath)) {
+ //
+ // Use old Device Path
+ //
+ if (DevicePathType (TempDevicePath) == HARDWARE_DEVICE_PATH &&
+ DevicePathSubType (TempDevicePath) == HW_MEMMAP_DP) {
+ HasFvNode = TRUE;
+ break;
+ }
+ TempDevicePath = NextDevicePathNode (TempDevicePath);
+ }
+
+ if (!HasFvNode) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check whether the input Fv file device path is valid
+ //
+ TempDevicePath = *DevicePath;
+ FoundFvHandle = NULL;
+ Status = gBS->LocateDevicePath (
+ &gEfiFirmwareVolume2ProtocolGuid,
+ &TempDevicePath,
+ &FoundFvHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->HandleProtocol (
+ FoundFvHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &Fv
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there
+ //
+ Status = Fv->ReadFile (
+ Fv,
+ FileGuid,
+ NULL,
+ &Size,
+ &Type,
+ &Attributes,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ return EFI_ALREADY_STARTED;
+ }
+ }
+ }
+
+ //
+ // Look for the input wanted FV file in current FV
+ // First, try to look for in Caller own FV. Caller and input wanted FV file usually are in the same FV
+ //
+ FindFvFile = FALSE;
+ FoundFvHandle = NULL;
+ Status = gBS->HandleProtocol (
+ CallerImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->HandleProtocol (
+ LoadedImage->DeviceHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &Fv
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = Fv->ReadFile (
+ Fv,
+ FileGuid,
+ NULL,
+ &Size,
+ &Type,
+ &Attributes,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ FindFvFile = TRUE;
+ FoundFvHandle = LoadedImage->DeviceHandle;
+ }
+ }
+ }
+ //
+ // Second, if fail to find, try to enumerate all FV
+ //
+ if (!FindFvFile) {
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ &FvHandleCount,
+ &FvHandleBuffer
+ );
+ for (Index = 0; Index < FvHandleCount; Index++) {
+ gBS->HandleProtocol (
+ FvHandleBuffer[Index],
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &Fv
+ );
+
+ Status = Fv->ReadFile (
+ Fv,
+ FileGuid,
+ NULL,
+ &Size,
+ &Type,
+ &Attributes,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Skip if input Fv file not in the FV
+ //
+ continue;
+ }
+ FindFvFile = TRUE;
+ FoundFvHandle = FvHandleBuffer[Index];
+ break;
+ }
+ }
+
+ if (FindFvFile) {
+ //
+ // Build the shell device path
+ //
+ NewDevicePath = DevicePathFromHandle (FoundFvHandle);
+ EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid);
+ NewDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode);
+ *DevicePath = NewDevicePath;
+ return EFI_SUCCESS;
+ }
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Gets the data and size of a variable.
+
+ Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
+ buffer, and the size of the buffer. If failure return NULL.
+
+ @param Name String part of EFI variable name
+ @param VendorGuid GUID part of EFI variable name
+ @param VariableSize Returns the size of the EFI variable that was
+ read
+
+ @return Dynamically allocated memory that contains a copy of the EFI variable.
+ Caller is responsible freeing the buffer.
+ @retval NULL Variable was not read
+
+**/
+VOID *
+EFIAPI
+GetVariableAndSize (
+ IN CHAR16 *Name,
+ IN EFI_GUID *VendorGuid,
+ OUT UINTN *VariableSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ VOID *Buffer;
+
+ Buffer = NULL;
+
+ //
+ // Pass in a zero size buffer to find the required buffer size.
+ //
+ BufferSize = 0;
+ Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // Allocate the buffer to return
+ //
+ Buffer = AllocateZeroPool (BufferSize);
+ if (Buffer == NULL) {
+ return NULL;
+ }
+ //
+ // Read variable into the allocated buffer.
+ //
+ Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
+ if (EFI_ERROR (Status)) {
+ BufferSize = 0;
+ }
+ }
+
+ *VariableSize = BufferSize;
+ return Buffer;
+}
+
+/**
+ Connect to the handle to a device on the device path.
+
+ This function will create all handles associate with every device
+ path node. If the handle associate with one device path node can not
+ be created success, then still give one chance to do the dispatch,
+ which load the missing drivers if possible.
+
+ @param DevicePathToConnect The device path which will be connected, it can
+ be a multi-instance device path
+
+ @retval EFI_SUCCESS All handles associate with every device path
+ node have been created
+ @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles
+ @retval EFI_NOT_FOUND Create the handle associate with one device
+ path node failed
+
+**/
+EFI_STATUS
+EFIAPI
+ConnectDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
+ EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *Next;
+ EFI_HANDLE Handle;
+ EFI_HANDLE PreviousHandle;
+ UINTN Size;
+
+ if (DevicePathToConnect == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ DevicePath = DuplicateDevicePath (DevicePathToConnect);
+ CopyOfDevicePath = DevicePath;
+ if (DevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ do {
+ //
+ // The outer loop handles multi instance device paths.
+ // Only console variables contain multiple instance device paths.
+ //
+ // After this call DevicePath points to the next Instance
+ //
+ Instance = GetNextDevicePathInstance (&DevicePath, &Size);
+ ASSERT (Instance != NULL);
+
+ Next = Instance;
+ while (!IsDevicePathEndType (Next)) {
+ Next = NextDevicePathNode (Next);
+ }
+
+ SetDevicePathEndNode (Next);
+
+ //
+ // Start the real work of connect with RemainingDevicePath
+ //
+ PreviousHandle = NULL;
+ do {
+ //
+ // Find the handle that best matches the Device Path. If it is only a
+ // partial match the remaining part of the device path is returned in
+ // RemainingDevicePath.
+ //
+ RemainingDevicePath = Instance;
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);
+
+ if (!EFI_ERROR (Status)) {
+ if (Handle == PreviousHandle) {
+ //
+ // If no forward progress is made try invoking the Dispatcher.
+ // A new FV may have been added to the system an new drivers
+ // may now be found.
+ // Status == EFI_SUCCESS means a driver was dispatched
+ // Status == EFI_NOT_FOUND means no new drivers were dispatched
+ //
+ Status = gDS->Dispatch ();
+ }
+
+ if (!EFI_ERROR (Status)) {
+ PreviousHandle = Handle;
+ //
+ // Connect all drivers that apply to Handle and RemainingDevicePath,
+ // the Recursive flag is FALSE so only one level will be expanded.
+ //
+ // Do not check the connect status here, if the connect controller fail,
+ // then still give the chance to do dispatch, because partial
+ // RemainingDevicepath may be in the new FV
+ //
+ // 1. If the connect fails, RemainingDevicepath and handle will not
+ // change, so next time will do the dispatch, then dispatch's status
+ // will take effect
+ // 2. If the connect succeeds, the RemainingDevicepath and handle will
+ // change, then avoid the dispatch, we have chance to continue the
+ // next connection
+ //
+ gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
+ }
+ }
+ //
+ // Loop until RemainingDevicePath is an empty device path
+ //
+ } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
+
+ } while (DevicePath != NULL);
+
+ if (CopyOfDevicePath != NULL) {
+ FreePool (CopyOfDevicePath);
+ }
+ //
+ // All handle with DevicePath exists in the handle database
+ //
+ return Status;
+}
+
+/**
+ Free all the mapping database memory resource and initialize the mapping list entry.
+
+ @param MappingDataBase Mapping database list entry pointer
+
+ @retval EFI_SUCCESS Mapping database successfully freed
+ @retval EFI_INVALID_PARAMETER MappingDataBase is NULL
+
+**/
+EFI_STATUS
+EFIAPI
+FreeMappingDatabase (
+ IN OUT LIST_ENTRY *MappingDataBase
+ )
+{
+ LIST_ENTRY *OverrideItemListIndex;
+ LIST_ENTRY *ImageInfoListIndex;
+ PLATFORM_OVERRIDE_ITEM *OverrideItem;
+ DRIVER_IMAGE_INFO *DriverImageInfo;
+
+ if (MappingDataBase == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OverrideItemListIndex = GetFirstNode (MappingDataBase);
+ while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
+ OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
+ //
+ // Free PLATFORM_OVERRIDE_ITEM.ControllerDevicePath[]
+ //
+ if (OverrideItem->ControllerDevicePath != NULL){
+ FreePool (OverrideItem->ControllerDevicePath);
+ }
+
+ ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
+ while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
+ //
+ // Free DRIVER_IMAGE_INFO.DriverImagePath[]
+ //
+ DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
+ if (DriverImageInfo->DriverImagePath != NULL) {
+ FreePool(DriverImageInfo->DriverImagePath);
+ }
+ //
+ // Free DRIVER_IMAGE_INFO itself
+ //
+ ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
+ RemoveEntryList (&DriverImageInfo->Link);
+ FreePool (DriverImageInfo);
+ }
+ //
+ // Free PLATFORM_OVERRIDE_ITEM itself
+ //
+ OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
+ RemoveEntryList (&OverrideItem->Link);
+ FreePool (OverrideItem);
+ }
+
+ InitializeListHead (MappingDataBase);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Create the mapping database according to variable.
+
+ Read the environment variable(s) that contain the override mappings from Controller Device Path to
+ a set of Driver Device Paths, and create the mapping database in memory with those variable info.
+ VariableLayout{
+ //
+ // NotEnd indicate whether the variable is the last one, and has no subsequent variable need to load.
+ // Each variable has MaximumVariableSize limitation, so we maybe need multiple variables to store
+ // large mapping infos.
+ // The variable(s) name rule is PlatDriOver, PlatDriOver1, PlatDriOver2, ....
+ //
+ UINT32 NotEnd; //Zero is the last one.
+ //
+ // The entry which contains the mapping that Controller Device Path to a set of Driver Device Paths
+ // There are often multi mapping entries in a variable.
+ //
+ UINT32 SIGNATURE; //SIGNATURE_32('p','d','o','i')
+ UINT32 DriverNum;
+ EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[];
+ EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
+ EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
+ EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
+ ......
+ UINT32 NotEnd; //Zero is the last one.
+ UINT32 SIGNATURE;
+ UINT32 DriverNum;
+ EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[];
+ EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
+ EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
+ EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
+ ......
+ }
+
+ @param MappingDataBase Mapping database list entry pointer
+
+ @retval EFI_SUCCESS Create the mapping database in memory successfully
+ @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null
+ @retval EFI_NOT_FOUND Cannot find the 'PlatDriOver' NV variable
+ @retval EFI_VOLUME_CORRUPTED The found NV variable is corrupted
+
+**/
+EFI_STATUS
+EFIAPI
+InitOverridesMapping (
+ OUT LIST_ENTRY *MappingDataBase
+ )
+{
+ UINTN BufferSize;
+ VOID *VariableBuffer;
+ UINT8 *VariableIndex;
+ UINTN VariableNum;
+ CHAR16 OverrideVariableName[40];
+ UINT32 NotEnd;
+ UINT32 DriverNumber;
+ PLATFORM_OVERRIDE_ITEM *OverrideItem;
+ DRIVER_IMAGE_INFO *DriverImageInfo;
+ BOOLEAN Corrupted;
+ UINT32 Signature;
+ EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;
+ UINTN Index;
+
+ if (MappingDataBase == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check the environment variable(s) that contain the override mappings .
+ //
+ VariableBuffer = GetVariableAndSize (L"PlatDriOver", &gEfiCallerIdGuid, &BufferSize);
+ ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0);
+ if (VariableBuffer == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Traverse all variables.
+ //
+ VariableNum = 1;
+ Corrupted = FALSE;
+ do {
+ VariableIndex = VariableBuffer;
+ //
+ // End flag
+ //
+ NotEnd = *(UINT32*) VariableIndex;
+ //
+ // Traverse the entries containing the mapping that Controller Device Path
+ // to a set of Driver Device Paths within this variable.
+ //
+ VariableIndex = VariableIndex + sizeof (UINT32);
+ while (VariableIndex < ((UINT8 *)VariableBuffer + BufferSize)) {
+ //
+ // Check signature of this entry
+ //
+ Signature = *(UINT32 *) VariableIndex;
+ if (Signature != PLATFORM_OVERRIDE_ITEM_SIGNATURE) {
+ Corrupted = TRUE;
+ break;
+ }
+ //
+ // Create PLATFORM_OVERRIDE_ITEM for this mapping
+ //
+ OverrideItem = AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM));
+ ASSERT (OverrideItem != NULL);
+ OverrideItem->Signature = PLATFORM_OVERRIDE_ITEM_SIGNATURE;
+ InitializeListHead (&OverrideItem->DriverInfoList);
+ VariableIndex = VariableIndex + sizeof (UINT32);
+ //
+ // Get DriverNum
+ //
+ DriverNumber = *(UINT32*) VariableIndex;
+ OverrideItem->DriverInfoNum = DriverNumber;
+ VariableIndex = VariableIndex + sizeof (UINT32);
+ //
+ // Get ControllerDevicePath[]
+ //
+ ControllerDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) VariableIndex;
+ OverrideItem->ControllerDevicePath = DuplicateDevicePath (ControllerDevicePath);
+ VariableIndex = VariableIndex + GetDevicePathSize (ControllerDevicePath);
+ //
+ // Align the VariableIndex since the controller device path may not be aligned, refer to the SaveOverridesMapping()
+ //
+ VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
+
+ //
+ // Get all DriverImageDevicePath[]
+ //
+ for (Index = 0; Index < DriverNumber; Index++) {
+ //
+ // Create DRIVER_IMAGE_INFO for this DriverDevicePath[]
+ //
+ DriverImageInfo = AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO));
+ ASSERT (DriverImageInfo != NULL);
+ DriverImageInfo->Signature = DRIVER_IMAGE_INFO_SIGNATURE;
+
+ DriverDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) VariableIndex;
+ DriverImageInfo->DriverImagePath = DuplicateDevicePath (DriverDevicePath);
+ VariableIndex = VariableIndex + GetDevicePathSize (DriverDevicePath);
+ //
+ // Align the VariableIndex since the driver image device path may not be aligned, refer to the SaveOverridesMapping()
+ //
+ VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
+
+ InsertTailList (&OverrideItem->DriverInfoList, &DriverImageInfo->Link);
+ }
+ InsertTailList (MappingDataBase, &OverrideItem->Link);
+ }
+
+ FreePool (VariableBuffer);
+ if (Corrupted) {
+ FreeMappingDatabase (MappingDataBase);
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ //
+ // If there are additional variables (PlatDriOver1, PlatDriOver2, PlatDriOver3.....), get them.
+ // NotEnd indicates whether current variable is the end variable.
+ //
+ if (NotEnd != 0) {
+ UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum++);
+ VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiCallerIdGuid, &BufferSize);
+ ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0);
+ if (VariableBuffer == NULL) {
+ FreeMappingDatabase (MappingDataBase);
+ return EFI_VOLUME_CORRUPTED;
+ }
+ }
+
+ } while (NotEnd != 0);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Calculate the needed size in NV variable for recording a specific PLATFORM_OVERRIDE_ITEM info.
+
+ @param OverrideItemListIndex Pointer to the list of a specific PLATFORM_OVERRIDE_ITEM
+
+ @return The needed size number
+
+**/
+UINTN
+EFIAPI
+GetOneItemNeededSize (
+ IN LIST_ENTRY *OverrideItemListIndex
+ )
+{
+ UINTN NeededSize;
+ PLATFORM_OVERRIDE_ITEM *OverrideItem;
+ LIST_ENTRY *ImageInfoListIndex;
+ DRIVER_IMAGE_INFO *DriverImageInfo;
+ UINTN DevicePathSize;
+
+ NeededSize = 0;
+ OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
+ NeededSize += sizeof (UINT32); //UINT32 SIGNATURE;
+ NeededSize += sizeof (UINT32); //UINT32 DriverNum;
+ DevicePathSize = GetDevicePathSize (OverrideItem->ControllerDevicePath);
+ NeededSize += DevicePathSize; // ControllerDevicePath
+ //
+ // Align the controller device path
+ //
+ NeededSize += ((sizeof(UINT32) - DevicePathSize) & (sizeof(UINT32) - 1));
+ //
+ // Traverse the Driver Info List of this Override Item
+ //
+ ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
+ while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
+ DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
+ DevicePathSize = GetDevicePathSize (DriverImageInfo->DriverImagePath);
+ NeededSize += DevicePathSize; //DriverDevicePath
+ //
+ // Align the driver image device path
+ //
+ NeededSize += ((sizeof(UINT32) - DevicePathSize) & (sizeof(UINT32) - 1));
+ ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
+ }
+
+ return NeededSize;
+}
+
+/**
+ Deletes all environment variable(s) that contain the override mappings from Controller Device Path to
+ a set of Driver Device Paths.
+
+ @retval EFI_SUCCESS Delete all variable(s) successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+DeleteOverridesVariables (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ VOID *VariableBuffer;
+ UINTN VariableNum;
+ UINTN BufferSize;
+ UINTN Index;
+ CHAR16 OverrideVariableName[40];
+
+ //
+ // Get environment variable(s) number
+ //
+ VariableNum = 0;
+ VariableBuffer = GetVariableAndSize (L"PlatDriOver", &gEfiCallerIdGuid, &BufferSize);
+ VariableNum++;
+ if (VariableBuffer == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Check NotEnd to get all PlatDriOverX variable(s)
+ //
+ while ((*(UINT32*)VariableBuffer) != 0) {
+ UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum);
+ VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiCallerIdGuid, &BufferSize);
+ VariableNum++;
+ ASSERT (VariableBuffer != NULL);
+ }
+
+ //
+ // Delete PlatDriOver and all additional variables, if exist.
+ //
+ Status = gRT->SetVariable (
+ L"PlatDriOver",
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ 0,
+ NULL
+ );
+ ASSERT (!EFI_ERROR (Status));
+ for (Index = 1; Index < VariableNum; Index++) {
+ UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", Index);
+ Status = gRT->SetVariable (
+ OverrideVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ 0,
+ NULL
+ );
+ ASSERT (!EFI_ERROR (Status));
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Save the memory mapping database into NV environment variable(s).
+
+ @param MappingDataBase Mapping database list entry pointer
+
+ @retval EFI_SUCCESS Save memory mapping database successfully
+ @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null
+
+**/
+EFI_STATUS
+EFIAPI
+SaveOverridesMapping (
+ IN LIST_ENTRY *MappingDataBase
+ )
+{
+ EFI_STATUS Status;
+ VOID *VariableBuffer;
+ UINT8 *VariableIndex;
+ UINTN NumIndex;
+ CHAR16 OverrideVariableName[40];
+ UINT32 NotEnd;
+ PLATFORM_OVERRIDE_ITEM *OverrideItem;
+ DRIVER_IMAGE_INFO *DriverImageInfo;
+ LIST_ENTRY *OverrideItemListIndex;
+ LIST_ENTRY *ItemIndex;
+ LIST_ENTRY *ImageInfoListIndex;
+ UINTN VariableNeededSize;
+ UINT64 MaximumVariableStorageSize;
+ UINT64 RemainingVariableStorageSize;
+ UINT64 MaximumVariableSize;
+ UINTN OneItemNeededSize;
+
+ if (MappingDataBase == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IsListEmpty (MappingDataBase)) {
+ Status = DeleteOverridesVariables ();
+ ASSERT_EFI_ERROR (Status);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Get the the maximum size of an individual EFI variable in current system
+ //
+ gRT->QueryVariableInfo (
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ &MaximumVariableStorageSize,
+ &RemainingVariableStorageSize,
+ &MaximumVariableSize
+ );
+
+ NumIndex = 0;
+ OverrideItemListIndex = GetFirstNode (MappingDataBase);
+ while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
+ //
+ // Try to find the most proper variable size which <= MaximumVariableSize,
+ // but can contain mapping info as much as possible
+ //
+ VariableNeededSize = sizeof (UINT32); // NotEnd;
+ ItemIndex = OverrideItemListIndex;
+ NotEnd = FALSE;
+ //
+ // Traverse all PLATFORM_OVERRIDE_ITEMs and get the total size.
+ //
+ while (!IsNull (MappingDataBase, ItemIndex)) {
+ OneItemNeededSize = GetOneItemNeededSize (ItemIndex);
+ //
+ // If the total size exceeds the MaximumVariableSize, then we must use
+ // multiple variables.
+ //
+ if ((VariableNeededSize +
+ OneItemNeededSize +
+ sizeof (VARIABLE_HEADER) +
+ StrSize (L"PlatDriOver ")
+ ) >= MaximumVariableSize
+ ) {
+ NotEnd = TRUE;
+ break;
+ }
+
+ VariableNeededSize += OneItemNeededSize;
+ ItemIndex = GetNextNode (MappingDataBase, ItemIndex);
+ }
+
+ if (NotEnd != 0) {
+ if (VariableNeededSize == sizeof (UINT32)) {
+ //
+ // If an individual EFI variable cannot contain a single Item, return error
+ //
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ //
+ // VariableNeededSize is the most proper variable size, allocate variable buffer
+ // ItemIndex now points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize
+ //
+ VariableBuffer = AllocateZeroPool (VariableNeededSize);
+ ASSERT (VariableBuffer != NULL);
+ ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0);
+
+ //
+ // Fill the variable buffer according to MappingDataBase
+ //
+ VariableIndex = VariableBuffer;
+ *(UINT32 *) VariableIndex = NotEnd;
+ VariableIndex += sizeof (UINT32); // pass NotEnd
+ //
+ // ItemIndex points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize
+ //
+ while (OverrideItemListIndex != ItemIndex){
+ *(UINT32 *) VariableIndex = PLATFORM_OVERRIDE_ITEM_SIGNATURE;
+ VariableIndex += sizeof (UINT32); // pass SIGNATURE
+
+ OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
+ *(UINT32 *) VariableIndex = OverrideItem->DriverInfoNum;
+ VariableIndex += sizeof (UINT32); // pass DriverNum
+
+ CopyMem (VariableIndex, OverrideItem->ControllerDevicePath, GetDevicePathSize (OverrideItem->ControllerDevicePath));
+ VariableIndex += GetDevicePathSize (OverrideItem->ControllerDevicePath); // pass ControllerDevicePath
+
+ //
+ // Align the VariableIndex since the controller device path may not be aligned
+ //
+ VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
+ //
+ // Save the Driver Info List of this PLATFORM_OVERRIDE_ITEM
+ //
+ ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
+ while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
+ DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
+ CopyMem (VariableIndex, DriverImageInfo->DriverImagePath, GetDevicePathSize (DriverImageInfo->DriverImagePath));
+ VariableIndex += GetDevicePathSize (DriverImageInfo->DriverImagePath); // pass DriverImageDevicePath
+ //
+ // Align the VariableIndex since the driver image device path may not be aligned
+ //
+ VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
+ ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
+ }
+
+ OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
+ }
+
+ ASSERT (((UINTN)VariableIndex - (UINTN)VariableBuffer) == VariableNeededSize);
+
+ if (NumIndex == 0) {
+ UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver");
+ } else {
+ UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", NumIndex );
+ }
+
+ Status = gRT->SetVariable (
+ OverrideVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ VariableNeededSize,
+ VariableBuffer
+ );
+ ASSERT (!EFI_ERROR(Status));
+
+ NumIndex ++;
+ FreePool (VariableBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the first Binding protocol which has the specific image handle.
+
+ @param ImageHandle The Image handle
+ @param BindingHandle The BindingHandle of the found Driver Binding protocol.
+ If Binding protocol is not found, it is set to NULL.
+
+ @return Pointer into the Binding Protocol interface
+ @retval NULL The paramter is not valid or the binding protocol is not found.
+
+**/
+EFI_DRIVER_BINDING_PROTOCOL *
+EFIAPI
+GetBindingProtocolFromImageHandle (
+ IN EFI_HANDLE ImageHandle,
+ OUT EFI_HANDLE *BindingHandle
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN DriverBindingHandleCount;
+ EFI_HANDLE *DriverBindingHandleBuffer;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBindingInterface;
+
+ if (BindingHandle == NULL || ImageHandle == NULL) {
+ return NULL;
+ }
+ //
+ // Get all drivers which support driver binding protocol
+ //
+ DriverBindingHandleCount = 0;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiDriverBindingProtocolGuid,
+ NULL,
+ &DriverBindingHandleCount,
+ &DriverBindingHandleBuffer
+ );
+ if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
+ return NULL;
+ }
+
+ for (Index = 0; Index < DriverBindingHandleCount; Index++) {
+ DriverBindingInterface = NULL;
+ Status = gBS->OpenProtocol (
+ DriverBindingHandleBuffer[Index],
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **) &DriverBindingInterface,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (DriverBindingInterface->ImageHandle == ImageHandle) {
+ *BindingHandle = DriverBindingHandleBuffer[Index];
+ FreePool (DriverBindingHandleBuffer);
+ return DriverBindingInterface;
+ }
+ }
+
+ //
+ // If no Driver Binding Protocol instance is found
+ //
+ FreePool (DriverBindingHandleBuffer);
+ *BindingHandle = NULL;
+ return NULL;
+}
+
+/**
+ Return the current TPL.
+
+ @return Current TPL
+
+**/
+EFI_TPL
+GetCurrentTpl (
+ VOID
+ )
+{
+ EFI_TPL Tpl;
+
+ Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ gBS->RestoreTPL (Tpl);
+
+ return Tpl;
+}
+
+
+/**
+ Retrieves the image handle of the platform override driver for a controller in
+ the system from the memory mapping database.
+
+ @param ControllerHandle The device handle of the controller to check if
+ a driver override exists.
+ @param DriverImageHandle On input, the previously returnd driver image handle.
+ On output, a pointer to the next driver handle.
+ Passing in a pointer to NULL, will return the
+ first driver handle for ControllerHandle.
+ @param MappingDataBase Mapping database list entry pointer
+ @param CallerImageHandle The caller driver's image handle, for
+ UpdateFvFileDevicePath use.
+
+ @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not
+ a valid handle. Or DriverImagePath is not a
+ device path that was returned on a previous call
+ to GetDriverPath().
+ @retval EFI_NOT_FOUND A driver override for ControllerHandle was not
+ found.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SUCCESS The driver override for ControllerHandle was
+ returned in DriverImagePath.
+
+**/
+EFI_STATUS
+EFIAPI
+GetDriverFromMapping (
+ IN EFI_HANDLE ControllerHandle,
+ IN OUT EFI_HANDLE *DriverImageHandle,
+ IN LIST_ENTRY *MappingDataBase,
+ IN EFI_HANDLE CallerImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath;
+ BOOLEAN ControllerFound;
+ BOOLEAN ImageFound;
+ EFI_HANDLE *ImageHandleBuffer;
+ UINTN ImageHandleCount;
+ UINTN Index;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+ EFI_HANDLE DriverBindingHandle;
+ BOOLEAN FoundLastReturned;
+ PLATFORM_OVERRIDE_ITEM *OverrideItem;
+ DRIVER_IMAGE_INFO *DriverImageInfo;
+ LIST_ENTRY *OverrideItemListIndex;
+ LIST_ENTRY *ImageInfoListIndex;
+ EFI_DEVICE_PATH_PROTOCOL *TempDriverImagePath;
+ EFI_HANDLE ImageHandle;
+ EFI_HANDLE Handle;
+ EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;
+ EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;
+ UINTN DevicePathSize;
+
+ //
+ // Check that ControllerHandle is a valid handle
+ //
+ if (ControllerHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Get the device path of ControllerHandle
+ //
+ Status = gBS->HandleProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ControllerDevicePath
+ );
+ if (EFI_ERROR (Status) || ControllerDevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Search ControllerDevicePath in MappingDataBase
+ //
+ OverrideItem = NULL;
+ ControllerFound = FALSE;
+ DevicePathSize = GetDevicePathSize (ControllerDevicePath);
+
+ OverrideItemListIndex = GetFirstNode (MappingDataBase);
+ while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
+ OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
+ if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
+ if (CompareMem (
+ ControllerDevicePath,
+ OverrideItem->ControllerDevicePath,
+ DevicePathSize
+ ) == 0
+ ) {
+ ControllerFound = TRUE;
+ break;
+ }
+ }
+ OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
+ }
+
+ if (!ControllerFound) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Passing in a pointer to NULL, will return the first driver device path for ControllerHandle.
+ // Check whether the driverImagePath is not a device path that was returned on a previous call to GetDriverPath().
+ //
+ if (*DriverImageHandle != NULL) {
+ if (*DriverImageHandle != OverrideItem->LastReturnedImageHandle) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // The GetDriverPath() may be called recursively, because it use ConnectDevicePath() internally,
+ // so should check whether there is a dead loop.
+ // Here use a controller device path stack to record all processed controller device path during a GetDriverPath() call,
+ // and check the controller device path whether appear again during the GetDriverPath() call.
+ //
+ if (CheckExistInStack (OverrideItem->ControllerDevicePath)) {
+ //
+ // There is a dependecy dead loop if the ControllerDevicePath appear in stack twice
+ //
+ return EFI_UNSUPPORTED;
+ }
+ PushDevPathStack (OverrideItem->ControllerDevicePath);
+
+ //
+ // Check every override driver, try to load and start them
+ //
+ ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
+ while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
+ DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
+ if (DriverImageInfo->ImageHandle == NULL) {
+ //
+ // Skip if the image is unloadable or unstartable
+ //
+ if ((!DriverImageInfo->UnLoadable) && ((!DriverImageInfo->UnStartable))) {
+ TempDriverImagePath = DriverImageInfo->DriverImagePath;
+ //
+ // If the image device path contains an FV node, check the FV file device path is valid.
+ // If it is invalid, try to return the valid device path.
+ // FV address maybe changes for memory layout adjust from time to time,
+ // use this funciton could promise the FV file device path is right.
+ //
+ Status = UpdateFvFileDevicePath (&TempDriverImagePath, NULL, CallerImageHandle);
+ if (!EFI_ERROR (Status)) {
+ FreePool (DriverImageInfo->DriverImagePath);
+ DriverImageInfo->DriverImagePath = TempDriverImagePath;
+ }
+ //
+ // Get all Loaded Image protocol to check whether the driver image has been loaded and started
+ //
+ ImageFound = FALSE;
+ ImageHandleCount = 0;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiLoadedImageProtocolGuid,
+ NULL,
+ &ImageHandleCount,
+ &ImageHandleBuffer
+ );
+ if (EFI_ERROR (Status) || (ImageHandleCount == 0)) {
+ return EFI_NOT_FOUND;
+ }
+
+ for(Index = 0; Index < ImageHandleCount; Index ++) {
+ //
+ // Get the EFI Loaded Image Device Path Protocol
+ //
+ LoadedImageDevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ ImageHandleBuffer[Index],
+ &gEfiLoadedImageDevicePathProtocolGuid,
+ (VOID **) &LoadedImageDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Maybe not all EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL existed.
+ //
+ continue;
+ }
+
+ DevicePathSize = GetDevicePathSize (DriverImageInfo->DriverImagePath);
+ if (DevicePathSize == GetDevicePathSize (LoadedImageDevicePath)) {
+ if (CompareMem (
+ DriverImageInfo->DriverImagePath,
+ LoadedImageDevicePath,
+ GetDevicePathSize (LoadedImageDevicePath)
+ ) == 0
+ ) {
+ ImageFound = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (ImageFound) {
+ //
+ // Find its related driver binding protocol
+ // Driver binding handle may be different with its driver's Image Handle.
+ //
+ DriverBindingHandle = NULL;
+ DriverBinding = GetBindingProtocolFromImageHandle (
+ ImageHandleBuffer[Index],
+ &DriverBindingHandle
+ );
+ ASSERT (DriverBinding != NULL);
+ DriverImageInfo->ImageHandle = ImageHandleBuffer[Index];
+ } else if (GetCurrentTpl() <= TPL_CALLBACK){
+ //
+ // The driver image has not been loaded and started. Try to load and start it now.
+ // Try to connect all device in the driver image path.
+ //
+ // Note: LoadImage() and StartImage() should be called under CALLBACK TPL in theory, but
+ // since many device need to be connected in CALLBACK level environment( e.g. Usb devices )
+ // and the Fat and Patition driver can endure executing in CALLBACK level in fact, so here permit
+ // to use LoadImage() and StartImage() in CALLBACK TPL.
+ //
+ Status = ConnectDevicePath (DriverImageInfo->DriverImagePath);
+ //
+ // check whether it points to a PCI Option Rom image,
+ // and try to use bus override protocol to get its first option rom image driver
+ //
+ TempDriverImagePath = DriverImageInfo->DriverImagePath;
+ gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDriverImagePath, &Handle);
+ //
+ // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
+ //
+ Status = gBS->HandleProtocol(
+ Handle,
+ &gEfiBusSpecificDriverOverrideProtocolGuid,
+ (VOID **) &BusSpecificDriverOverride
+ );
+ if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
+ ImageHandle = NULL;
+ Status = BusSpecificDriverOverride->GetDriver (
+ BusSpecificDriverOverride,
+ &ImageHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Find its related driver binding protocol
+ // Driver binding handle may be different with its driver's Image handle
+ //
+ DriverBindingHandle = NULL;
+ DriverBinding = GetBindingProtocolFromImageHandle (
+ ImageHandle,
+ &DriverBindingHandle
+ );
+ ASSERT (DriverBinding != NULL);
+ DriverImageInfo->ImageHandle = ImageHandle;
+ }
+ }
+ //
+ // Skip if any device cannot be connected now, future passes through GetDriver() may be able to load that driver.
+ // Only file path media or FwVol Device Path Node remain if all device is connected
+ //
+ TempDriverImagePath = DriverImageInfo->DriverImagePath;
+ gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDriverImagePath, &Handle);
+ if (((DevicePathType (TempDriverImagePath) == MEDIA_DEVICE_PATH) &&
+ (DevicePathSubType (TempDriverImagePath) == MEDIA_FILEPATH_DP)) ||
+ (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempDriverImagePath) != NULL)
+ ) {
+ //
+ // Try to load the driver
+ //
+ TempDriverImagePath = DriverImageInfo->DriverImagePath;
+ Status = gBS->LoadImage (
+ FALSE,
+ CallerImageHandle,
+ TempDriverImagePath,
+ NULL,
+ 0,
+ &ImageHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Try to start the driver
+ //
+ Status = gBS->StartImage (ImageHandle, NULL, NULL);
+ if (EFI_ERROR (Status)){
+ DriverImageInfo->UnStartable = TRUE;
+ DriverImageInfo->ImageHandle = NULL;
+ } else {
+ //
+ // Find its related driver binding protocol
+ // Driver binding handle may be different with its driver's Image handle
+ //
+ DriverBindingHandle = NULL;
+ DriverBinding = GetBindingProtocolFromImageHandle (
+ ImageHandle,
+ &DriverBindingHandle
+ );
+ ASSERT (DriverBinding != NULL);
+ DriverImageInfo->ImageHandle = ImageHandle;
+ }
+ } else {
+ DriverImageInfo->UnLoadable = TRUE;
+ DriverImageInfo->ImageHandle = NULL;
+ }
+ }
+ }
+ FreePool (ImageHandleBuffer);
+ }
+ }
+ ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
+ }
+ //
+ // Finish try to load and start the override driver of a controller, popup the controller's device path
+ //
+ PopDevPathStack (NULL);
+
+ //
+ // return the DriverImageHandle for ControllerHandle
+ //
+ FoundLastReturned = FALSE;
+ ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
+ while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
+ DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
+ if (DriverImageInfo->ImageHandle != NULL) {
+ if ((*DriverImageHandle == NULL) || FoundLastReturned) {
+ //
+ // If DriverImageHandle is NULL, then we just need to return the first driver.
+ // If FoundLastReturned, this means we have just encountered the previously returned driver.
+ // For both cases, we just return the image handle of this driver.
+ //
+ OverrideItem->LastReturnedImageHandle = DriverImageInfo->ImageHandle;
+ *DriverImageHandle = DriverImageInfo->ImageHandle;
+ return EFI_SUCCESS;
+ } else if (*DriverImageHandle == DriverImageInfo->ImageHandle){
+ //
+ // We have found the previously returned driver.
+ //
+ FoundLastReturned = TRUE;
+ }
+ }
+ ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Check mapping database whether already has the mapping info which
+ records the input Controller to input DriverImage.
+
+ @param ControllerDevicePath The controller device path is to be check.
+ @param DriverImageDevicePath The driver image device path is to be check.
+ @param MappingDataBase Mapping database list entry pointer
+ @param DriverInfoNum the controller's total override driver number
+ @param DriverImageNO The driver order number for the input DriverImage.
+ If the DriverImageDevicePath is NULL, DriverImageNO is not set.
+
+ @retval EFI_INVALID_PARAMETER ControllerDevicePath or MappingDataBase is NULL.
+ @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or
+ DriverImageDevicePath is not found in the found DriverImage Info list.
+ @retval EFI_SUCCESS The controller's total override driver number and
+ input DriverImage's order number is correctly return.
+**/
+EFI_STATUS
+EFIAPI
+CheckMapping (
+ IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath OPTIONAL,
+ IN LIST_ENTRY *MappingDataBase,
+ OUT UINT32 *DriverInfoNum OPTIONAL,
+ OUT UINT32 *DriverImageNO OPTIONAL
+ )
+{
+ LIST_ENTRY *OverrideItemListIndex;
+ PLATFORM_OVERRIDE_ITEM *OverrideItem;
+ LIST_ENTRY *ImageInfoListIndex;
+ DRIVER_IMAGE_INFO *DriverImageInfo;
+ BOOLEAN Found;
+ UINT32 ImageNO;
+ UINTN DevicePathSize;
+
+ if (ControllerDevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (MappingDataBase == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Search ControllerDevicePath in MappingDataBase
+ //
+ Found = FALSE;
+ OverrideItem = NULL;
+ OverrideItemListIndex = GetFirstNode (MappingDataBase);
+ while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
+ OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
+ DevicePathSize = GetDevicePathSize (ControllerDevicePath);
+ if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
+ if (CompareMem (
+ ControllerDevicePath,
+ OverrideItem->ControllerDevicePath,
+ DevicePathSize
+ ) == 0
+ ) {
+ Found = TRUE;
+ break;
+ }
+ }
+ OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
+ }
+
+ if (!Found) {
+ //
+ // ControllerDevicePath is not in MappingDataBase
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ ASSERT (OverrideItem->DriverInfoNum != 0);
+ if (DriverInfoNum != NULL) {
+ *DriverInfoNum = OverrideItem->DriverInfoNum;
+ }
+
+ //
+ // If DriverImageDevicePath is NULL, skip checking DriverImageDevicePath
+ // in the controller's Driver Image Info List
+ //
+ if (DriverImageDevicePath == NULL) {
+ return EFI_SUCCESS;
+ }
+ //
+ // return the DriverImageHandle for ControllerHandle
+ //
+ ImageNO = 0;
+ Found = FALSE;
+ ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
+ while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
+ DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
+ ImageNO++;
+ DevicePathSize = GetDevicePathSize (DriverImageDevicePath);
+ if (DevicePathSize == GetDevicePathSize (DriverImageInfo->DriverImagePath)) {
+ if (CompareMem (
+ DriverImageDevicePath,
+ DriverImageInfo->DriverImagePath,
+ GetDevicePathSize (DriverImageInfo->DriverImagePath)
+ ) == 0
+ ) {
+ Found = TRUE;
+ break;
+ }
+ }
+ ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
+ }
+
+ if (!Found) {
+ //
+ // DriverImageDevicePath is not found in the controller's Driver Image Info List
+ //
+ return EFI_NOT_FOUND;
+ } else {
+ if (DriverImageNO != NULL) {
+ *DriverImageNO = ImageNO;
+ }
+ return EFI_SUCCESS;
+ }
+}
+
+
+/**
+ Insert a driver image as a controller's override driver into the mapping database.
+ The driver image's order number is indicated by DriverImageNO.
+
+ @param ControllerDevicePath The controller device path need to add a
+ override driver image item
+ @param DriverImageDevicePath The driver image device path need to be insert
+ @param MappingDataBase Mapping database list entry pointer
+ @param DriverImageNO The inserted order number. If this number is taken,
+ the larger available number will be used.
+
+ @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or DriverImageDevicePath is NULL
+ or MappingDataBase is NULL
+ @retval EFI_ALREADY_STARTED The input Controller to input DriverImage has been
+ recorded into the mapping database.
+ @retval EFI_SUCCESS The Controller and DriverImage are inserted into
+ the mapping database successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+InsertDriverImage (
+ IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath,
+ IN LIST_ENTRY *MappingDataBase,
+ IN UINT32 DriverImageNO
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *OverrideItemListIndex;
+ PLATFORM_OVERRIDE_ITEM *OverrideItem;
+ LIST_ENTRY *ImageInfoListIndex;
+ DRIVER_IMAGE_INFO *DriverImageInfo;
+ BOOLEAN Found;
+ UINT32 ImageNO;
+ UINTN DevicePathSize;
+
+ if (ControllerDevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (DriverImageDevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (MappingDataBase == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If the driver is already in the controller's Driver Image Info List,
+ // just return EFI_ALREADY_STARTED.
+ //
+ Status = CheckMapping (
+ ControllerDevicePath,
+ DriverImageDevicePath,
+ MappingDataBase,
+ NULL,
+ NULL
+ );
+ if (Status == EFI_SUCCESS) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ //
+ // Search the input ControllerDevicePath in MappingDataBase
+ //
+ Found = FALSE;
+ OverrideItem = NULL;
+ OverrideItemListIndex = GetFirstNode (MappingDataBase);
+ while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
+ OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
+ DevicePathSize = GetDevicePathSize (ControllerDevicePath);
+ if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
+ if (CompareMem (
+ ControllerDevicePath,
+ OverrideItem->ControllerDevicePath,
+ DevicePathSize
+ ) == 0
+ ) {
+ Found = TRUE;
+ break;
+ }
+ }
+ OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
+ }
+ //
+ // If cannot find, this is a new controller item
+ // Add the Controller related PLATFORM_OVERRIDE_ITEM structrue in mapping data base
+ //
+ if (!Found) {
+ OverrideItem = AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM));
+ ASSERT (OverrideItem != NULL);
+ OverrideItem->Signature = PLATFORM_OVERRIDE_ITEM_SIGNATURE;
+ OverrideItem->ControllerDevicePath = DuplicateDevicePath (ControllerDevicePath);
+ InitializeListHead (&OverrideItem->DriverInfoList);
+ InsertTailList (MappingDataBase, &OverrideItem->Link);
+ }
+
+ //
+ // Prepare the driver image related DRIVER_IMAGE_INFO structure.
+ //
+ DriverImageInfo = AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO));
+ ASSERT (DriverImageInfo != NULL);
+ DriverImageInfo->Signature = DRIVER_IMAGE_INFO_SIGNATURE;
+ DriverImageInfo->DriverImagePath = DuplicateDevicePath (DriverImageDevicePath);
+ //
+ // Find the driver image wanted order location
+ //
+ ImageNO = 0;
+ Found = FALSE;
+ ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
+ while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
+ if (ImageNO == (DriverImageNO - 1)) {
+ //
+ // find the wanted order location, insert it
+ //
+ InsertTailList (ImageInfoListIndex, &DriverImageInfo->Link);
+ OverrideItem->DriverInfoNum ++;
+ Found = TRUE;
+ break;
+ }
+ ImageNO++;
+ ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
+ }
+
+ if (!Found) {
+ //
+ // if not find the wanted order location, add it as last item of the controller mapping item
+ //
+ InsertTailList (&OverrideItem->DriverInfoList, &DriverImageInfo->Link);
+ OverrideItem->DriverInfoNum ++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Delete a controller's override driver from the mapping database.
+
+ @param ControllerDevicePath The controller device path will be deleted
+ when all drivers images on it are removed.
+ @param DriverImageDevicePath The driver image device path will be delete.
+ If NULL, all driver image will be delete.
+ @param MappingDataBase Mapping database list entry pointer
+
+ @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or MappingDataBase is NULL
+ @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or
+ DriverImageDevicePath is not found in the found DriverImage Info list.
+ @retval EFI_SUCCESS Delete the specified driver successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+DeleteDriverImage (
+ IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath,
+ IN LIST_ENTRY *MappingDataBase
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *OverrideItemListIndex;
+ PLATFORM_OVERRIDE_ITEM *OverrideItem;
+ LIST_ENTRY *ImageInfoListIndex;
+ DRIVER_IMAGE_INFO *DriverImageInfo;
+ BOOLEAN Found;
+ UINTN DevicePathSize;
+
+ if (ControllerDevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (MappingDataBase == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If ControllerDevicePath is not found in mapping database, return EFI_NOT_FOUND.
+ //
+ Status = CheckMapping (
+ ControllerDevicePath,
+ DriverImageDevicePath,
+ MappingDataBase,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Search ControllerDevicePath in MappingDataBase
+ //
+ Found = FALSE;
+ OverrideItem = NULL;
+ OverrideItemListIndex = GetFirstNode (MappingDataBase);
+ while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
+ OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
+ DevicePathSize = GetDevicePathSize (ControllerDevicePath);
+ if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
+ if (CompareMem (
+ ControllerDevicePath,
+ OverrideItem->ControllerDevicePath,
+ DevicePathSize
+ ) == 0
+ ) {
+ Found = TRUE;
+ break;
+ }
+ }
+ OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
+ }
+
+ ASSERT (Found);
+ ASSERT (OverrideItem->DriverInfoNum != 0);
+
+ Found = FALSE;
+ ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
+ while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
+ DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
+ ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
+ if (DriverImageDevicePath != NULL) {
+ //
+ // Search for the specified DriverImageDevicePath and remove it, then break.
+ //
+ DevicePathSize = GetDevicePathSize (DriverImageDevicePath);
+ if (DevicePathSize == GetDevicePathSize (DriverImageInfo->DriverImagePath)) {
+ if (CompareMem (
+ DriverImageDevicePath,
+ DriverImageInfo->DriverImagePath,
+ GetDevicePathSize (DriverImageInfo->DriverImagePath)
+ ) == 0
+ ) {
+ Found = TRUE;
+ FreePool(DriverImageInfo->DriverImagePath);
+ RemoveEntryList (&DriverImageInfo->Link);
+ OverrideItem->DriverInfoNum --;
+ break;
+ }
+ }
+ } else {
+ //
+ // Remove all existing driver image info entries, so no break here.
+ //
+ Found = TRUE;
+ FreePool(DriverImageInfo->DriverImagePath);
+ RemoveEntryList (&DriverImageInfo->Link);
+ OverrideItem->DriverInfoNum --;
+ }
+ }
+
+ //
+ // Confirm all driver image info entries have been removed,
+ // if DriverImageDevicePath is NULL.
+ //
+ if (DriverImageDevicePath == NULL) {
+ ASSERT (OverrideItem->DriverInfoNum == 0);
+ }
+ //
+ // If Override Item has no driver image info entry, then delete this item.
+ //
+ if (OverrideItem->DriverInfoNum == 0) {
+ FreePool(OverrideItem->ControllerDevicePath);
+ RemoveEntryList (&OverrideItem->Link);
+ FreePool (OverrideItem);
+ }
+
+ if (!Found) {
+ //
+ // DriverImageDevicePath is not NULL and cannot be found in the controller's
+ // driver image info list.
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatOverMngr.h b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatOverMngr.h
new file mode 100644
index 0000000000..2d73d0ee6f
--- /dev/null
+++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatOverMngr.h
@@ -0,0 +1,73 @@
+/** @file
+
+ The defintions are required both by Source code and Vfr file.
+ The PLAT_OVER_MNGR_DATA structure, form guid and Ifr question ID are defined.
+
+Copyright (c) 2007 - 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PLAT_OVER_MNGR_H_
+#define _PLAT_OVER_MNGR_H_
+
+#define PLAT_OVER_MNGR_GUID \
+ { \
+ 0x8614567d, 0x35be, 0x4415, {0x8d, 0x88, 0xbd, 0x7d, 0xc, 0x9c, 0x70, 0xc0} \
+ }
+
+//
+// The max number of the supported driver list.
+//
+#define MAX_CHOICE_NUM 0x00ff
+#define UPDATE_DATA_SIZE 0x1000
+
+#define FORM_ID_DEVICE 0x1100
+#define FORM_ID_DRIVER 0x1200
+#define FORM_ID_ORDER 0x1500
+
+#define KEY_VALUE_DEVICE_OFFSET 0x0100
+#define KEY_VALUE_DEVICE_MAX (KEY_VALUE_DEVICE_OFFSET + MAX_CHOICE_NUM)
+
+#define KEY_VALUE_DEVICE_REFRESH 0x1234
+#define KEY_VALUE_DEVICE_FILTER 0x1235
+#define KEY_VALUE_DEVICE_CLEAR 0x1236
+
+#define KEY_VALUE_DRIVER_GOTO_PREVIOUS 0x1300
+#define KEY_VALUE_DRIVER_GOTO_ORDER 0x1301
+
+#define KEY_VALUE_ORDER_GOTO_PREVIOUS 0x2000
+#define KEY_VALUE_ORDER_SAVE_AND_EXIT 0x1800
+
+#define VARSTORE_ID_PLAT_OVER_MNGR 0x1000
+
+#define LABEL_END 0xffff
+
+typedef struct {
+ UINT8 DriSelection[MAX_CHOICE_NUM];
+ UINT8 DriOrder[MAX_CHOICE_NUM];
+ UINT8 PciDeviceFilter;
+} PLAT_OVER_MNGR_DATA;
+
+//
+// Field offset of structure PLAT_OVER_MNGR_DATA
+//
+#define VAR_OFFSET(Field) ((UINTN) &(((PLAT_OVER_MNGR_DATA *) 0)->Field))
+#define DRIVER_SELECTION_VAR_OFFSET (VAR_OFFSET (DriSelection))
+#define DRIVER_ORDER_VAR_OFFSET (VAR_OFFSET (DriOrder))
+
+//
+// Tool automatic generated Question Id start from 1
+// In order to avoid to conflict them, the Driver Selection and Order QuestionID offset is defined from 0x0500.
+//
+#define QUESTION_ID_OFFSET 0x0500
+#define DRIVER_SELECTION_QUESTION_ID (VAR_OFFSET (DriSelection) + QUESTION_ID_OFFSET)
+#define DRIVER_ORDER_QUESTION_ID (VAR_OFFSET (DriOrder) + QUESTION_ID_OFFSET)
+
+#endif
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverride.c b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverride.c
deleted file mode 100644
index 64e9a4d64d..0000000000
--- a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverride.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/** @file
-
-Copyright (c) 2007 - 2009, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include <Uefi.h>
-
-#include <Library/BaseLib.h>
-#include <Library/DebugLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/PlatformDriverOverrideLib.h>
-#include <Protocol/PlatformDriverOverride.h>
-
-LIST_ENTRY mMappingDataBase = INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase);
-BOOLEAN mEnvironmentVariableRead = FALSE;
-EFI_HANDLE mCallerImageHandle = NULL;
-
-/**
- Retrieves the image handle of the platform override driver for a controller in the system.
-
- @param This A pointer to the
- EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL instance.
- @param ControllerHandle The device handle of the controller to check if a
- driver override exists.
- @param DriverImageHandle On input, a pointer to the previous driver image
- handle returned by GetDriver(). On output, a
- pointer to the next driver image handle. Passing
- in a NULL, will return the first driver image
- handle for ControllerHandle.
-
- @retval EFI_SUCCESS The driver override for ControllerHandle was
- returned in DriverImageHandle.
- @retval EFI_NOT_FOUND A driver override for ControllerHandle was not
- found.
- @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not a
- valid handle. DriverImageHandle is not a handle
- that was returned on a previous call to
- GetDriver().
-
-**/
-EFI_STATUS
-EFIAPI
-GetDriver (
- IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN OUT EFI_HANDLE *DriverImageHandle
- )
-{
- EFI_STATUS Status;
-
- //
- // Check that ControllerHandle is a valid handle
- //
- if (ControllerHandle == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Read the environment variable(s) that contain the override mappings from Controller Device Path to
- // a set of Driver Device Paths, and initialize in memory database of the overrides that map Controller
- // Device Paths to an ordered set of Driver Device Paths and Driver Handles. This action is only performed
- // once and finished in first call.
- //
- if (!mEnvironmentVariableRead) {
- mEnvironmentVariableRead = TRUE;
-
- Status = InitOverridesMapping (&mMappingDataBase);
- if (EFI_ERROR (Status)){
- DEBUG ((DEBUG_ERROR, "The status to Get Platform Driver Override Variable is %r\n", Status));
- InitializeListHead (&mMappingDataBase);
- return EFI_NOT_FOUND;
- }
- }
-
- //
- // if the environment variable does not exist, just return not found
- //
- if (IsListEmpty (&mMappingDataBase)) {
- return EFI_NOT_FOUND;
- }
-
- return GetDriverFromMapping (
- ControllerHandle,
- DriverImageHandle,
- &mMappingDataBase,
- mCallerImageHandle
- );
-}
-
-/**
- Retrieves the device path of the platform override driver for a controller in the system.
- This driver doesn't support this API.
-
- @param This A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_
- PROTOCOL instance.
- @param ControllerHandle The device handle of the controller to check if a driver override
- exists.
- @param DriverImagePath On input, a pointer to the previous driver device path returned by
- GetDriverPath(). On output, a pointer to the next driver
- device path. Passing in a pointer to NULL, will return the first
- driver device path for ControllerHandle.
-
- @retval EFI_UNSUPPORTED
-**/
-EFI_STATUS
-EFIAPI
-GetDriverPath (
- IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN OUT EFI_DEVICE_PATH_PROTOCOL **DriverImagePath
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-
-/**
- Used to associate a driver image handle with a device path that was returned on a prior call to the
- GetDriverPath() service. This driver image handle will then be available through the
- GetDriver() service. This driver doesn't support this API.
-
- @param This A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_
- PROTOCOL instance.
- @param ControllerHandle The device handle of the controller.
- @param DriverImagePath A pointer to the driver device path that was returned in a prior
- call to GetDriverPath().
- @param DriverImageHandle The driver image handle that was returned by LoadImage()
- when the driver specified by DriverImagePath was loaded
- into memory.
-
- @retval EFI_UNSUPPORTED
-**/
-EFI_STATUS
-EFIAPI
-DriverLoaded (
- IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *DriverImagePath,
- IN EFI_HANDLE DriverImageHandle
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL mPlatformDriverOverride = {
- GetDriver,
- GetDriverPath,
- DriverLoaded
-};
-
-/**
- Platform Driver Override driver entry point, install the Platform Driver Override Protocol
-
- @param ImageHandle ImageHandle of the loaded driver.
- @param SystemTable Pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The DXE Driver, DXE Runtime Driver, DXE SMM Driver,
- or UEFI Driver exited normally.
- @retval EFI_ALREADY_STARTED A protocol instance has been installed. Not need install again.
-**/
-EFI_STATUS
-EFIAPI
-PlatformDriverOverrideEntry (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_HANDLE Handle;
- EFI_STATUS Status;
- VOID *Instance;
-
- mCallerImageHandle = ImageHandle;
-
- //
- // According to UEFI spec, there can be at most a single instance
- // in the system of the EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL.
- // So here we check the existence.
- //
- Status = gBS->LocateProtocol (
- &gEfiPlatformDriverOverrideProtocolGuid,
- NULL,
- &Instance
- );
- //
- // If there was no error, assume there is an installation and return error
- //
- if (!EFI_ERROR (Status)) {
- return EFI_ALREADY_STARTED;
- }
-
- //
- // Install platform driver override protocol
- //
- Handle = NULL;
- Status = gBS->InstallProtocolInterface (
- &Handle,
- &gEfiPlatformDriverOverrideProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &mPlatformDriverOverride
- );
- ASSERT_EFI_ERROR (Status);
- return EFI_SUCCESS;
-}
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf
index 855fb82a59..59bc3dfed0 100644
--- a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf
+++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf
@@ -1,9 +1,21 @@
#/** @file
-# This driver produces UEFI PLATFORM_DRIVER_OVERRIDE_PROTOCOL if this protocol doesn't exist.
-# It doesn't install again if this protocol exists.
-# It only implements one interface GetDriver of PLATFORM_DRIVER_OVERRIDE_PROTOCOL protocol
-# and doesn't support other two interfaces GetDriverPath, DriverLoaded.
+# This driver produces UEFI PLATFORM_DRIVER_OVERRIDE_PROTOCOL if this protocol doesn't exist.
+# It doesn't install again if this protocol exists.
+# It only implements one interface GetDriver of PLATFORM_DRIVER_OVERRIDE_PROTOCOL protocol
+# and doesn't support other two interfaces GetDriverPath, DriverLoaded.
#
+# This driver also offers an UI interface in device manager to let user configure
+# platform override protocol to override the default algorithm for matching
+# drivers to controllers.
+#
+# The main flow:
+# 1. It dynamicly locate all controller device path.
+# 2. It dynamicly locate all drivers which support binding protocol.
+# 3. It export and dynamicly update two menu to let user select the
+# mapping between drivers to controllers.
+# 4. It save all the mapping info in NV variables for the following boot,
+# which will be consumed by GetDriver API of the produced the platform override protocol.
+#
# Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.
#
# All rights reserved. This program and the accompanying materials
@@ -18,11 +30,12 @@
[Defines]
INF_VERSION = 0x00010005
- BASE_NAME = PlatformDriOverrideDxe
+ BASE_NAME = PlatDriOverrideDxe
FILE_GUID = 35034CE2-A6E5-4fb4-BABE-A0156E9B2549
- MODULE_TYPE = UEFI_DRIVER
+ MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
- ENTRY_POINT = PlatformDriverOverrideEntry
+ ENTRY_POINT = PlatDriOverrideDxeInit
+ UNLOAD_IMAGE = PlatDriOverrideDxeUnload
#
# The following information is for reference only and not required by the build tools.
@@ -31,7 +44,12 @@
#
[Sources.common]
- PlatformDriOverride.c
+ VfrStrings.uni
+ Vfr.vfr
+ PlatDriOverrideDxe.c
+ PlatOverMngr.h
+ PlatDriOverrideLib.c
+ InternalPlatDriOverrideDxe.h
[Packages]
MdePkg/MdePkg.dec
@@ -39,11 +57,43 @@
[LibraryClasses]
BaseLib
- UefiDriverEntryPoint
DebugLib
- PlatformDriverOverrideLib
+ UefiLib
+ UefiDriverEntryPoint
UefiBootServicesTableLib
+ HiiLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ DevicePathLib
+ DxeServicesTableLib
+ UefiRuntimeServicesTableLib
+ PrintLib
+
+[Guids]
+ ## This GUID C Name is not required for build since it is from UefiLib and not directly used by this module source.
+ ## gEfiGlobalVariableGuid ## SOMETIMES_CONSUMED ## Variable:L"PlatformLang" this variable specifies the platform supported language string (RFC 4646 format)
+ ## gEfiGlobalVariableGuid ## SOMETIMES_CONSUMED ## Variable:L"Lang" this variable specifies the platform supported language string (ISO 639-2 format)
+ ##
+ # There could be more than one variables, from PlatDriOver, PlatDriOver1, PlatDriOver2,...
+ #
+ # gEfiCallerIdGuid ## Private ## Variable:L"PlatDriOver"
+ gEfiIfrTianoGuid ## CONSUMES ## Guid
[Protocols]
- gEfiPlatformDriverOverrideProtocolGuid ## PRODUCED
- \ No newline at end of file
+ gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMED (Get Driver Name if ComponentName2Protocol exists)
+ gEfiComponentNameProtocolGuid ## SOMETIMES_CONSUMED (Get Driver Name if ComponentNameProtocol exists and ComponentName2Protocol doesn't exist)
+ gEfiFirmwareVolume2ProtocolGuid ## SOMETIMES_CONSUMED (Get Driver Name from EFI UI section if ComponentName2Protocol and ComponentNameProtocol don't exist)
+ gEfiPciIoProtocolGuid ## SOMETIMES_CONSUMED (Find the PCI device if PciIo protocol is installed)
+ gEfiBusSpecificDriverOverrideProtocolGuid ## SOMETIMES_CONSUMED (Check whether the PCI device contains one or more efi drivers in its option rom by this protocol)
+
+ gEfiDriverBindingProtocolGuid ## SOMETIMES_CONSUMED
+ gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMED
+ gEfiLoadedImageDevicePathProtocolGuid ## SOMETIMES_CONSUMED (Show the drivers in the second page that support DriverBindingProtocol, LoadedImageProtocol and LoadedImageDevicePathProtocol)
+ gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMED (Show the controller device in the first page that support DevicePathProtocol)
+
+ gEfiHiiDatabaseProtocolGuid ## CONSUMED
+ gEfiFormBrowser2ProtocolGuid ## CONSUMED
+ gEfiHiiConfigRoutingProtocolGuid ## CONSUMED
+ gEfiHiiConfigAccessProtocolGuid ## PRODUCED
+ gEfiDevicePathToTextProtocolGuid ## CONSUMED
+ gEfiPlatformDriverOverrideProtocolGuid ## PRODUCED
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/Vfr.vfr b/MdeModulePkg/Universal/PlatformDriOverrideDxe/Vfr.vfr
new file mode 100644
index 0000000000..f00a51007b
--- /dev/null
+++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/Vfr.vfr
@@ -0,0 +1,109 @@
+// *++
+//
+// Copyright (c) 2009, Intel Corporation
+// All rights reserved. This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Module Name:
+//
+// Vfr.vfr
+//
+// Abstract:
+//
+// Platform driver Override manager formset
+//
+//
+// --*/
+
+#include "PlatOverMngr.h"
+
+#define EFI_DISK_DEVICE_CLASS 0x01
+
+formset
+ guid = PLAT_OVER_MNGR_GUID,
+ title = STRING_TOKEN(STR_ENTRY_TITLE),
+ help = STRING_TOKEN(STR_TITLE_HELP),
+ class = EFI_DISK_DEVICE_CLASS,
+ subclass = 0xff,
+
+ varstore PLAT_OVER_MNGR_DATA,
+ varid = VARSTORE_ID_PLAT_OVER_MNGR,
+ name = Data,
+ guid = PLAT_OVER_MNGR_GUID;
+
+ form formid = FORM_ID_DEVICE,
+ title = STRING_TOKEN(STR_TITLE);
+
+ text
+ help = STRING_TOKEN(STR_FIRST_REFRESH_HELP),
+ text = STRING_TOKEN(STR_FIRST_REFRESH),
+ text = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_DEVICE_REFRESH;
+
+ checkbox varid = Data.PciDeviceFilter,
+ prompt = STRING_TOKEN(STR_PCI_DEVICE_FILTER_PROMPT),
+ help = STRING_TOKEN(STR_PCI_DEVICE_FILTER_HELP),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_DEVICE_FILTER,
+ endcheckbox;
+
+ label FORM_ID_DEVICE;
+ label LABEL_END;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ goto FORM_ID_DEVICE,
+ prompt = STRING_TOKEN(STR_CLEAR_ALL),
+ help = STRING_TOKEN(STR_CLEAR_ALL_HELP),
+ flags = INTERACTIVE | RESET_REQUIRED,
+ key = KEY_VALUE_DEVICE_CLEAR;
+ endform;
+
+ form formid = FORM_ID_DRIVER,
+ title = STRING_TOKEN(STR_TITLE);
+
+ goto FORM_ID_DEVICE,
+ prompt = STRING_TOKEN(STR_GOTO_PREVIOUS),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_DRIVER_GOTO_PREVIOUS;
+
+ goto FORM_ID_ORDER,
+ prompt = STRING_TOKEN(STR_TITLE_ORDER),
+ help = STRING_TOKEN(STR_TITLE_ORDER_HELP),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_DRIVER_GOTO_ORDER;
+
+ label FORM_ID_DRIVER;
+ label LABEL_END;
+
+ endform;
+
+ form formid = FORM_ID_ORDER,
+ title = STRING_TOKEN(STR_TITLE);
+
+ goto FORM_ID_DRIVER,
+ prompt = STRING_TOKEN(STR_GOTO_PREVIOUS),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE,
+ key = KEY_VALUE_ORDER_GOTO_PREVIOUS;
+
+ label FORM_ID_ORDER;
+ label LABEL_END;
+
+ subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+ goto FORM_ID_ORDER,
+ prompt = STRING_TOKEN(STR_SAVE_AND_EXIT),
+ help = STRING_TOKEN(STR_NULL_STRING),
+ flags = INTERACTIVE | RESET_REQUIRED,
+ key = KEY_VALUE_ORDER_SAVE_AND_EXIT;
+ endform;
+
+endformset;
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/VfrStrings.uni b/MdeModulePkg/Universal/PlatformDriOverrideDxe/VfrStrings.uni
new file mode 100644
index 0000000000..c30fb5c4de
--- /dev/null
+++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/VfrStrings.uni
Binary files differ