Port PlatformDriOverrideDxe into R9.
1. Add one OverrideVariableGuid in MdeModulePkg
2. Add one library PlatDriOverLib used by PlatformDriOverrideDxe.
3. Add PlatformDriOverrideDxe in MdeModulePkg

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4557 6f19259b-4bc3-4df7-8a09-765794883524
diff --git a/MdeModulePkg/Include/Guid/OverrideVariable.h b/MdeModulePkg/Include/Guid/OverrideVariable.h
new file mode 100644
index 0000000..673813a
--- /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 0000000..8e6ab17
--- /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 0000000..1ba2d78
--- /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 0000000..f01088e
--- /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 0000000..331a9bc
--- /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 0000000..d32715b
--- /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 dadf7a6..f182323 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 5f53c67..637cdfb 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 0000000..2a18913
--- /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 0000000..5a5b276
--- /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 0000000..dbc9f0e
--- /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 0000000..6e1645a
--- /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