diff options
Diffstat (limited to 'MdeModulePkg')
12 files changed, 2720 insertions, 2 deletions
diff --git a/MdeModulePkg/Include/Guid/OverrideVariable.h b/MdeModulePkg/Include/Guid/OverrideVariable.h new file mode 100644 index 0000000000..673813a580 --- /dev/null +++ b/MdeModulePkg/Include/Guid/OverrideVariable.h @@ -0,0 +1,34 @@ +/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+ OverrideVariable.h
+
+Abstract:
+
+ Platform Override Variable Guid definitions
+
+--*/
+
+#ifndef __EFI_OVERRIDE_VARIABLE_GUID_H__
+#define __EFI_OVERRIDE_VARIABLE_GUID_H__
+
+//
+// This guid is used for a platform driver override variable
+//
+#define EFI_OVERRIDE_VARIABLE_GUID \
+ { 0x8e3d4ad5, 0xf762, 0x438a, { 0xa1, 0xc1, 0x5b, 0x9f, 0xe6, 0x8c, 0x6b, 0x15 }}
+
+extern EFI_GUID gEfiOverrideVariableGuid;
+
+
+#endif // #ifndef __EFI_OVERRIDE_VARIABLE_GUID_H__
diff --git a/MdeModulePkg/Include/Library/PlatDriOverLib.h b/MdeModulePkg/Include/Library/PlatDriOverLib.h new file mode 100644 index 0000000000..8e6ab174d7 --- /dev/null +++ b/MdeModulePkg/Include/Library/PlatDriOverLib.h @@ -0,0 +1,255 @@ +/** @file + +Copyright (c) 2007, 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: + + PlatDriOverLib.h + +Abstract: + + +**/ + +#ifndef _PLAT_DRI_OVER_LIB_H_ +#define _PLAT_DRI_OVER_LIB_H_ + +#include <PiDxe.h> +#include <Protocol/PlatformDriverOverride.h> +#include <Protocol/DevicePath.h> +#include <Library/BaseLib.h> + +#include <VariableFormat.h> + +/**
+ Install the Platform Driver Override Protocol, and ensure there is only one Platform Driver Override Protocol
+ in the system.
+
+ @param gPlatformDriverOverride PlatformDriverOverride protocol interface which
+ needs to be installed
+
+ @retval EFI_ALREADY_STARTED There has been a Platform Driver Override
+ Protocol in the system, cannot install it again.
+ @retval Other Returned by InstallProtocolInterface
+
+**/ +EFI_STATUS +EFIAPI +InstallPlatformDriverOverrideProtocol ( + EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *gPlatformDriverOverride + ); + +/**
+ 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 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 multi variables to store
+ // large mapping infos.
+ // The variable(s) name rule is PlatDriOver, PlatDriOver1, PlatDriOver2, ....
+ //
+ UINT32 NotEnd;
+ //
+ // 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; //EFI_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 SIGNATURE;
+ UINT32 DriverNum;
+ EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[];
+ EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
+ EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
+ EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
+ ......
+ }
+ typedef struct _PLATFORM_OVERRIDE_ITEM{
+ UINTN Signature; //EFI_SIGNATURE_32('p','d','o','i')
+ LIST_ENTRY Link;
+ UINT32 DriverInfoNum;
+ EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath;
+ LIST_ENTRY DriverInfoList; //DRIVER_IMAGE_INFO List
+ } PLATFORM_OVERRIDE_ITEM;
+ typedef struct _DRIVER_IMAGE_INFO{
+ UINTN Signature; //EFI_SIGNATURE_32('p','d','i','i')
+ LIST_ENTRY Link;
+ EFI_HANDLE ImageHandle;
+ EFI_DEVICE_PATH_PROTOCOL *DriverImagePath;
+ BOOLEAN UnLoadable;
+ BOOLEAN UnStartable;
+ } DRIVER_IMAGE_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)
+
+ @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 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 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_PLATFORM_DRIVER_OVERRIDE_PROTOCOL * This, + IN EFI_HANDLE ControllerHandle, + IN OUT EFI_HANDLE * DriverImageHandle, + IN LIST_ENTRY * MappingDataBase, + IN EFI_HANDLE CallerImageHandle + ); + +EFI_STATUS +EFIAPI +DeleteOverridesVariables ( + VOID + ); + +/**
+ Check mapping database whether already has the mapping info which
+ records the input Controller to input DriverImage.
+ If has, the controller's total override driver number and input DriverImage's order number is return.
+
+ @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 DriverInfoNum the controller's total override driver number
+ @param DriverImageNO The inserted order number
+
+ @return EFI_INVALID_PARAMETER
+ @return EFI_NOT_FOUND
+ @return EFI_SUCCESS
+
+**/ +EFI_STATUS +EFIAPI +CheckMapping ( + IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath, + IN LIST_ENTRY * MappingDataBase, + OUT UINT32 *DriverInfoNum, + OUT UINT32 *DriverImageNO + ); + +/**
+ 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
+
+ @return EFI_INVALID_PARAMETER
+ @return EFI_ALREADY_STARTED
+ @return EFI_SUCCESS
+
+**/ +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 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
+
+ @return EFI_INVALID_PARAMETER
+ @return EFI_NOT_FOUND
+ @return EFI_SUCCESS
+
+**/ +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/Library/DxePlatDriOverLib/DxePlatDriOverLib.inf b/MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.inf new file mode 100644 index 0000000000..1ba2d7887b --- /dev/null +++ b/MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.inf @@ -0,0 +1,65 @@ +#/** @file
+# Component name for module PlatDriOverLib
+#
+# FIX ME!
+# Copyright (c) 2007, Intel Corporation. All rights reserved.
+#
+# 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.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatDriOverLib
+ FILE_GUID = 8bd8d711-2736-46d7-8c81-5de68e0a9e88
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatDriOverLib
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ PlatDriOver.h
+ PlatDriOverLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ DxeServicesTableLib
+ MemoryAllocationLib
+ DevicePathLib
+ BaseLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+
+[Guids]
+ gEfiOverrideVariableGuid # ALWAYS_CONSUMED
+
+[Protocols]
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiLoadedImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiPlatformDriverOverrideProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiBusSpecificDriverOverrideProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiDriverBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
diff --git a/MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.msa b/MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.msa new file mode 100644 index 0000000000..f01088e875 --- /dev/null +++ b/MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.msa @@ -0,0 +1,94 @@ +<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>PlatDriOverLib</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>8bd8d711-2736-46d7-8c81-5de68e0a9e88</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component name for module PlatDriOverLib</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>
+ <License>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.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>PlatDriOverLib</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_PRODUCED">
+ <Keyword>PlatDriOverLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PrintLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiRuntimeServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DevicePathLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DxeServicesTableLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>PlatDriOverLib.c</Filename>
+ <Filename>PlatDriOver.h</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiDriverBindingProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiBusSpecificDriverOverrideProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiPlatformDriverOverrideProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiLoadedImageProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiFirmwareVolumeProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiFirmwareVolume2ProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ </Externs>
+</ModuleSurfaceArea>
\ No newline at end of file diff --git a/MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOver.h b/MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOver.h new file mode 100644 index 0000000000..331a9bc5cc --- /dev/null +++ b/MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOver.h @@ -0,0 +1,121 @@ +/** @file + +Copyright (c) 2007, 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: + + PlatDriOver.h + +Abstract: + + +**/ + +#ifndef _PLAT_DRI_OVER_H_ +#define _PLAT_DRI_OVER_H_ + +#include <PiDxe.h> + +#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/PlatformDriverOverride.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/BusSpecificDriverOverride.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h> +#include <Library/PlatDriOverLib.h>
+ +#include <Guid/OverrideVariable.h> + + +#define PLATFORM_OVERRIDE_ITEM_SIGNATURE EFI_SIGNATURE_32('p','d','o','i') + typedef struct _PLATFORM_OVERRIDE_ITEM{ + UINTN Signature; + LIST_ENTRY Link; + UINT32 DriverInfoNum; + EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath; + LIST_ENTRY DriverInfoList; //DRIVER_IMAGE_INFO List + EFI_HANDLE LastReturnedImageHandle; +} PLATFORM_OVERRIDE_ITEM; + +#define DRIVER_IMAGE_INFO_SIGNATURE EFI_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 EFI_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; + +EFI_STATUS +EFIAPI +PushDevPathStack ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +EFI_STATUS +EFIAPI +PopDevPathStack ( + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +BOOLEAN +EFIAPI +CheckExistInStack ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +EFI_STATUS +EFIAPI +UpdateFvFileDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath, + IN EFI_GUID *FileGuid, + IN EFI_HANDLE CallerImageHandle + ); + +VOID * +GetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VariableSize + ); + +EFI_STATUS +ConnectDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect + ); + +EFI_STATUS +BdsConnectDeviceByPciClassType ( + UINT8 ClassType, + UINT8 SubClassCode, + UINT8 PI, + BOOLEAN Recursive + ); + +#endif diff --git a/MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOverLib.c b/MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOverLib.c new file mode 100644 index 0000000000..d32715bb40 --- /dev/null +++ b/MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOverLib.c @@ -0,0 +1,1800 @@ +/** @file
+
+Copyright (c) 2007, 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:
+
+ PlatDriOverLib.c
+
+Abstract:
+
+
+**/
+
+#include "PlatDriOver.h"
+
+STATIC LIST_ENTRY mDevicePathStack = INITIALIZE_LIST_HEAD_VARIABLE (mDevicePathStack);
+
+
+/**
+ Install the Platform Driver Override Protocol, and ensure there is only one Platform Driver Override Protocol
+ in the system.
+
+ @param gPlatformDriverOverride PlatformDriverOverride protocol interface which
+ needs to be installed
+
+ @retval EFI_ALREADY_STARTED There has been a Platform Driver Override
+ Protocol in the system, cannot install it again.
+ @retval Other Returned by InstallProtocolInterface
+
+**/
+EFI_STATUS
+EFIAPI
+InstallPlatformDriverOverrideProtocol (
+ EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *gPlatformDriverOverride
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+
+ //
+ // There will be only one platform driver override protocol in the system
+ // If there is another out there, someone is trying to install us again,
+ // Fail that scenario.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPlatformDriverOverrideProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ //
+ // If there was no error, assume there is an installation and return error
+ //
+ if (!EFI_ERROR (Status)) {
+ if (HandleBuffer != NULL) {
+ gBS->FreePool (HandleBuffer);
+ }
+ return EFI_ALREADY_STARTED;
+ }
+
+ //
+ // Install platform driver override protocol
+ //
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiPlatformDriverOverrideProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ gPlatformDriverOverride
+ );
+ return Status;
+}
+
+
+/**
+ 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
+ )
+{
+ LIST_ENTRY *OverrideItemListIndex;
+ LIST_ENTRY *ImageInfoListIndex;
+ PLATFORM_OVERRIDE_ITEM *OverrideItem;
+ DRIVER_IMAGE_INFO *DriverImageInfo;
+
+ if (MappingDataBase == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OverrideItemListIndex = MappingDataBase->ForwardLink;
+ while (OverrideItemListIndex != MappingDataBase){
+ OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
+ //
+ // Free PLATFORM_OVERRIDE_ITEM.ControllerDevicePath[]
+ //
+ if (OverrideItem->ControllerDevicePath != NULL){
+ FreePool(OverrideItem->ControllerDevicePath);
+ }
+
+ ImageInfoListIndex = OverrideItem->DriverInfoList.ForwardLink;
+ while (ImageInfoListIndex != &OverrideItem->DriverInfoList){
+ //
+ // Free all 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 = ImageInfoListIndex->ForwardLink;
+ RemoveEntryList (&DriverImageInfo->Link);
+ FreePool (DriverImageInfo);
+ }
+ //
+ // Free PLATFORM_OVERRIDE_ITEM itself
+ //
+ OverrideItemListIndex = OverrideItemListIndex->ForwardLink;
+ RemoveEntryList (&OverrideItem->Link);
+ FreePool (OverrideItem);
+ }
+
+ InitializeListHead (MappingDataBase);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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 multi variables to store
+ // large mapping infos.
+ // The variable(s) name rule is PlatDriOver, PlatDriOver1, PlatDriOver2, ....
+ //
+ UINT32 NotEnd;
+ //
+ // 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; //EFI_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 SIGNATURE;
+ UINT32 DriverNum;
+ EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[];
+ EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
+ EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
+ EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[];
+ ......
+ }
+ typedef struct _PLATFORM_OVERRIDE_ITEM{
+ UINTN Signature; //EFI_SIGNATURE_32('p','d','o','i')
+ LIST_ENTRY Link;
+ UINT32 DriverInfoNum;
+ EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath;
+ LIST_ENTRY DriverInfoList; //DRIVER_IMAGE_INFO List
+ } PLATFORM_OVERRIDE_ITEM;
+ typedef struct _DRIVER_IMAGE_INFO{
+ UINTN Signature; //EFI_SIGNATURE_32('p','d','i','i')
+ LIST_ENTRY Link;
+ EFI_HANDLE ImageHandle;
+ EFI_DEVICE_PATH_PROTOCOL *DriverImagePath;
+ BOOLEAN UnLoadable;
+ BOOLEAN UnStartable;
+ } DRIVER_IMAGE_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
+ )
+{
+ 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;
+ }
+
+ VariableNum = 0;
+ Corrupted = FALSE;
+ //
+ // Check the environment variable(s) that contain the override mappings .
+ //
+ VariableBuffer = GetVariableAndSize (L"PlatDriOver", &gEfiOverrideVariableGuid, &BufferSize);
+ ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0);
+ VariableNum ++;
+ if (VariableBuffer == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ do {
+ VariableIndex = VariableBuffer;
+ NotEnd = *(UINT32*) VariableIndex;
+ VariableIndex = VariableIndex + sizeof (UINT32);
+ while (VariableIndex < ((UINT8 *)VariableBuffer + BufferSize)) {
+ OverrideItem = AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM));
+ ASSERT (OverrideItem != NULL);
+ OverrideItem->Signature = PLATFORM_OVERRIDE_ITEM_SIGNATURE;
+ InitializeListHead (&OverrideItem->DriverInfoList);
+ //
+ // Check SIGNATURE
+ //
+ Signature = *(UINT32 *) VariableIndex;
+ VariableIndex = VariableIndex + sizeof (UINT32);
+ if (Signature != PLATFORM_OVERRIDE_ITEM_SIGNATURE) {
+ FreePool (OverrideItem);
+ Corrupted = TRUE;
+ break;
+ }
+ //
+ // 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 DriverDevicePath[]
+ //
+ for (Index = 0; Index < DriverNumber; Index++) {
+ 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 has other variable(PlatDriOver1, PlatDriOver2, PlatDriOver3.....), get them.
+ // NotEnd indicate whether current variable is the end variable.
+ //
+ if (NotEnd != 0) {
+ UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum);
+ VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiOverrideVariableGuid, &BufferSize);
+ ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0);
+ VariableNum ++;
+ 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 a list entry point to 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;
+
+
+ NeededSize = 0;
+ OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
+ NeededSize += sizeof (UINT32); //UINT32 SIGNATURE;
+ NeededSize += sizeof (UINT32); //UINT32 DriverNum;
+ NeededSize += GetDevicePathSize (OverrideItem->ControllerDevicePath); // ControllerDevicePath
+ //
+ // Align the controller device path
+ //
+ NeededSize += ((sizeof(UINT32) - ((UINTN) GetDevicePathSize (OverrideItem->ControllerDevicePath))) \
+ & (sizeof(UINT32) - 1));
+ ImageInfoListIndex = OverrideItem->DriverInfoList.ForwardLink;
+ while (ImageInfoListIndex != &OverrideItem->DriverInfoList){
+ DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
+ NeededSize += GetDevicePathSize (DriverImageInfo->DriverImagePath); //DriverDevicePath
+ //
+ // Align the driver image device path
+ //
+ NeededSize += ((sizeof(UINT32) - ((UINTN) GetDevicePathSize (DriverImageInfo->DriverImagePath))) \
+ & (sizeof(UINT32) - 1));
+ ImageInfoListIndex = ImageInfoListIndex->ForwardLink;
+ }
+
+ return NeededSize;
+}
+
+
+
+/**
+ Save the memory mapping database into NV environment variable(s)
+
+ @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
+ )
+{
+ 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;
+ UINTN SavedSize;
+ UINT64 MaximumVariableStorageSize;
+ UINT64 RemainingVariableStorageSize;
+ UINT64 MaximumVariableSize;
+ UINTN OneItemNeededSize;
+
+ if (MappingDataBase == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (MappingDataBase->ForwardLink == MappingDataBase) {
+ Status = DeleteOverridesVariables ();
+ 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 = MappingDataBase->ForwardLink;
+ while (OverrideItemListIndex != MappingDataBase) {
+ //
+ // Try to find the most proper variable size which <= MaximumVariableSize, but can contain mapping info as much as possible
+ //
+ VariableNeededSize = 0;
+ VariableNeededSize += sizeof (UINT32); //BOOLEAN NotEnd;
+ ItemIndex = OverrideItemListIndex;
+ NotEnd = FALSE;
+
+ while (ItemIndex != MappingDataBase){
+ OneItemNeededSize = GetOneItemNeededSize (ItemIndex);
+ if ((VariableNeededSize +
+ OneItemNeededSize +
+ sizeof (VARIABLE_HEADER) +
+ StrSize (L"PlatDriOver ")
+ ) >= MaximumVariableSize
+ ) {
+ NotEnd = TRUE;
+ break;
+ }
+
+ VariableNeededSize += GetOneItemNeededSize (ItemIndex);
+ ItemIndex = ItemIndex->ForwardLink;
+ }
+
+ if (NotEnd) {
+ 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 ((UINTN) VariableBuffer % sizeof(UINTN) == 0);
+
+ //
+ // Fill the variable buffer according to MappingDataBase
+ //
+ SavedSize = 0;
+ VariableIndex = VariableBuffer;
+ *(UINT32 *) VariableIndex = NotEnd;
+ VariableIndex += sizeof (UINT32); // pass NoEnd
+ SavedSize += sizeof (UINT32);
+ //
+ // 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
+ SavedSize += sizeof (UINT32);
+
+ OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
+ *(UINT32 *) VariableIndex = OverrideItem->DriverInfoNum;
+ VariableIndex += sizeof (UINT32); // pass DriverNum
+ SavedSize += sizeof (UINT32);
+
+ CopyMem (VariableIndex, OverrideItem->ControllerDevicePath, GetDevicePathSize (OverrideItem->ControllerDevicePath));
+ VariableIndex += GetDevicePathSize (OverrideItem->ControllerDevicePath); // pass ControllerDevicePath
+ SavedSize += GetDevicePathSize (OverrideItem->ControllerDevicePath);
+
+ //
+ // Align the VariableIndex since the controller device path may not be aligned
+ //
+ SavedSize += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
+ VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
+
+ ImageInfoListIndex = OverrideItem->DriverInfoList.ForwardLink;
+ while (ImageInfoListIndex != &OverrideItem->DriverInfoList){
+ DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
+ CopyMem (VariableIndex, DriverImageInfo->DriverImagePath, GetDevicePathSize (DriverImageInfo->DriverImagePath));
+ VariableIndex += GetDevicePathSize (DriverImageInfo->DriverImagePath); // pass DriverImageDevicePath
+ SavedSize += GetDevicePathSize (DriverImageInfo->DriverImagePath);
+ //
+ // Align the VariableIndex since the driver image device path may not be aligned
+ //
+ SavedSize += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
+ VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
+ ImageInfoListIndex = ImageInfoListIndex->ForwardLink;
+ }
+
+ OverrideItemListIndex = OverrideItemListIndex->ForwardLink;
+ }
+
+ ASSERT (SavedSize == VariableNeededSize);
+
+ if (NumIndex == 0) {
+ UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver");
+ } else {
+ UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", NumIndex );
+ }
+
+ Status = gRT->SetVariable (
+ OverrideVariableName,
+ &gEfiOverrideVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ VariableNeededSize,
+ VariableBuffer
+ );
+ ASSERT (!EFI_ERROR(Status));
+
+ NumIndex ++;
+ FreePool (VariableBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Retrieves the image handle of the platform override driver for a controller in the system from the memory mapping database.
+
+ @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 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_PLATFORM_DRIVER_OVERRIDE_PROTOCOL * This,
+ 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_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+ 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 *LoadedImageHandleDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TatalFilePath;
+ EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;
+ UINTN DevicePathSize;
+
+ //
+ // Check that ControllerHandle is a valid handle
+ //
+ if (ControllerHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ 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;
+ OverrideItemListIndex = MappingDataBase->ForwardLink;
+ while (OverrideItemListIndex != MappingDataBase){
+ OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
+ DevicePathSize = GetDevicePathSize (ControllerDevicePath);
+ if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
+ if (CompareMem (
+ ControllerDevicePath,
+ OverrideItem->ControllerDevicePath,
+ GetDevicePathSize (OverrideItem->ControllerDevicePath)
+ ) == 0
+ ) {
+ ControllerFound = TRUE;
+ break;
+ }
+
+ }
+ OverrideItemListIndex = OverrideItemListIndex->ForwardLink;
+ }
+
+ 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() maybe 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 = OverrideItem->DriverInfoList.ForwardLink;
+ while (ImageInfoListIndex != &OverrideItem->DriverInfoList){
+ 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 contain a 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 ++) {
+ Status = gBS->HandleProtocol (
+ ImageHandleBuffer[Index],
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Get the driver image total file path
+ //
+ LoadedImageHandleDevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ LoadedImage->DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &LoadedImageHandleDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Maybe Not all LoadedImage->DeviceHandle has valid value. Skip the invalid image.
+ //
+ continue;
+ }
+
+ TatalFilePath = AppendDevicePath (LoadedImageHandleDevicePath, LoadedImage->FilePath);
+
+ DevicePathSize = GetDevicePathSize (DriverImageInfo->DriverImagePath);
+ if (DevicePathSize == GetDevicePathSize (TatalFilePath)) {
+ if (CompareMem (
+ DriverImageInfo->DriverImagePath,
+ TatalFilePath,
+ GetDevicePathSize (TatalFilePath)
+ ) == 0
+ ) {
+ ImageFound = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (ImageFound) {
+ Status = gBS->HandleProtocol (
+ ImageHandleBuffer[Index],
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **) &DriverBinding
+ );
+ ASSERT (!EFI_ERROR (Status));
+ DriverImageInfo->ImageHandle = ImageHandleBuffer[Index];
+ } else {
+ //
+ // The driver image has not been loaded and started, need try to load and start it now
+ // Try to connect all device in the driver image path
+ //
+ 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)) {
+ Status = gBS->HandleProtocol (
+ ImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **) &DriverBinding
+ );
+ ASSERT (!EFI_ERROR (Status));
+ 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 {
+ Status = gBS->HandleProtocol (
+ ImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **) &DriverBinding
+ );
+ ASSERT (!EFI_ERROR (Status));
+ DriverImageInfo->ImageHandle = ImageHandle;
+ }
+ } else {
+ DriverImageInfo->UnLoadable = TRUE;
+ DriverImageInfo->ImageHandle = NULL;
+ }
+ }
+ }
+ FreePool (ImageHandleBuffer);
+ }
+ }
+ ImageInfoListIndex = ImageInfoListIndex->ForwardLink;
+ }
+ //
+ // 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 = OverrideItem->DriverInfoList.ForwardLink;
+ while (ImageInfoListIndex != &OverrideItem->DriverInfoList){
+ DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
+ if (DriverImageInfo->ImageHandle != NULL) {
+ if ((*DriverImageHandle == NULL) || FoundLastReturned) {
+ OverrideItem->LastReturnedImageHandle = DriverImageInfo->ImageHandle;
+ *DriverImageHandle = DriverImageInfo->ImageHandle;
+ return EFI_SUCCESS;
+ } else if (*DriverImageHandle == DriverImageInfo->ImageHandle){
+ FoundLastReturned = TRUE;
+ }
+ }
+ ImageInfoListIndex = ImageInfoListIndex->ForwardLink;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Check mapping database whether already has the mapping info which
+ records the input Controller to input DriverImage.
+ If has, the controller's total override driver number and input DriverImage's order number is return.
+
+ @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 DriverInfoNum the controller's total override driver number
+ @param DriverImageNO The inserted order number
+
+ @return EFI_INVALID_PARAMETER
+ @return EFI_NOT_FOUND
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+CheckMapping (
+ IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath,
+ IN LIST_ENTRY * MappingDataBase,
+ OUT UINT32 *DriverInfoNum,
+ OUT UINT32 *DriverImageNO
+ )
+{
+ LIST_ENTRY *OverrideItemListIndex;
+ PLATFORM_OVERRIDE_ITEM *OverrideItem;
+ LIST_ENTRY *ImageInfoListIndex;
+ DRIVER_IMAGE_INFO *DriverImageInfo;
+ BOOLEAN Found;
+ UINT32 ImageNO;
+ UINTN DevicePathSize;
+
+ //
+ // Check that ControllerHandle is a valid handle
+ //
+ if (ControllerDevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (MappingDataBase == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Search ControllerDevicePath in MappingDataBase
+ //
+ Found = FALSE;
+ OverrideItem = NULL;
+ OverrideItemListIndex = MappingDataBase->ForwardLink;
+ while (OverrideItemListIndex != MappingDataBase){
+ OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
+ DevicePathSize = GetDevicePathSize (ControllerDevicePath);
+ if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
+ if (CompareMem (
+ ControllerDevicePath,
+ OverrideItem->ControllerDevicePath,
+ GetDevicePathSize (OverrideItem->ControllerDevicePath)
+ ) == 0
+ ) {
+ Found = TRUE;
+ break;
+ }
+ }
+ OverrideItemListIndex = OverrideItemListIndex->ForwardLink;
+ }
+
+ if (!Found) {
+ return EFI_NOT_FOUND;
+ }
+
+ ASSERT (OverrideItem->DriverInfoNum != 0);
+ if (DriverInfoNum != NULL) {
+ *DriverInfoNum = OverrideItem->DriverInfoNum;
+ }
+
+
+ if (DriverImageDevicePath == NULL) {
+ return EFI_SUCCESS;
+ }
+ //
+ // return the DriverImageHandle for ControllerHandle
+ //
+ ImageNO = 0;
+ Found = FALSE;
+ ImageInfoListIndex = OverrideItem->DriverInfoList.ForwardLink;
+ while (ImageInfoListIndex != &OverrideItem->DriverInfoList){
+ 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 = ImageInfoListIndex->ForwardLink;
+ }
+
+ if (!Found) {
+ 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
+
+ @return EFI_INVALID_PARAMETER
+ @return EFI_ALREADY_STARTED
+ @return EFI_SUCCESS
+
+**/
+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;
+
+ //
+ // Check that ControllerHandle is a valid handle
+ //
+ if (ControllerDevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (DriverImageDevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (MappingDataBase == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ 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 = MappingDataBase->ForwardLink;
+ while (OverrideItemListIndex != MappingDataBase){
+ OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
+ DevicePathSize = GetDevicePathSize (ControllerDevicePath);
+ if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
+ if (CompareMem (
+ ControllerDevicePath,
+ OverrideItem->ControllerDevicePath,
+ GetDevicePathSize (OverrideItem->ControllerDevicePath)
+ ) == 0
+ ) {
+ Found = TRUE;
+ break;
+ }
+ }
+ OverrideItemListIndex = OverrideItemListIndex->ForwardLink;
+ }
+ //
+ // 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 wantted order location
+ //
+ ImageNO = 0;
+ Found = FALSE;
+ ImageInfoListIndex = OverrideItem->DriverInfoList.ForwardLink;
+ while (ImageInfoListIndex != &OverrideItem->DriverInfoList){
+ if (ImageNO == (DriverImageNO - 1)) {
+ //
+ // find the wantted order location, insert it
+ //
+ InsertTailList (ImageInfoListIndex, &DriverImageInfo->Link);
+ OverrideItem->DriverInfoNum ++;
+ Found = TRUE;
+ break;
+ }
+ //DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
+ ImageNO++;
+ ImageInfoListIndex = ImageInfoListIndex->ForwardLink;
+ }
+
+ if (!Found) {
+ //
+ // if not find the wantted 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 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
+
+ @return EFI_INVALID_PARAMETER
+ @return EFI_NOT_FOUND
+ @return EFI_SUCCESS
+
+**/
+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;
+
+ //
+ // Check that ControllerHandle is a valid handle
+ //
+ if (ControllerDevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (MappingDataBase == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = CheckMapping (
+ ControllerDevicePath,
+ DriverImageDevicePath,
+ MappingDataBase,
+ NULL,
+ NULL
+ );
+ if (Status == EFI_NOT_FOUND) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Search ControllerDevicePath in MappingDataBase
+ //
+ Found = FALSE;
+ OverrideItem = NULL;
+ OverrideItemListIndex = MappingDataBase->ForwardLink;
+ while (OverrideItemListIndex != MappingDataBase){
+ OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
+ DevicePathSize = GetDevicePathSize (ControllerDevicePath);
+ if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
+ if (CompareMem (
+ ControllerDevicePath,
+ OverrideItem->ControllerDevicePath,
+ GetDevicePathSize (OverrideItem->ControllerDevicePath)
+ ) == 0
+ ) {
+ Found = TRUE;
+ break;
+ }
+ }
+ OverrideItemListIndex = OverrideItemListIndex->ForwardLink;
+ }
+
+ ASSERT (Found);
+ ASSERT (OverrideItem->DriverInfoNum != 0);
+ //
+ //
+ //
+ Found = FALSE;
+ ImageInfoListIndex = OverrideItem->DriverInfoList.ForwardLink;
+ while (ImageInfoListIndex != &OverrideItem->DriverInfoList){
+ DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
+ ImageInfoListIndex = ImageInfoListIndex->ForwardLink;
+ if (DriverImageDevicePath != NULL) {
+ 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 {
+ Found = TRUE;
+ FreePool(DriverImageInfo->DriverImagePath);
+ RemoveEntryList (&DriverImageInfo->Link);
+ OverrideItem->DriverInfoNum --;
+ }
+ }
+
+ if (DriverImageDevicePath == NULL) {
+ ASSERT (OverrideItem->DriverInfoNum == 0);
+ }
+
+ if (OverrideItem->DriverInfoNum == 0) {
+ FreePool(OverrideItem->ControllerDevicePath);
+ RemoveEntryList (&OverrideItem->Link);
+ FreePool (OverrideItem);
+ }
+
+ if (!Found) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Deletes all environment variable(s) that contain the override mappings from Controller Device Path to
+ a set of Driver Device Paths.
+
+ None
+
+ @return EFI_SUCCESS
+
+**/
+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", &gEfiOverrideVariableGuid, &BufferSize);
+ VariableNum ++;
+ if (VariableBuffer == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Check NotEnd to get all PlatDriOverX variable(s)
+ //
+ while (*(UINT32*)VariableBuffer) {
+ UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum);
+ VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiOverrideVariableGuid, &BufferSize);
+ VariableNum ++;
+ ASSERT (VariableBuffer != NULL);
+ }
+
+ Status = gRT->SetVariable (
+ L"PlatDriOver",
+ &gEfiOverrideVariableGuid,
+ 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,
+ &gEfiOverrideVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ 0,
+ NULL
+ );
+ ASSERT (!EFI_ERROR (Status));
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Push a controller device path into a globle device path list
+
+ @param ControllerDevicePath The controller device path need to push into
+ stack
+
+ @return EFI_SUCCESS
+
+**/
+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 ControllerDevicePath The controller device path retrieved from stack
+
+ @return EFI_SUCCESS
+ @return EFI_NOT_FOUND
+
+**/
+EFI_STATUS
+EFIAPI
+PopDevPathStack (
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ DEVICE_PATH_STACK_ITEM *DevicePathStackItem;
+ LIST_ENTRY *ItemListIndex;
+
+ ItemListIndex = mDevicePathStack.BackLink;
+ 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 ControllerDevicePath The controller device path need to check
+
+ @return True
+ @return False
+
+**/
+BOOLEAN
+EFIAPI
+CheckExistInStack (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ DEVICE_PATH_STACK_ITEM *DevicePathStackItem;
+ LIST_ENTRY *ItemListIndex;
+ BOOLEAN Found;
+ UINTN DevicePathSize;
+
+ Found = FALSE;
+ 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,
+ GetDevicePathSize (DevicePathStackItem->DevicePath)
+ ) == 0
+ ) {
+ Found = TRUE;
+ break;
+ }
+ }
+ ItemListIndex = ItemListIndex->BackLink;
+ }
+
+ return Found;
+}
+
+
+/**
+ According to a file guild, 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 need to check
+ on output, the updated valid Fv file device path
+ @param FileGuid the Fv file guild
+ @param CallerImageHandle
+
+ @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid
+ parameter
+ @retval EFI_UNSUPPORTED the input DevicePath does not contain Fv file
+ guild at all
+ @retval EFI_ALREADY_STARTED the input DevicePath has pointed to Fv file, it
+ is valid
+ @retval EFI_SUCCESS has 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) || (*DevicePath == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check whether the device path point to the default the input Fv file
+ //
+ TempDevicePath = *DevicePath;
+ LastDeviceNode = TempDevicePath;
+ while (!EfiIsDevicePathEnd (TempDevicePath)) {
+ LastDeviceNode = TempDevicePath;
+ TempDevicePath = EfiNextDevicePathNode (TempDevicePath);
+ }
+ GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode (
+ (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode
+ );
+ if (GuidPoint == NULL) {
+ //
+ // if this option does not points 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 contain memory map node
+ //
+ TempDevicePath = *DevicePath;
+ HasFVNode = FALSE;
+ while (!EfiIsDevicePathEnd (TempDevicePath)) {
+ //
+ // Use old Device Path
+ //
+ if (DevicePathType (TempDevicePath) == HARDWARE_DEVICE_PATH &&
+ DevicePathSubType (TempDevicePath) == HW_MEMMAP_DP) {
+ HasFVNode = TRUE;
+ break;
+ }
+ TempDevicePath = EfiNextDevicePathNode (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;
+}
+
+
+/**
+ 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.
+ @return 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;
+}
+
+
+/**
+ 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);
+ 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 fail, RemainingDevicepath and handle will not
+ // change, so next time will do the dispatch, then dispatch's status
+ // will take effect
+ // 2. If the connect success, 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;
+}
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index dadf7a698c..f182323a45 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -2,7 +2,7 @@ # Mde Module Package Reference Implementations
#
# This module provides headers and libraries that conform to EFI/PI Industry standards.
-# Copyright (c) 2007, Intel Corporation.
+# Copyright (c) 2007 - 2008, Intel Corporation.
#
# All rights reserved.
# This program and the accompanying materials are licensed and made available under
@@ -33,6 +33,7 @@ UdpIoLib|Include/Library/UdpIoLib.h
S3Lib|Include/Library/S3Lib.h
RecoveryLib|Include/Library/RecoveryLib.h
+ PlatDriOverLib|Include/Library/PlatDriOverLib.h
[Guids.common]
@@ -64,6 +65,7 @@ gEfiPeiPeCoffLoaderGuid = { 0xD8117CFF, 0x94A6, 0x11D4, { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}
gEfiVariableInfoGuid = { 0xddcf3616, 0x3275, 0x4164, { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }}
gSimpleTextInExNotifyGuid = { 0x856f2def, 0x4e93, 0x4d6b, { 0x94, 0xce, 0x1c, 0xfe, 0x47, 0x01, 0x3e, 0xa5 }}
+ gEfiOverrideVariableGuid = { 0x8e3d4ad5, 0xf762, 0x438a, { 0xa1, 0xc1, 0x5b, 0x9f, 0xe6, 0x8c, 0x6b, 0x15 }}
[Protocols.common]
@@ -97,7 +99,7 @@ ##gPeiFlashMapPpiGuid will be removed in future
gPeiFlashMapPpiGuid = { 0xf34c2fa0, 0xde88, 0x4270, {0x84, 0x14, 0x96, 0x12, 0x22, 0xf4, 0x52, 0x1c } }
-
+
gPeiOperatorPresencePpiGuid = { 0x20a7378c, 0xaa83, 0x4ce1, {0x82, 0x1f, 0x47, 0x40, 0xee, 0x1b, 0x3f, 0x9f } }
[PcdsFeatureFlag.common]
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index 5f53c67b2c..637cdfbe80 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -72,6 +72,7 @@ DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+ PlatDriOverLib|MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.inf
[LibraryClasses.IA32]
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
@@ -255,6 +256,8 @@ MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf
MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf
+ MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.inf
+
MdeModulePkg/Library/PeiS3LibNull/PeiS3LibNull.inf
MdeModulePkg/Library/PeiRecoveryLibNull/PeiRecoveryLibNull.inf
@@ -274,6 +277,8 @@ MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf
MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf
+ MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf
+
MdeModulePkg/Application/HelloWorld/HelloWorld.inf
MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverride.c b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverride.c new file mode 100644 index 0000000000..2a189138ed --- /dev/null +++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverride.c @@ -0,0 +1,186 @@ +/** @file
+
+Copyright (c) 2007, 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:
+
+ PlatformDriOverride.c
+
+Abstract:
+
+
+**/
+
+
+#include "PlatformDriOverride.h"
+
+EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL gPlatformDriverOverride = {
+ GetDriver,
+ GetDriverPath,
+ DriverLoaded
+};
+
+STATIC LIST_ENTRY mMappingDataBase = INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase);
+STATIC BOOLEAN mEnvironmentVariableRead = FALSE;
+STATIC EFI_HANDLE mCallerImageHandle;
+
+
+EFI_STATUS
+EFIAPI
+PlatformDriverOverrideEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ Platform Driver Override driver entry point, install the Platform Driver Override Protocol
+
+Arguments:
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
+
+Returns:
+ EFI_STATUS
+
+--*/
+{
+ mEnvironmentVariableRead = FALSE;
+ mCallerImageHandle = ImageHandle;
+ InitializeListHead (&mMappingDataBase);
+ return InstallPlatformDriverOverrideProtocol (&gPlatformDriverOverride);
+}
+
+
+/**
+ 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().
+
+**/
+STATIC
+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 (Status == EFI_NOT_FOUND) {
+ InitializeListHead (&mMappingDataBase);
+ return EFI_NOT_FOUND;
+ } else if (Status == EFI_VOLUME_CORRUPTED){
+ DEBUG ((DEBUG_ERROR, "Platform Driver Override Variable is corrupt\n"));
+ //
+ // The environment variable(s) that contain the override mappings from Controller Device Path to
+ // a set of Driver Device Paths is corrupted, platform code can use LibDeleteOverridesVariables to
+ // delete all orverride variables as a policy. Here can be IBV/OEM customized.
+ //
+
+ //LibDeleteOverridesVariables();
+ InitializeListHead (&mMappingDataBase);
+ return EFI_NOT_FOUND;
+ } else if (EFI_ERROR (Status)){
+ InitializeListHead (&mMappingDataBase);
+ return EFI_NOT_FOUND;
+ }
+ }
+ //
+ // if the environment variable does not exist or the variable appears to be corrupt, just return not found
+ //
+ if (IsListEmpty (&mMappingDataBase)) {
+ return EFI_NOT_FOUND;
+ }
+
+ return GetDriverFromMapping (
+ This,
+ ControllerHandle,
+ DriverImageHandle,
+ &mMappingDataBase,
+ mCallerImageHandle
+ );
+
+}
+
+
+/**
+ For the use of the ControllerHandle parameter in the GetDriverPath() and DriverLoaded() APIs
+ makes those APIs very difficult to use, so not support.
+
+
+
+**/
+STATIC
+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;
+}
+
+
+/**
+ For the use of the ControllerHandle parameter in the GetDriverPath() and DriverLoaded() APIs
+ makes those APIs very difficult to use, so not support.
+
+
+
+**/
+STATIC
+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;
+}
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverride.h b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverride.h new file mode 100644 index 0000000000..5a5b276451 --- /dev/null +++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverride.h @@ -0,0 +1,58 @@ +/** @file + +Copyright (c) 2007, 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: + + PlatformDriOverride.h + +Abstract: + + +**/ + +#ifndef PLATFORM_DRI_OVERRIDE_H_ +#define PLATFORM_DRI_OVERRIDE_H_ + +#include <PiDxe.h> +
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/PlatDriOverLib.h> + +STATIC +EFI_STATUS +EFIAPI +GetDriver ( + IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL * This, + IN EFI_HANDLE ControllerHandle, + IN OUT EFI_HANDLE * DriverImageHandle + ); + +STATIC +EFI_STATUS +EFIAPI +GetDriverPath ( + IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL * This, + IN EFI_HANDLE ControllerHandle, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DriverImagePath + ); + +STATIC +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 + ); +#endif diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf new file mode 100644 index 0000000000..dbc9f0ecb7 --- /dev/null +++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf @@ -0,0 +1,48 @@ +#/** @file
+# Component name for module PlatformDriOverride
+#
+# FIX ME!
+# Copyright (c) 2007, Intel Corporation. All rights reserved.
+#
+# 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.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformDriOverrideDxe
+ FILE_GUID = 35034CE2-A6E5-4fb4-BABE-A0156E9B2549
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = PlatformDriverOverrideEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ PlatformDriOverride.c
+ PlatformDriOverride.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiDriverEntryPoint
+ DebugLib
+ PlatDriOverLib
+
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.msa b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.msa new file mode 100644 index 0000000000..6e1645af35 --- /dev/null +++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.msa @@ -0,0 +1,50 @@ +<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>PlatformDriOverrideDxe</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>35034CE2-A6E5-4fb4-BABE-A0156E9B2549</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component name for module PlatformDriOverride</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>
+ <License>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.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>PlatformDriOverrideDxe</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>PlatformDriOverride.h</Filename>
+ <Filename>PlatformDriOverride.c</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>PlatformDriverOverrideEntry</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
\ No newline at end of file |